Personalizando o SELinux

Depois de integrar o nível básico da funcionalidade do SELinux e analisar minuciosamente os resultados, você pode 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, eles correm o risco de quebrar a implementação do Android SELinux e os aplicativos que ele governa. Isso inclui aplicativos de terceiros que provavelmente precisarão ser aprimorados para serem compatíveis 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 de init
  • Familiarize-se com as macros antes de escrever a política
  • Envie as alterações da política principal ao AOSP

E lembre-se de não:

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

Consulte a seção Recursos de segurança do kernel do documento Definição de compatibilidade do Android para obter 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á oferece suporte ao Android Open Source Project, não é necessário 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 privilégio mínimo .
  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 isolam 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íticas SELinux) dentro do diretório /device/ manufacturer / device-name /sepolicy e use as variáveis BOARD_SEPOLICY para incluí-las em sua compilação.
  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 negação adicional aparecer nas compilações do 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 do SELinux no futuro. Em um processo de desenvolvimento de software ideal, 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 realiza uma nova função, verifique se o componente atende à política de segurança do Android, bem como a qualquer política associada criada pelo OEM, antes de ativar o modo de imposiçã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 do dispositivo quebradas. Por outro lado, se suas alterações beneficiarem outras pessoas, você deve enviar as modificações para a 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

O 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 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 };

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 básica ( 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 do init e tem permissão para se comunicar com ele.

Na linha net_domain(dhcp) , a política permite que o DHCP use a funcionalidade de rede comum do domínio de net , como leitura e gravação de pacotes TCP, comunicação por meio de soquetes e realização de solicitações de 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 rotulagem de arquivo refinada 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 arquivo, arquivos FIFO, soquetes de datagrama 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

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 arquivo
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
processar
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 SELinux proíbem comportamentos que nunca deveriam ocorrer. Com o teste de compatibilidade , as regras neverallow SELinux agora são aplicadas em todos os dispositivos.

As diretrizes a seguir destinam-se a ajudar os fabricantes a evitar erros relacionados a regras de neverallow durante a personalização. Os números de regras 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;
Veja a página man para ptrace . O recurso sys_ptrace concede a capacidade de ptrace de qualquer processo, o que permite um grande controle sobre outros processos e deve pertencer apenas aos componentes do sistema designados, 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 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 destina-se a evitar a execução de código arbitrário no sistema. Especificamente, ele afirma que apenas o código em /system é executado, o que permite garantias de segurança graças a mecanismos como inicialização verificada. Muitas vezes, a melhor solução ao encontrar um problema com essa regra neverallow é mover o código incorreto para a partição /system .

Personalizando o 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 as extensões SEPolicy e SEPolicy do Android Open Source Project (AOSP). Para obter mais informações sobre como a política do SELinux é mantida compatível entre 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 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 superior, adicionar uma política a BOARD_SEPOLICY_DIRS coloca a política apenas na imagem do fornecedor.

No Android 8.0 e superior, a política existe nos seguintes locais no AOSP:

  • sistema/sepolítica/público . 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 deve persistir nas versões para que você possa incluir qualquer coisa /public em sua política personalizada. Por isso, o tipo de política que pode ser colocada em /public é mais restrito. Considere esta API de política exportada da plataforma: Qualquer coisa que lide com a interface entre /system e /vendor pertence aqui.
  • sistema/sepolítica/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/sepolítica/fornecedor . Inclui política para componentes que vão em /vendor mas existem na árvore da plataforma principal (não em diretórios específicos do dispositivo). Este é um artefato da distinção do sistema de compilaçã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 dispositivo para política, que no Android 8.0 e superior corresponde à política de componentes na imagem do fornecedor.

No Android 11 e superior, as partições system_ext e do produto também podem incluir políticas específicas de partição. As políticas do 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 deve ter 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 política necessária para o funcionamento da imagem do produto, mas da qual a política de imagem do fornecedor não deve ter conhecimento. Instalado na partição do produto.
Observação: quando o GSI é usado, as partições system_ext e do 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 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 do produto. As políticas públicas atuam como API exportada entre system_ext/product e vendor. Os parceiros devem gerenciar os próprios problemas de compatibilidade.

Cenários de políticas compatíveis

Em dispositivos lançados com Android 8.0 e superior, a imagem do fornecedor deve funcionar com a imagem do sistema OEM e a imagem do sistema AOSP de referência fornecida pelo Google (e passar o 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 : Adicionando um novo serviço ao vndservicemanager da imagem do fornecedor que suporta processos da imagem do fornecedor.

Tal como acontece com os dispositivos lançados com versões anteriores do Android, adicione 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 do fornecedor 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 de fornecedor para trabalhar com AOSP

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

Assim 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 ditando interações com os novos bits específicos do fornecedor, sujeito às restrições de neverallow previstas. Assim como no caso somente 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 (registrado 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 habilitar a funcionalidade em uma imagem do sistema parceiro, desde que esses novos bits não precisem interagir com novos componentes na imagem do fornecedor (especificamente, esses 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. Essa política faz parte da imagem do sistema e pode ser atualizada em um OTA somente de estrutura, mas não estará presente ao usar a imagem do sistema AOSP de referência.

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

Exemplo: uma nova 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 enviado na partição do fornecedor. Isso é semelhante ao cenário acima de adicionar suporte a 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 corretamente com o restante da partição do sistema (o que é bom desde que ainda têm os rótulos de tipo AOSP públicos).

A política para interação de componentes AOSP públicos 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 no 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 ir 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 estão lá). Embora a política possa ser incluída na política específica do dispositivo, ela não poderá usar outros tipos de system/sepolicy/private ou alteração (de qualquer maneira que afete a política) como resultado de uma atualização somente da estrutura. A política pode ser alterada em um OTA somente de estrutura, mas não estará presente 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 atendem a novos componentes do sistema

Exemplo: Adicionando um novo 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 das extensões AOSP , a política para interações entre o sistema e o fornecedor deve ir 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 dos 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 em adição à política AOSP existente, ou seja, não remova a política pública AOSP. Os novos tipos públicos podem ser usados ​​para política em system/sepolicy/private e em device/ manufacturer / device-name /sepolicy .

Tenha em mente que cada adição ao 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. Somente 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 sem suporte

Dispositivos lançados com Android 8.0 e superior não são compatíveis com o cenário e os exemplos de política a seguir.

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

Exemplo: um novo processo de sistema não AOSP, exigindo 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 um OTA somente de estrutura. Embora o novo tipo possa ser adicionado à política em system/sepolicy/public , a política de fornecedor existente não tem conhecimento do novo tipo, pois está rastreando 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 as extensões do parceiro de atributo 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 já 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 o 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 optar por uma política de sistema futura que use esses atributos. No entanto, as extensões de atributo em system/sepolicy/public não são suportadas , portanto, todas as políticas que ditam como os componentes do sistema interagem com os novos componentes do fornecedor (e que não são tratadas por atributos já presentes no 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 fornecedor como parte de um OTA somente de estrutura.