Personalizar o SELinux

Depois de integrar o nível básico da funcionalidade do SELinux e analisar os resultados, adicione suas próprias configurações de política para abranger as personalizações no sistema operacional Android. Essas políticas ainda precisam atender aos requisitos do Programa de compatibilidade do Android e não podem remover as configurações padrão do SELinux.

Os fabricantes não podem remover a política de SELinux atual. Caso contrário, eles arriscam quebrar a implementação do SELinux do Android e os apps que ele governa. Isso inclui apps de terceiros que provavelmente precisarão ser aprimorados para serem compatíveis e operacionais. Os apps não podem exigir modificações para continuar funcionando em dispositivos com SELinux ativado.

Ao personalizar o SELinux, lembre-se de:

  • Gravar a política do SELinux para todos os novos daemons
  • Use domínios predefinidos sempre que apropriado
  • Atribuir um domínio a qualquer processo gerado como um serviço init
  • Conheça a política de macros antes de escrever
  • Enviar mudanças na política principal para o AOSP

E não faça o seguinte:

  • Criar política incompatível
  • Permitir a personalização da política do usuário final
  • Permitir personalizações de política de MDM
  • Assustar os usuários com violações de políticas
  • Adicionar backdoors

Consulte a seção Recursos de segurança do kernel do documento de definição de compatibilidade do Android para requisitos específicos.

O SELinux usa uma abordagem de lista de permissões, o que significa que todo o acesso precisa ser explicitamente permitido na política para ser concedido. Como a política SELinux padrão do Android já oferece suporte ao Android Open Source Project, não é necessário modificar as configurações do SELinux de nenhuma forma. Se você personalizar as configurações do SELinux, tenha cuidado para não corromper os apps que já existem. Para começar, faça o seguinte:

  1. Use o kernel mais recente do Android.
  2. Adote o princípio do menor privilégio.
  3. Abordar apenas suas próprias adições ao Android. A política padrão funciona com a base de código do Android Open Source Project automaticamente.
  4. Compartimentalizar componentes de software em módulos que realizam tarefas únicas.
  5. Crie políticas do SELinux que isolem essas tarefas de funções não relacionadas.
  6. Coloque essas políticas em arquivos *.te (a extensão para arquivos de origem de política do SELinux) no diretório /device/manufacturer/device-name/sepolicy e use variáveis BOARD_SEPOLICY para incluí-las no seu build.
  7. Torne os novos domínios permissivos inicialmente. Isso é feito usando uma declaração permissiva no arquivo .te do domínio.
  8. Analise os resultados e refine suas definições de domínio.
  9. Remova a declaração permissiva quando nenhuma outra negação aparecer nos builds userdebug.

Depois de integrar a alteração da política do SELinux, adicione uma etapa ao fluxo de trabalho de desenvolvimento para garantir a compatibilidade com o SELinux no futuro. Em um processo ideal de desenvolvimento de software, a política do SELinux muda apenas quando o modelo de software muda, e não a implementação real.

Ao começar a personalizar o SELinux, primeiro audite suas adições no Android. Se você adicionou um componente que executa uma nova função, verifique se ele atende à política de segurança do Android e a qualquer política associada criada pelo OEM antes de ativar o modo de aplicação.

Para evitar problemas desnecessários, é melhor ser muito amplo e compatível do que muito restritivo e incompatível, o que resulta em funções de dispositivo corrompidas. Por outro lado, se as mudanças beneficiarem outras pessoas, envie as modificações para a política SELinux padrão como um patch. Se o patch for aplicado à política de segurança padrão, não será necessário fazer essa mudança em cada nova versão do Android.

Exemplos de declarações de política

O SELinux é baseado na linguagem de computador M4 e, portanto, oferece suporte a várias macros para economizar tempo.

No exemplo a seguir, todos os domínios recebem acesso de leitura ou gravação em /dev/null e leitura de /dev/zero.

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

Essa mesma instrução pode ser escrita com macros *_file_perms do SELinux (abreviatura):

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

Exemplo de política

Veja abaixo um exemplo completo de política para DHCP:

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

Vamos analisar o exemplo:

Na primeira linha, a declaração de tipo, o daemon DHCP herda da política de segurança básica (domain). Com base nos exemplos de instrução anteriores, o DHCP pode ler e gravar em /dev/null.

Na segunda linha, o DHCP é identificado como um domínio permissivo.

Na linha init_daemon_domain(dhcp), a política declara que o DHCP é gerado de init e tem permissão para se comunicar com ele.

Na linha net_domain(dhcp), a política permite que o DHCP use funcionalidades de rede comuns do domínio net, como ler e gravar pacotes TCP, comunicar-se por soquetes e conduzir solicitações DNS.

Na linha allow dhcp proc_net:file write;, a política indica que o DHCP pode gravar em arquivos específicos em /proc. Esta linha demonstra a rotulação refinada de arquivos do SELinux. Ele usa o rótulo proc_net para limitar o acesso de gravação apenas aos arquivos em /proc/sys/net.

O bloco final do exemplo que começa com allow dhcp netd:fd use; mostra como os apps podem interagir entre si. A política diz que o DHCP e o netd podem se comunicar entre si por descritores de arquivos, arquivos FIFO, soquetes de datagrama e soquetes de fluxo UNIX. O DHCP só pode ler e gravar nos soquetes de datagrama e nos soquetes de fluxo do UNIX, e não pode criar nem abrir esses soquetes.

Controles disponíveis

Classe Permissão
arquivo
ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
diretório
add_name remove_name reparent search rmdir open audit_access execmod
soquete
ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
sistema de arquivos
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
Processo
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
segurança
compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
capacidade
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

MAIS

E MAIS

regras de nunca permitir

As regras neverallow do SELinux proíbem comportamentos que nunca devem ocorrer. Com o teste de compatibilidade, as regras neverallow do SELinux agora são aplicadas em todos os dispositivos.

As diretrizes a seguir têm o objetivo de ajudar os fabricantes a evitar erros relacionados às regras neverallow durante a personalização. Os números de regra usados aqui correspondem ao Android 5.1 e estão sujeitos a alterações por versão.

Regra 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
Consulte a página do manual de ptrace. O recurso sys_ptrace concede a capacidade de ptrace qualquer processo, o que permite um grande controle sobre outros processos e deve pertencer apenas a componentes do sistema designados, descritos na regra. A necessidade desse recurso geralmente indica a presença de algo que não se destina a builds voltados ao usuário ou funcionalidades que não são necessárias. Remova o componente desnecessário.

Regra 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
O objetivo desta regra é impedir a execução de código arbitrário no sistema. Especificamente, ele garante que apenas o código em /system seja executado, o que permite garantias de segurança graças a mecanismos como a inicialização verificada. Muitas vezes, a melhor solução ao encontrar um problema com essa regra neverallow é mover o código com problemas para a partição /system.

Personalizar o SEPolicy no Android 8.0 e versões mais recentes

Esta seção apresenta diretrizes para a política SELinux do fornecedor no Android 8.0 e versões mais recentes, incluindo detalhes sobre o Projeto de código aberto do Android (AOSP) SEPolicy e as extensões SEPolicy. Para mais informações sobre como a política do SELinux é mantida compatível com partições e versões do Android, consulte Compatibilidade.

Posicionamento da política

No Android 7.0 e versões anteriores, os fabricantes de dispositivos poderiam adicionar uma política ao BOARD_SEPOLICY_DIRS, incluindo uma política criada para aumentar a política do AOSP em diferentes tipos de dispositivos. No Android 8.0 e versões mais recentes, a adição de uma política a BOARD_SEPOLICY_DIRS coloca a política apenas na imagem do fornecedor.

No Android 8.0 e versões mais recentes, a política existe nos seguintes locais no AOSP:

  • system/sepolicy/public. Inclui a política exportada para uso na política específica do fornecedor. Tudo vai para a infraestrutura de compatibilidade do Android 8.0. A política pública é mantida em todas as versões para que você possa incluir qualquer /public na sua política personalizada. Por isso, o tipo de política que pode ser colocado em /public é mais restrito. Considere essa a API de política exportada da plataforma: tudo o que lida com a interface entre /system e /vendor pertence a esse grupo.
  • system/sepolicy/private. Inclui a política necessária para o funcionamento da imagem do sistema, mas a política de imagem do fornecedor não precisa ter conhecimento.
  • system/sepolicy/vendor. Inclui a política para componentes que vão para /vendor, mas existem na árvore de plataforma principal (não diretórios específicos do dispositivo). Esse é um artefato da distinção entre dispositivos e componentes globais do sistema de build. Conceitos são parte da política específica do dispositivo descrita abaixo.
  • device/manufacturer/device-name/sepolicy. Inclui a política específica do dispositivo. Também inclui personalizações do dispositivo para a política, que no Android 8.0 e versões mais recentes corresponde à política para componentes na imagem do fornecedor.

No Android 11 e versões mais recentes, as partições system_ext e do produto também podem incluir políticas específicas da partição. As políticas system_ext e do produto também são divididas em públicas e privadas, e os fornecedores podem usar as políticas públicas do system_ext e do produto, como a política do sistema.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS. Inclui a política exportada para uso na política específica do fornecedor. Instalado na partição system_ext.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS. Inclui a política necessária para o funcionamento da imagem system_ext, mas da qual a política de imagem do fornecedor não tem conhecimento. Instalado na partição system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS. Inclui a política exportada para uso na política específica do fornecedor. Instalado na partição do produto.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS: inclui a política necessária para o funcionamento da imagem do produto, mas da qual a política de imagem do fornecedor não precisa ter conhecimento. Instalada na partição do produto.
Observação:quando a GSI é usada, as partições system_ext e de produto do OEM não são montadas. As regras na política de segurança do fornecedor que usa o system_ext do OEM e a política pública do produto se tornam NOP porque as definições de tipo específicas do OEM estão ausentes.
Observação:tenha muito cuidado ao usar o system_ext e as políticas públicas de produtos. As políticas públicas funcionam como uma API exportada entre system_ext/product e o fornecedor. Os parceiros precisam gerenciar os problemas de compatibilidade por conta própria.

Cenários de política com suporte

Em dispositivos lançados com o Android 8.0 e versões mais recentes, a imagem do fornecedor precisa funcionar com a imagem do sistema do OEM e a imagem do sistema AOSP de referência fornecida pelo Google (e transmitir o CTS nesta imagem de referência). Esses requisitos garantem uma separação limpa entre o framework e o código do fornecedor. Esses dispositivos são compatíveis com os seguintes cenários.

extensões somente de imagem do fornecedor

Exemplo:adicionar um novo serviço a vndservicemanager na imagem do fornecedor que oferece suporte a processos da imagem do fornecedor.

Como nos dispositivos lançados com versões anteriores do Android, adicione a personalização específica do dispositivo em device/manufacturer/device-name/sepolicy. A nova política que rege como os componentes do fornecedor interagem (apenas) com outros componentes precisa envolver os tipos presentes apenas em device/manufacturer/device-name/sepolicy. A política escrita aqui permite que o código do fornecedor funcione, não será atualizada como parte de um OTA somente de framework e está presente na política combinada em um dispositivo com a imagem de sistema AOSP de referência.

Suporte de imagem do fornecedor para trabalhar com o AOSP

Exemplo:adição de um novo processo (registrado com hwservicemanager da imagem do fornecedor) que implementa um HAL definido pelo AOSP.

Como nos dispositivos lançados com versões anteriores do Android, realize personalizações específicas do dispositivo em device/manufacturer/device-name/sepolicy. A política exportada como parte do system/sepolicy/public/ está disponível para uso e é enviada como parte da política do fornecedor. Os tipos e atributos da política pública podem ser usados em novas regras que ditam as interações com os novos bits específicos do fornecedor, sujeitos às restrições neverallow fornecidas. Assim como no caso exclusivo do fornecedor, a nova política aqui não será atualizada como parte de uma OTA exclusiva do framework e estará presente na política combinada em um dispositivo com a imagem de sistema AOSP de referência.

extensões somente para imagens do sistema

Exemplo:adição de um novo serviço (registrado no servicemanager) que é acessado apenas por outros processos a partir da imagem do sistema.

Adicione essa política a system/sepolicy/private. É possível adicionar processos ou objetos extras para ativar a funcionalidade em uma imagem do sistema do parceiro, desde que esses novos bits não precisem interagir com novos componentes na imagem do fornecedor. Especificamente, esses processos ou objetos precisam funcionar totalmente sem a política da imagem do fornecedor. A política exportada por system/sepolicy/public está disponível aqui, assim como para extensões somente de imagem do fornecedor. Essa política faz parte da imagem do sistema e pode ser atualizada em uma OTA somente de framework, mas não estará presente ao usar a imagem do sistema AOSP de referência.

extensões de imagem do fornecedor que servem componentes estendidos do AOSP

Exemplo:um HAL novo que não é do AOSP para uso por clientes estendidos que também existem na imagem do sistema do AOSP (como um system_server estendido).

A política de interação entre o sistema e o fornecedor precisa ser incluída no diretório device/manufacturer/device-name/sepolicy enviado na partição do fornecedor. Isso é semelhante ao cenário acima de adicionar suporte à imagem do fornecedor para trabalhar com a imagem de referência do AOSP, exceto que os componentes modificados do AOSP também podem requerer uma política adicional para operar corretamente com o restante da partição do sistema (o que é aceitável, desde que eles ainda tenham os rótulos de tipo AOSP público).

A política de interação de componentes públicos do AOSP com extensões somente de imagem do sistema precisa estar em system/sepolicy/private.

extensões de imagem do sistema que acessam apenas interfaces AOSP

Exemplo:um novo processo do sistema não AOSP precisa acessar uma HAL de que o AOSP depende.

Isso é semelhante ao exemplo de extensão somente para imagem do sistema, exceto que novos componentes do sistema podem interagir na interface system/vendor. A política do novo componente do sistema precisa estar em system/sepolicy/private, o que é aceitável, desde que seja por uma interface já estabelecida pelo AOSP em system/sepolicy/public, ou seja, os tipos e atributos necessários para a funcionalidade existem. Embora a política possa ser incluída na política específica do dispositivo, ela não poderia usar outros tipos de system/sepolicy/private ou fazer mudanças (de qualquer maneira que afete a política) como resultado de uma atualização somente de framework. A política pode ser alterada em uma OTA somente de framework, mas não será apresentada ao usar uma imagem do sistema AOSP, que também não terá o novo componente do sistema.

extensões de imagem do fornecedor que servem novos componentes do sistema

Exemplo:adição de um HAL não AOSP para uso por um processo de cliente sem um análogo AOSP (e, portanto, requer o próprio domínio).

Assim como no exemplo de extensões AOSP, a política para interações entre o sistema e o fornecedor precisa ser colocada no diretório device/manufacturer/device-name/sepolicy enviado na partição do fornecedor para garantir que a política do sistema não tenha conhecimento de detalhes específicos do fornecedor. Você pode adicionar novos tipos públicos que estendem a política em system/sepolicy/public. Isso deve ser feito apenas além da política AOSP atual, ou seja, não remova a política pública do AOSP. Os novos tipos públicos podem ser usados para a política em system/sepolicy/private e em device/manufacturer/device-name/sepolicy.

Lembre-se de que cada adição a system/sepolicy/public aumenta a complexidade expondo uma nova garantia de compatibilidade que precisa ser rastreada em um arquivo de mapeamento e que está sujeita a outras restrições. Somente novos tipos e regras de permissão correspondentes podem ser adicionados em system/sepolicy/public. Não há suporte para atributos e outras declarações de política. Além disso, os novos tipos públicos não podem ser usados para rotular objetos diretamente na política /vendor.

Cenários de política sem suporte

Os dispositivos lançados com o Android 8.0 e versões mais recentes não oferecem suporte ao cenário e aos exemplos de política a seguir.

Extensões adicionais à imagem do sistema que precisam de permissão para novos componentes da imagem do fornecedor após uma OTA somente de framework

Exemplo:um novo processo de sistema não AOSP, que exige o próprio domínio, foi adicionado na próxima versão do Android e precisa de acesso a uma nova HAL não AOSP.

Semelhante à interação de novos componentes do sistema e do fornecedor (não AOSP), exceto que o novo tipo de sistema é introduzido em uma OTA somente de framework. Embora o novo tipo possa ser adicionado à política em system/sepolicy/public, a política do fornecedor atual não tem conhecimento do novo tipo, porque está rastreando apenas a política pública do sistema Android 8.0. O AOSP lida com isso expondo recursos fornecidos pelo fornecedor por um atributo (por exemplo, o atributo hal_foo), mas como as extensões de parceiro de atributo não são compatíveis com system/sepolicy/public, esse método não está disponível para a política do fornecedor. O acesso precisa ser fornecido por um tipo público existente anteriormente.

Exemplo:uma mudança em um processo do sistema (AOSP ou não AOSP) precisa mudar a forma como ele interage com o novo componente do fornecedor que não é do AOSP.

A política na imagem do sistema precisa ser escrita sem o conhecimento de personalizações específicas do fornecedor. A política relacionada a interfaces específicas no AOSP é exposta por atributos em system/sepolicy/public para que a política do fornecedor possa ser ativada para uma política de sistema futura que use esses atributos. No entanto, não há suporte para extensões de atributo em system/sepolicy/public. Portanto, todas as políticas que determinam como os componentes do sistema interagem com novos componentes do fornecedor (e que não são processadas por atributos já presentes no AOSP system/sepolicy/public) precisam estar em device/manufacturer/device-name/sepolicy. Isso significa que os tipos de sistema não podem mudar o acesso permitido aos tipos de fornecedores como parte de uma OTA somente de framework.