Construindo Política SELinux

Este artigo aborda como a política SELinux é construída. A política SELinux é construída a partir da combinação da política central AOSP (plataforma) e da política específica do dispositivo (fornecedor). O fluxo de construção da política SELinux para Android 4.4 até Android 7.0 mesclou todos os fragmentos da sepolicy e gerou 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) sempre que a política era modificada.

No Android 8.0 e versões posteriores, a política de plataforma e de fornecedor é criada separadamente. SOCs e OEMs podem atualizar suas partes da política, criar suas imagens (como vendor.img e boot.img ) e, em seguida, 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 mais cedo 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 em 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 políticas e rótulos SELinux.
    • external/selinux/libselinux : o Android usa apenas um subconjunto do projeto externo libselinux junto com algumas personalizações específicas do Android. Para obter detalhes, consulte external/selinux/README.android .
    • external/selinux/libsepol :
      • chkcon : Determine se um contexto de segurança é válido para uma determinada política binária (executável de host).
      • libsepol : biblioteca SELinux para manipulação de políticas de segurança binárias (biblioteca hospedeira estática/compartilhada, biblioteca estática de destino).
    • external/selinux/checkpolicy : compilador de políticas SELinux (executáveis ​​de host: checkpolicy , checkmodule e dispol ). Depende da libsepol .
  • system/sepolicy : configurações principais de políticas do Android SELinux, incluindo contextos e arquivos de políticas. A principal lógica de construção da sepolicy também está aqui ( system/sepolicy/Android.mk ).

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

Android 7.0 e anteriores

Esta seção aborda como a política SELinux é criada no Android 7.x e versões anteriores.

Construindo política SELinux

A política SELinux é criada combinando a política AOSP principal 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 por meio 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íticas 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 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 construção do SELinux para Android 7.x.
Figura 1 . Lógica de construçã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 , *.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 executando 7.xe versões anteriores geralmente contêm os seguintes arquivos relacionados ao SELinux:

  • selinux_version
  • sepolicy: saída binária após combinar 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 SELinux

Quando o sistema é inicializado, o SELinux está no modo permissivo (e não no modo obrigatório). O processo init executa as seguintes tarefas:

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

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

Android 8.0 e superior

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

A sepolicy da plataforma é ainda dividida em partes de plataforma privada e de plataforma pública para exportar tipos e atributos específicos para redatores de políticas de fornecedores. É garantido que os tipos/atributos públicos da plataforma sejam mantidos como APIs estáveis ​​para uma determinada versão da plataforma. A compatibilidade com tipos/atributos públicos de plataformas anteriores pode ser garantida para diversas versões usando arquivos de mapeamento de plataforma.

Política pública de plataforma

A plataforma public sepolicy inclui tudo definido em system/sepolicy/public . A plataforma pode assumir que os tipos e atributos definidos na política pública são APIs estáveis ​​para uma determinada versão da plataforma. Isso forma a 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 compilação PLATFORM_SEPOLICY_VERSION . A política pública versionada é 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 da plataforma privada, a política pública da plataforma atual, a política específica do dispositivo e a política pública versionada correspondente à versão da plataforma contra a qual a política do dispositivo foi escrita.

Política privada de plataforma

A plataforma private sepolicy inclui tudo definido em /system/sepolicy/private . Esta parte da política forma tipos, permissões e atributos exclusivos da plataforma necessários para a funcionalidade da plataforma. Eles não são exportados para os criadores de políticas vendor/device . Os redatores de políticas fora da plataforma não devem escrever suas extensões de política com base em tipos/atributos/regras definidos na política privada da plataforma. Além disso, estas regras podem ser modificadas ou podem desaparecer como parte de uma atualização apenas do quadro.

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 das versões anteriores da política pública da plataforma 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 anterior da plataforma da qual se espera que esta 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 foram adicionadas. Assim como a plataforma sepolicy, a política system_ext e a política de produto são divididas em políticas públicas e políticas privadas.

A política pública é exportada para o fornecedor. Tipos e atributos tornam-se APIs estáveis, e a política do fornecedor pode referir-se 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 system_ext e produto.

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

system_ext e mapeamento de produto

system_ext e product têm permissão para 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 versionados 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, em seguida, 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, em seguida, adicione product_{ver}.cil a PRODUCT_PACKAGES .
  • Consulte um exemplo que adiciona um arquivo de mapeamento da partição do produto do dispositivo redbull.

    Construindo política SELinux

    A política SELinux no Android 8.0 é feita combinando peças 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 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 desejarem)
    BOARD_SEPOLICY_DIRS Política de segurança do fornecedor
    BOARD_ODM_SEPOLICY_DIRS (Android 9 e superior) Política Odm
    SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 e superior) API 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 sepolicy do produto
    PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 e superior) Detalhes de implementação do produto (os fornecedores podem ignorar)

    O sistema de construção utiliza esta política e produz componentes de sistema, system_ext, produto, fornecedor e política 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 combinada privada + pública
      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ública + fornecedor + BOARD_SEPOLICY_DIRS sobre quais partes devem ser transformadas em atributos que serão vinculados à política da plataforma.
    3. Criação de um arquivo de mapeamento vinculando a plataforma e as peças do fornecedor. Inicialmente, isso apenas vincula os tipos da política pública aos atributos correspondentes na política do fornecedor; posteriormente, também fornecerá a base para o arquivo mantido em futuras versões da plataforma, permitindo a compatibilidade com a política do fornecedor direcionada a esta versão da plataforma.
    4. Combinação de arquivos de políticas (descreve soluções pré-compiladas e no dispositivo).
      1. Combine mapeamento, plataforma e política de fornecedor.
      2. Compile o arquivo de política binária de saída.

    Política SELinux pré-compilada

    Antes init ativar o SELinux, init reúne todos os arquivos CIL das partições ( system , system_ext , product , vendor e odm ) e os compila na política binária, o formato que pode ser carregado no kernel. Como a compilação leva tempo (geralmente de 1 a 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, init verifica se algum arquivo de política foi atualizado comparando os hashes. Se nada mudou, init carrega a política pré-compilada. Caso contrário, init compila instantaneamente e o utiliza em vez do pré-compilado.

    Mais especificamente, a política pré-compilada será 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, init retornará ao caminho de compilação no dispositivo. Consulte system/core/init/selinux.cpp para obter mais detalhes.