Personalizando o SELinux

Depois de integrar o nível básico da funcionalidade do SELinux e analisar minuciosamente os resultados, você poderá adicionar suas próprias configurações de política para cobrir suas personalizações no sistema operacional Android. Essas políticas ainda devem atender aos requisitos do programa de compatibilidade do Android e não devem remover as configurações padrão do SELinux.

Os fabricantes não devem remover a política SELinux existente. Caso contrário, correm o risco de quebrar a implementação do Android SELinux e as aplicações que ela controla. Isso inclui aplicativos de terceiros que provavelmente precisarão ser aprimorados para estarem em conformidade e operacionais. Os aplicativos não devem exigir nenhuma modificação para continuar funcionando em dispositivos habilitados para SELinux.

Ao embarcar na personalização do SELinux, lembre-se de:

  • Escreva a política SELinux para todos os novos daemons
  • Use domínios predefinidos sempre que apropriado
  • Atribua um domínio a qualquer processo gerado como um serviço init
  • Familiarize-se com as macros antes de escrever a política
  • Enviar alterações na política principal ao AOSP

E lembre-se de não:

  • Criar política incompatível
  • Permitir personalização da política do usuário final
  • Permitir personalizações de políticas 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 Definição de compatibilidade do Android para requisitos específicos.

O SELinux usa uma abordagem de lista branca, o que significa que todo acesso deve ser explicitamente permitido na política para ser concedido. Como a política SELinux padrão do Android já suporta o Android Open Source Project, você não é obrigado a modificar as configurações do SELinux de forma alguma. Se você personalizar as configurações do SELinux, tome muito cuidado para não quebrar os aplicativos existentes. Para começar:

  1. Use o kernel Android mais recente .
  2. Adote o princípio do menor privilégio .
  3. Aborde apenas suas próprias adições ao Android. A política padrão funciona automaticamente com a base de código do Android Open Source Project .
  4. Compartimentalize os componentes de software em módulos que realizam tarefas singulares.
  5. Crie políticas SELinux que isolem essas tarefas de funções não relacionadas.
  6. Coloque essas políticas em arquivos *.te (a extensão dos arquivos de origem de políticas do SELinux) no diretório /device/ manufacturer / device-name /sepolicy e use as variáveis BOARD_SEPOLICY para incluí-las em sua compilação.
  7. Torne 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 nas compilações do userdebug.

Depois de integrar a alteração da política do SELinux, adicione uma etapa ao seu fluxo de trabalho de desenvolvimento para garantir a compatibilidade do 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 ao Android. Se você adicionou um componente que executa uma nova função, certifique-se de que o componente atenda à política de segurança do Android, bem como a qualquer política associada criada pelo OEM, antes de ativar o modo de aplicação.

Para evitar problemas desnecessários, é melhor ser excessivamente amplo e compatível do que muito restritivo e incompatível, o que resulta em funções do dispositivo interrompidas. Por outro lado, se suas alterações beneficiarem outras pessoas, você deverá enviar as modificações na política padrão do SELinux como um patch . Se o patch for aplicado à política de segurança padrão, você não precisará fazer essa alteração a cada nova versão do Android.

Exemplos de declarações de política

SELinux é baseado na linguagem de computador M4 e, portanto, suporta uma variedade de macros para economizar tempo.

No exemplo a seguir, todos os domínios recebem acesso para leitura ou gravação em /dev/null e leitura em /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 };

Esta mesma instrução pode ser escrita com macros SELinux *_file_perms (abreviação):

# 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;

Política de exemplo

Aqui está um exemplo completo de política para DHCP, que examinamos abaixo:

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 dissecar o exemplo:

Na primeira linha, a declaração de tipo, o daemon DHCP herda da política de segurança base ( domain ). Dos exemplos de instruções 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 afirma que o DHCP é gerado a partir 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 leitura e gravação de pacotes TCP, comunicação por soquetes e condução de solicitações DNS.

Na linha allow dhcp proc_net:file write; , a política afirma que o DHCP pode gravar em arquivos específicos em /proc . Esta linha demonstra a rotulagem 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 começando com allow dhcp netd:fd use; descreve como os aplicativos podem interagir uns com os outros. A política diz que DHCP e netd podem se comunicar entre si por meio de descritores de arquivos, arquivos FIFO, soquetes de datagramas e soquetes de fluxo UNIX. O DHCP só pode ler e gravar nos soquetes de datagrama e soquetes de fluxo UNIX e não criá-los ou abri-los.

Controles disponíveis

Aula 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 arquivo
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 nunca permitir

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

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

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

Regra 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
Esta regra tem como objetivo impedir a execução de código arbitrário no sistema. Especificamente, afirma que apenas o código em /system é executado, o que permite garantias de segurança graças a mecanismos como inicialização verificada. Freqüentemente, a melhor solução ao encontrar um problema com esta regra neverallow é mover o código incorreto para a partição /system .

Personalizando SEPolicy no Android 8.0+

Esta seção fornece diretrizes para a política SELinux do fornecedor no Android 8.0 e superior, incluindo detalhes sobre SEPolicy e extensões SEPolicy do Android Open Source Project (AOSP). Para obter mais informações sobre como a política SELinux é mantida compatível entre partições e versões do Android, consulte Compatibilidade .

Colocação de política

No Android 7.0 e versões anteriores, os fabricantes de dispositivos podiam adicionar políticas a BOARD_SEPOLICY_DIRS , incluindo políticas destinadas a aumentar a política AOSP em diferentes tipos de dispositivos. No Android 8.0 e versões posteriores, adicionar uma política a BOARD_SEPOLICY_DIRS coloca a política apenas na imagem do fornecedor.

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

  • sistema/sepolicy/público . Inclui política exportada para uso em políticas específicas do fornecedor. Tudo vai para a infraestrutura de compatibilidade do Android 8.0. A política pública deve persistir entre as versões para que você possa incluir qualquer coisa /public na sua política personalizada. Por conta disso, o tipo de política que pode ser colocada em /public é mais restrito. Considere isto a API de política exportada da plataforma: qualquer coisa que lide com a interface entre /system e /vendor pertence aqui.
  • sistema/sepolicy/privado . Inclui a política necessária para o funcionamento da imagem do sistema, mas da qual a política de imagem do fornecedor não deve ter conhecimento.
  • sistema/sepolicy/vendor . Inclui política para componentes que vão em /vendor , mas existem na árvore principal da plataforma (não em diretórios específicos do dispositivo). Este é um artefato da distinção do sistema de construção entre dispositivos e componentes globais; conceitualmente, isso faz parte da política específica do dispositivo descrita abaixo.
  • dispositivo/ manufacturer / device-name /sepolicy . Inclui política específica do dispositivo. Também inclui personalizações de dispositivos de acordo com a política, que no Android 8.0 e versões posteriores corresponde à política para componentes na imagem do fornecedor.

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

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS . Inclui política exportada para uso em políticas específicas 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 deve ter conhecimento. Instalado na partição system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS . Inclui política exportada para uso em políticas específicas do fornecedor. Instalado na partição do produto.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS . Inclui política necessária para o funcionamento da imagem do produto, mas da qual a política de imagem do fornecedor não deveria ter conhecimento. Instalado na partição do produto.
Nota: quando GSI é usado, as partições system_ext e de produto do OEM não serão montadas. As regras na sepolicy do fornecedor que usa o system_ext do OEM e a política pública do produto tornam-se NOP porque faltam as definições de tipo específicas do OEM.
Nota: Tenha cuidado extra ao usar políticas públicas system_ext e de produto. As políticas públicas atuam como API exportada entre system_ext/product e fornecedor. Os parceiros devem gerenciar eles próprios os problemas de compatibilidade.

Cenários de política suportados

Em dispositivos com Android 8.0 e superior, a imagem do fornecedor precisa funcionar com a imagem do sistema OEM e a imagem de referência do sistema AOSP fornecida pelo Google (e passar no CTS nesta imagem de referência). Esses requisitos garantem uma separação clara entre a estrutura e o código do fornecedor. Esses dispositivos suportam os seguintes cenários.

extensões somente de imagem do fornecedor

Exemplo : Adicionar um novo serviço ao vndservicemanager da imagem do fornecedor que suporta processos da imagem do fornecedor.

Assim como acontece com os 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 com (apenas) componentes de outros fornecedores deve envolver 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á atualizado como parte de um OTA somente de estrutura e estará presente na política combinada em um dispositivo com a imagem do sistema AOSP de referência.

suporte de imagem do fornecedor para trabalhar com AOSP

Exemplo : Adicionar um novo processo (registrado com hwservicemanager da imagem do fornecedor) que implementa um HAL definido por AOSP.

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

extensões somente de imagem do sistema

Exemplo : Adicionando um novo serviço (cadastrado no servicemanager) que é acessado apenas por outros processos da imagem do sistema.

Adicione esta política a system/sepolicy/private . Você pode adicionar processos ou objetos extras para ativar a funcionalidade em uma imagem de sistema parceiro, desde que esses novos bits não precisem interagir com novos componentes na imagem do fornecedor (especificamente, tais processos ou objetos devem funcionar totalmente sem 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. Esta política faz parte da imagem do sistema e pode ser atualizada apenas em uma estrutura OTA, mas não estará presente ao usar a imagem de referência do sistema AOSP.

extensões de imagem de fornecedor que atendem componentes AOSP estendidos

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

A política para interação entre o sistema e o fornecedor deve ser incluída no diretório device/ manufacturer / device-name /sepolicy fornecido na partição do fornecedor. Isto é semelhante ao cenário acima de adicionar suporte à imagem do fornecedor para trabalhar com a imagem AOSP de referência, exceto que os componentes AOSP modificados também podem exigir política adicional para operar adequadamente com o resto da partição do sistema (o que é bom, desde que ainda possuem rótulos de tipo AOSP públicos).

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

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

Exemplo: Um novo processo de sistema não AOSP deve acessar um HAL do qual o AOSP depende.

Isso é semelhante ao exemplo de extensão somente imagem do sistema , exceto que novos componentes do sistema podem interagir na interface system/vendor . A política para o novo componente do sistema deve entrar em system/sepolicy/private , o que é aceitável desde que seja através de uma interface já estabelecida pelo AOSP em system/sepolicy/public (ou seja, os tipos e atributos necessários para a funcionalidade estejam lá). Embora a política possa ser incluída na política específica do dispositivo, ela não poderá usar outros tipos system/sepolicy/private ou alterar (de qualquer forma que afete a política) como resultado de uma atualização apenas da estrutura. A política pode ser alterada em um OTA somente de estrutura, mas não estará presente ao usar uma imagem de sistema AOSP (que também não terá o novo componente de sistema).

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

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

Semelhante ao exemplo de extensões AOSP , a política para interações entre o sistema e o fornecedor deve estar 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 ; isto deve ser feito apenas em adição à política AOSP existente, ou seja, não remover a política pública AOSP. Os novos tipos públicos podem então ser usados ​​para políticas em system/sepolicy/private e em device/ manufacturer / device-name /sepolicy .

Tenha em mente que cada adição a system/sepolicy/public adiciona complexidade ao expor uma nova garantia de compatibilidade que deve ser rastreada em um arquivo de mapeamento e que está sujeita a outras restrições. Apenas novos tipos e regras de permissão correspondentes podem ser adicionados em system/sepolicy/public ; atributos e outras declarações de política não são suportados. Além disso, novos tipos públicos não podem ser usados ​​para rotular objetos diretamente na política /vendor .

Cenários de política não suportados

Os dispositivos lançados com Android 8.0 e versões posteriores não são compatíveis com o cenário e os exemplos de política a seguir.

Extensões adicionais para imagem do sistema que precisam de permissão para novos componentes de imagem do fornecedor após um OTA somente de estrutura

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

Semelhante à interação do novo sistema (não AOSP) e dos componentes do fornecedor , exceto que o novo tipo de sistema é introduzido em uma OTA somente de estrutura. Embora o novo tipo possa ser adicionado à política em system/sepolicy/public , a política do fornecedor existente não tem conhecimento do novo tipo, pois rastreia apenas a política pública do sistema Android 8.0. O AOSP lida com isso expondo recursos fornecidos pelo fornecedor por meio de um atributo (por exemplo, atributo hal_foo ), mas como extensões de parceiros de atributos não são suportadas em system/sepolicy/public , esse método não está disponível para a política do fornecedor. O acesso deve ser fornecido por um tipo público previamente existente.

Exemplo: Uma alteração em um processo do sistema (AOSP ou não AOSP) deve alterar a forma como ele interage com o novo componente do fornecedor não AOSP.

A política na imagem do sistema deve ser escrita sem conhecimento de personalizações específicas do fornecedor. A política relativa a interfaces específicas no AOSP é, portanto, exposta por meio de atributos em system/sepolicy/public para que a política do fornecedor possa aceitar futuras políticas do sistema que utilizem esses atributos. No entanto, extensões de atributos em system/sepolicy/public não são suportadas , portanto, todas as políticas que determinam como os componentes do sistema interagem com os componentes do novo fornecedor (e que não são tratadas por atributos já presentes em AOSP system/sepolicy/public ) devem estar em device/ manufacturer / device-name /sepolicy . Isso significa que os tipos de sistema não podem alterar o acesso permitido aos tipos de fornecedores como parte de uma OTA somente de estrutura.