O SELinux é configurado para negação por padrão, o que significa que cada acesso para o qual ele tem um hook no kernel precisa ser explicitamente permitido por uma política. Isso significa que um arquivo de política é composto por uma grande quantidade de informações sobre regras, tipos, classes, permissões e muito mais. Uma análise completa do SELinux está fora do escopo deste documento, mas entender como escrever regras de política é essencial ao usar novos dispositivos Android. Já existe muita informação disponível sobre o SELinux. Consulte Documentação de suporte para recursos sugeridos.
Arquivos de chave
Para ativar o SELinux, integre o kernel do Android mais recente e incorpore os arquivos encontrados no diretório system/sepolicy. Quando compilados, esses arquivos compreendem a política de segurança do kernel do SELinux e cobrem o sistema operacional Android upstream.
Em geral, não modifique os arquivos system/sepolicy
diretamente. Em vez disso, adicione ou edite seus próprios arquivos de política específicos do dispositivo no diretório
/device/manufacturer/device-name/sepolicy
. No Android 8.0 e em versões mais recentes, as mudanças feitas nesses arquivos
afetam apenas a política no diretório do fornecedor. Para mais detalhes sobre a separação da
sepolicy pública no Android 8.0 e versões mais recentes, consulte
Personalizar a SEPolicy no Android
8.0 e versões mais recentes. Independente da versão do Android, você ainda modifica estes arquivos:
Arquivos de política
Os arquivos que terminam com *.te
são arquivos de origem da política do SELinux, que
definem domínios e seus rótulos. Talvez seja necessário criar novos arquivos de política em
/device/manufacturer/device-name/sepolicy
,
mas tente atualizar os arquivos atuais sempre que possível.
Arquivos de contexto
Os arquivos de contexto são onde você especifica rótulos para seus objetos.
- O
file_contexts
atribui rótulos a arquivos e é usado por vários componentes do espaço do usuário. Ao criar novas políticas, crie ou atualize esse arquivo para atribuir novos rótulos aos arquivos. Para aplicar novosfile_contexts
, recompile a imagem do sistema de arquivos ou executerestorecon
no arquivo para ser rotulado novamente. Em upgrades, as mudanças emfile_contexts
são aplicadas automaticamente às partições do sistema e de dados do usuário como parte do upgrade. As mudanças também podem ser aplicadas automaticamente na atualização para outras partições adicionando chamadasrestorecon_recursive
ao arquivo init.board.rc depois que a partição for montada com acesso de leitura e gravação. - O
genfs_contexts
atribui rótulos a sistemas de arquivos, comoproc
ouvfat
, que não são compatíveis com atributos estendidos. Essa configuração é carregada como parte da política do kernel, mas as mudanças podem não entrar em vigor para inodes no núcleo, exigindo uma reinicialização ou desmontagem e remontagem do sistema de arquivos para aplicar totalmente a mudança. Rótulos específicos também podem ser atribuídos a montagens específicas, comovfat
usando a opçãocontext=mount
. - O
property_contexts
atribui rótulos a propriedades do sistema Android para controlar quais processos podem defini-las. Essa configuração é lida pelo processoinit
durante a inicialização. - O
service_contexts
atribui rótulos aos serviços de vinculação do Android para controlar quais processos podem adicionar (registrar) e encontrar (pesquisar) uma referência de vinculação para o serviço. Essa configuração é lida pelo processoservicemanager
durante a inicialização. - O
seapp_contexts
atribui rótulos a processos de apps e diretórios/data/data
. Essa configuração é lida pelo processozygote
em cada inicialização do app e peloinstalld
durante a inicialização. - O
mac_permissions.xml
atribui uma tagseinfo
aos apps com base na assinatura e, opcionalmente, no nome do pacote. A tagseinfo
pode ser usada como uma chave no arquivoseapp_contexts
para atribuir um rótulo específico a todos os apps com essa tagseinfo
. Essa configuração é lida porsystem_server
durante a inicialização. keystore2_key_contexts
atribui rótulos aos namespaces do Keystore 2. Esses namespaces são aplicados pelo daemonkeystore2
. O keystore sempre forneceu namespaces baseados em UID/AID. O Keystore 2 também aplica namespaces definidos pela sepolicy. Uma descrição detalhada do formato e das convenções desse arquivo pode ser encontrada aqui.
Makefile BoardConfig.mk
Depois de editar ou adicionar arquivos de política e contexto, atualize o
makefile
/device/manufacturer/device-name/BoardConfig.mk
para fazer referência ao subdiretório sepolicy
e a cada novo arquivo de política.
Para mais informações sobre as variáveis BOARD_SEPOLICY
, consulte o
arquivo
system/sepolicy/README
.
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
Depois da reconstrução, o SELinux será ativado no dispositivo. Agora você pode personalizar suas políticas do SELinux para acomodar suas próprias adições ao sistema operacional Android, conforme descrito em Personalização, ou verificar sua configuração atual, conforme abordado em Validação.
Quando os novos arquivos de política e as atualizações do BoardConfig.mk estiverem no lugar, as novas configurações de política serão incorporadas automaticamente ao arquivo de política do kernel final. Para mais informações sobre como a sepolicy é criada no dispositivo, consulte Criar sepolicy.
Implementação
Para começar a usar o SELinux:
- Ative o SELinux no kernel:
CONFIG_SECURITY_SELINUX=y
- Mude o parâmetro kernel_cmdline ou bootconfig para que:
ouBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Isso é apenas para o desenvolvimento inicial da política do dispositivo. Depois de ter uma política de bootstrap inicial, remova esse parâmetro para que o dispositivo aplique ou falhe no CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Inicialize o sistema no modo permissivo e veja quais negações são encontradas na inicialização:
No Ubuntu 14.04 ou mais recente: No Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Avalie a saída para avisos semelhantes a
init: Warning! Service name needs a SELinux domain defined; please fix!
. Consulte Validação para instruções e ferramentas. - Identifique dispositivos e outros arquivos novos que precisam de rotulagem.
- Use rótulos novos ou atuais para seus objetos. Analise os arquivos
*_contexts
para ver como as coisas foram rotuladas anteriormente e use o conhecimento dos significados dos rótulos para atribuir um novo. O ideal é que seja um rótulo que se encaixe na política, mas às vezes é necessário criar um novo rótulo e regras de acesso a ele. Adicione os rótulos aos arquivos de contexto apropriados. - Identifique domínios/processos que precisam ter domínios de segurança próprios.
Provavelmente, você precisará escrever uma política completamente nova para cada um. Todos os
serviços gerados de
init
, por exemplo, precisam ter o próprio. Os comandos a seguir ajudam a revelar aqueles que permanecem em execução (mas TODOS os serviços precisam desse tratamento):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- Analise
init.device.rc
para identificar domínios que não têm um tipo. Dê a eles um domínio no início do processo de desenvolvimento para evitar adicionar regras ainit
ou confundir os acessos deinit
com os da própria política. - Configure
BOARD_CONFIG.mk
para usar variáveisBOARD_SEPOLICY_*
. Consulte o README emsystem/sepolicy
para detalhes sobre a configuração. - Examine os arquivos init.device.rc e fstab.device e confira se cada uso de
mount
corresponde a um sistema de arquivos rotulado corretamente ou se uma opçãocontext= mount
foi especificada. - Analise cada negação e crie uma política do SELinux para processar cada uma delas corretamente. Consulte os exemplos em Personalização.
Comece com as políticas no AOSP e depois crie suas próprias personalizações. Para mais informações sobre a estratégia de política e uma análise mais detalhada de algumas dessas etapas, consulte Como escrever uma política do SELinux.
Casos de uso
Confira exemplos específicos de exploits a serem considerados ao criar seu próprio software e políticas SELinux associadas:
Links simbólicos:como os links simbólicos aparecem como arquivos, eles são lidos como arquivos, o que pode levar a exploits. Por exemplo, alguns componentes privilegiados, como init
, mudam as permissões de determinados arquivos, às vezes para serem excessivamente abertas.
Em seguida, os invasores podem substituir esses arquivos por symlinks para o código que eles controlam, permitindo que eles substituam arquivos arbitrários. Mas se você sabe que seu app nunca atravessa um link simbólico, é possível proibir isso com o SELinux.
Arquivos de sistema:considere a classe de arquivos de sistema que
só podem ser modificados pelo servidor do sistema. No entanto, como netd
, init
e vold
são executados como raiz, eles podem acessar esses arquivos do sistema. Assim, se netd
for comprometido, ele poderá
comprometer esses arquivos e, possivelmente, o próprio servidor do sistema.
Com o SELinux, é possível identificar esses arquivos como arquivos de dados do servidor do sistema.
Portanto, o único domínio com acesso de leitura/gravação a eles é o servidor do sistema.
Mesmo que netd
fosse comprometido, ele não poderia mudar de domínio para o domínio do servidor do sistema e acessar esses arquivos, embora seja executado como raiz.
Dados do app:outro exemplo é a classe de funções que precisam ser executadas como raiz, mas não podem acessar dados do app. Isso é muito útil, já que é possível fazer declarações abrangentes, como a proibição de acesso à Internet de determinados domínios não relacionados aos dados do app.
setattr:para comandos como chmod
e chown
, é possível identificar o conjunto de arquivos em que o domínio associado pode realizar setattr
. Qualquer coisa fora disso pode ser proibida de fazer essas mudanças, mesmo pelo root. Assim, um app pode executar
chmod
e chown
em relação aos marcados
app_data_files
, mas não shell_data_files
ou system_data_files
.