Criando a Política SELinux

Este artigo aborda como a política do SELinux é construída. A política do SELinux é construída a partir da combinação da política principal do AOSP (plataforma) e da política específica do dispositivo (fornecedor). O fluxo de compilação da política SELinux para Android 4.4 a Android 7.0 mesclava todos os fragmentos de sepolicy e gerava arquivos monolíticos no diretório raiz. Isso significava que os fornecedores de SoC e fabricantes de ODM modificavam boot.img (para dispositivos não A/B) ou system.img (para dispositivos A/B) toda vez que a política era modificada.

No Android 8.0 e superior, a política de plataforma e fornecedor é criada separadamente. SOCs e OEMs podem atualizar suas partes da política, criar suas imagens (como vendor.img e boot.img ) e atualizar essas imagens independentemente das atualizações da plataforma.

No entanto, como os arquivos de política SELinux modularizados são armazenados em partições /vendor , o processo init deve montar as partições do sistema e do fornecedor antes para que possa ler os arquivos SELinux dessas partições e mesclá-los com os arquivos principais do SELinux no diretório do sistema (antes de carregá-los no o núcleo).

Arquivos Fonte

A lógica para construir o SELinux está nestes arquivos:

  • external/selinux : Projeto SELinux externo, usado para construir utilitários de linha de comando HOST para compilar a política e os rótulos do SELinux.
    • external/selinux/libselinux : o Android usa apenas um subconjunto do projeto libselinux externo junto com algumas personalizações específicas do Android. Para obter detalhes, consulte external/selinux/README.android .
    • external/selinux/libsepol :
      • chkcon : Determina se um contexto de segurança é válido para uma determinada política binária (executável do host).
      • libsepol : Biblioteca SELinux para manipular políticas de segurança binária (biblioteca estática/compartilhada do host, biblioteca estática de destino).
    • external/selinux/checkpolicy : compilador de política SELinux (executáveis ​​do host: checkpolicy , checkmodule e dispol ). Depende de libsepol .
  • system/sepolicy : configurações principais de política do Android SELinux, incluindo contextos e arquivos de política. A lógica principal de compilação de sepolicy também está aqui ( system/sepolicy/Android.mk ).

Para mais detalhes sobre os arquivos em system/sepolicy Implementando o SELinux .

Android 7.0 e anteriores

Esta seção aborda como a política SELinux é criada no Android 7.xe anterior.

Criando a política do SELinux

A política SELinux é criada combinando a política principal do AOSP com personalizações específicas do dispositivo. A política combinada é então passada para o compilador de políticas e vários verificadores. A personalização específica do dispositivo é feita através da variável BOARD_SEPOLICY_DIRS definida no arquivo Boardconfig.mk específico do dispositivo. Essa variável de construção global contém uma lista de diretórios que especificam a ordem na qual procurar arquivos de política adicionais.

Por exemplo, um fornecedor de SoC e um ODM podem adicionar um diretório, um para as configurações específicas do SoC e outro para as configurações específicas do dispositivo, para gerar as configurações finais do SELinux para um determinado dispositivo:

  • BOARD_SEPOLICY_DIRS += device/ SOC /common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/ SoC / DEVICE /sepolicy

O conteúdo dos arquivos file_contexts em system/sepolicy e BOARD_SEPOLICY_DIRS são concatenados para gerar o file_contexts.bin no dispositivo:

Esta imagem mostra a lógica de compilação do SELinux para o Android 7.x.
Figura 1 . Lógica de compilação do SELinux

O arquivo sepolicy consiste em vários arquivos de origem:

  • O policy.conf de texto simples é gerado concatenando security_classes , initial_sids , arquivos *.te , genfs_contexts e port_contexts nessa ordem.
  • Para cada arquivo (como security_classes ), seu conteúdo é a concatenação dos arquivos com o mesmo nome em system/sepolicy/ e BOARDS_SEPOLICY_DIRS .
  • O policy.conf é enviado ao compilador SELinux para verificação de sintaxe e compilado em formato binário como sepolicy no dispositivo.
    Esta imagem mostra os arquivos que geram o arquivo de política SELinux para Android 7.x.
    Figura 2 . arquivo de política SELinux

Arquivos SELinux

Após a compilação, os dispositivos Android com versão 7.xe anteriores normalmente contêm os seguintes arquivos relacionados ao SELinux:

  • selinux_version
  • sepolicy: saída binária após a combinação de arquivos de política (como security_classes , initial_sids e *.te )
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Para obter mais detalhes, consulte Implementando o SELinux .

Inicialização do SELinux

Quando o sistema inicializa, o SELinux está no modo permissivo (e não no modo de imposição). O processo init executa as seguintes tarefas:

  • Carrega arquivos de sepolicy do ramdisk no kernel por meio de /sys/fs/selinux/load .
  • Muda o SELinux para o modo de imposição.
  • Executa re-exec() para aplicar a regra de domínio SELinux a si mesmo.

Para diminuir o tempo de inicialização, execute o re-exec() no processo de init o mais rápido possível.

Android 8.0 e superior

No Android 8.0, a política do SELinux é dividida em componentes de plataforma e fornecedor para permitir atualizações independentes de política de plataforma/fornecedor, mantendo a compatibilidade.

A política de segurança da plataforma é dividida em partes privadas da plataforma e partes públicas da plataforma para exportar tipos e atributos específicos para os criadores de políticas do fornecedor. Os tipos/atributos públicos da plataforma são mantidos como APIs estáveis ​​para uma determinada versão da plataforma. A compatibilidade com tipos/atributos públicos da plataforma anterior pode ser garantida para várias versões usando arquivos de mapeamento de plataforma.

Política de segurança pública da plataforma

A política de segurança pública da plataforma inclui tudo definido em system/sepolicy/public . A plataforma pode assumir que os tipos e atributos definidos nas políticas públicas são APIs estáveis ​​para uma determinada versão da plataforma. Isso faz parte da sepolicy que é exportada pela plataforma na qual os desenvolvedores de políticas do fornecedor (ou seja, do dispositivo) podem escrever políticas adicionais específicas do dispositivo.

Os tipos são versionados de acordo com a versão da política na qual os arquivos do fornecedor são gravados, definida pela variável de construção PLATFORM_SEPOLICY_VERSION . A política pública com versão é então incluída na política do fornecedor e (em sua forma original) na política da plataforma. Assim, a política final inclui a política de plataforma privada, a política de segurança pública da plataforma atual, a política específica do dispositivo e a política pública versionada correspondente à versão da plataforma na qual a política do dispositivo foi escrita.

Sepolicy privado da plataforma

A política de segurança privada da plataforma inclui tudo definido em /system/sepolicy/private . Essa parte da política forma tipos, permissões e atributos somente de plataforma necessários para a funcionalidade da plataforma. Eles não são exportados para os escritores de política de vendor/device . Os criadores de políticas que não são de plataforma não devem gravar suas extensões de política com base em tipos/atributos/regras definidas na sepolicy privada da plataforma. Além disso, essas regras podem ser modificadas ou podem desaparecer como parte de uma atualização somente da estrutura.

Mapeamento privado da plataforma

O mapeamento privado da plataforma inclui declarações de política que mapeiam os atributos expostos na política pública da plataforma das versões anteriores da plataforma para os tipos concretos usados ​​na política pública da plataforma atual. Isso garante que a política do fornecedor que foi escrita com base nos atributos públicos da plataforma da(s) versão(ões) de política pública da plataforma anterior continue funcionando. O controle de versão é baseado na variável de construção PLATFORM_SEPOLICY_VERSION definida no AOSP para uma determinada versão da plataforma. Existe um arquivo de mapeamento separado para cada versão de plataforma anterior da qual se espera que essa plataforma aceite a política do fornecedor. Para obter mais detalhes, consulte Compatibilidade .

Android 11 e superior

system_ext e sepolicy do produto

No Android 11, a política system_ext e a política do produto são adicionadas. Assim como a sepolicy da plataforma, a política system_ext e a política do produto são divididas em política pública e política privada.

A política pública é exportada para o fornecedor. Tipos e atributos se tornam APIs estáveis, e a política do fornecedor pode se referir a tipos e atributos na política pública. Os tipos são versionados de acordo com PLATFORM_SEPOLICY_VERSION e a política versionada é incluída na política do fornecedor. A política original está incluída em cada partição do system_ext e do produto.

A política privada contém tipos, permissões e atributos somente system_ext e somente produto, necessários para a funcionalidade das partições system_ext e do produto. A política privada é invisível para o fornecedor, o que implica que essas regras são internas e podem ser modificadas.

system_ext e mapeamento de produtos

system_ext e product podem exportar seus tipos públicos designados para o fornecedor. No entanto, a responsabilidade de manter a compatibilidade é de cada parceiro. Para compatibilidade, os parceiros podem fornecer seus próprios arquivos de mapeamento que mapeiam os atributos de versão de versões anteriores para tipos concretos usados ​​na política pública atual.

  • Para instalar um arquivo de mapeamento para system_ext, coloque um arquivo cil contendo as informações de mapeamento desejadas em {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil e adicione system_ext_{ver}.cil a PRODUCT_PACKAGES .
  • Para instalar um arquivo de mapeamento para o produto, coloque um arquivo cil contendo as informações de mapeamento desejadas em {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil e adicione product_{ver}.cil a PRODUCT_PACKAGES .
  • Consulte um exemplo que adiciona um arquivo de mapeamento da partição do produto do dispositivo redbull.

    Criando a política do SELinux

    A política do SELinux no Android 8.0 é feita combinando partes de /system e /vendor . A lógica para configurar isso adequadamente está em /platform/system/sepolicy/Android.mk .

    A política existe nos seguintes locais:

    Localização Contém
    system/sepolicy/public API de sepolicy da plataforma
    system/sepolicy/private Detalhes de implementação da plataforma (os fornecedores podem ignorar)
    system/sepolicy/vendor Arquivos de política e contexto que os fornecedores podem usar (os fornecedores podem ignorar, se desejar)
    BOARD_SEPOLICY_DIRS Política de segurança do fornecedor
    BOARD_ODM_SEPOLICY_DIRS (Android 9 e superior) Sepolicy Odm
    SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 e superior) API de sepolicy do System_ext
    SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 e superior) Detalhes de implementação do System_ext (os fornecedores podem ignorar)
    PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 e superior) API de sepolicy do produto
    PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 e superior) Detalhes de implementação do produto (os fornecedores podem ignorar)

    O sistema de compilação usa essa política e produz componentes de política system, system_ext, product, vendor e odm na partição correspondente. As etapas incluem:

    1. Convertendo políticas para o formato SELinux Common Intermediate Language (CIL), especificamente:
      1. política de plataforma pública (sistema + system_ext + produto)
      2. política privada + pública combinada
      3. política pública + fornecedor e BOARD_SEPOLICY_DIRS
    2. Controle de versão da política fornecida pelo público como parte da política do fornecedor. Feito usando a política CIL pública produzida para informar a política combinada público + fornecedor + BOARD_SEPOLICY_DIRS sobre quais partes devem ser transformadas em atributos que serão vinculados à política da plataforma.
    3. Criando um arquivo de mapeamento ligando a plataforma e as partes do fornecedor. Inicialmente, isso apenas vincula os tipos da política pública com os atributos correspondentes na política do fornecedor; posteriormente, também fornecerá a base para o arquivo mantido em versões futuras da plataforma, permitindo a compatibilidade com a política do fornecedor direcionada a essa versão da plataforma.
    4. Combinando arquivos de política (descreva soluções no dispositivo e pré-compiladas).
      1. Combine mapeamento, plataforma e política de fornecedores.
      2. Compile o arquivo de política binária de saída.

    Política SELinux pré-compilada

    Antes do init init SELinux, ele reúne todos os arquivos CIL das partições ( system , system_ext , product , vendor e odm ) e os compila em política binária, o formato que pode ser carregado no kernel. Como a compilação leva tempo (geralmente 1-2 segundos), os arquivos CIL são pré-compilados no momento da compilação e colocados em /vendor/etc/selinux/precompiled_sepolicy ou /odm/etc/selinux/precompiled_sepolicy , junto com os hashes sha256 dos arquivos CIL de entrada. Em tempo de execução, o init verifica se algum arquivo de política foi atualizado comparando os hashes. Se nada mudou, o init carrega a política pré-compilada. Caso contrário, o init compila em tempo real e o usa em vez do pré-compilado.

    Mais especificamente, a política pré-compilada é usada se todas as condições a seguir forem atendidas. Aqui, {partition} representa a partição onde existe a política pré-compilada: vendor ou odm .

    • Ambos /system/etc/selinux/plat_sepolicy_and_mapping.sha256 e /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 existem e são idênticos.
    • Ambos /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 e /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 não existem. Ou ambos existem e são idênticos.
    • Ambos /product/etc/selinux/product_sepolicy_and_mapping.sha256 e /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 não existem. Ou ambos existem e são idênticos.

    Se algum deles for diferente, o init retornará ao caminho de compilação no dispositivo. Veja system/core/init/selinux.cpp para mais detalhes.