O SELinux é configurado para negar por padrão, o que significa que cada acesso que tiver um gancho no kernel precisa ser explicitamente permitido pela 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 consideração completa do SELinux está fora do escopo deste documento, mas entender como escrever regras de política agora é essencial ao usar novos dispositivos Android. Há um grande quantidade de informações disponíveis sobre o SELinux. Consulte a documentação de suporte para conferir recursos sugeridos.
Arquivos de chaves
Para ativar o SELinux, integre a mais recente kernel do Android e depois incorpora os arquivos encontrados na system/sepolicy (link em inglês) diretório. Quando compilados, esses arquivos formam a parte de segurança do kernel e abrangem 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 versões mais recentes, as alterações feitas nesses arquivos devem
afetam apenas a política no seu diretório de fornecedores. Para mais detalhes sobre a separação de
sepolicy pública no Android 8.0 e versões mais recentes, consulte
Personalizar SEPolicy no Android
8.0 e versões mais recentes. Independentemente da versão do Android, você ainda vai modificar 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 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
Nos arquivos de contexto, são especificados rótulos para os objetos.
file_contexts
atribui rótulos a arquivos e é usado por vários componentes do espaço do usuário. À medida que você cria novas políticas, crie ou atualize esse arquivo para atribuir novos rótulos aos arquivos. Para aplicar um novofile_contexts
, reconstrua a imagem do sistema de arquivos ou executerestorecon
no arquivo a ser remarcado. Em upgrades, as mudanças emfile_contexts
são aplicadas automaticamente ao sistema e às partições de userdata como parte do upgrade. As mudanças também podem ser aplicadas automaticamente no upgrade para outras partições adicionando chamadasrestorecon_recursive
ao arquivo init.board.rc depois que a partição for montada para leitura e gravação.genfs_contexts
atribui rótulos a sistemas de arquivos, comoproc
ouvfat
, que não oferecem suporte a 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 suportes específicos, comovfat
usando a opçãocontext=mount
.- O
property_contexts
atribui rótulos às propriedades do sistema Android para: e controlar quais processos podem defini-los. Essa configuração é lida pelo Processoinit
durante a inicialização. service_contexts
atribui rótulos aos serviços de vinculação do Android para controlar quais processos podem adicionar (registrar) e encontrar (procurar) um binder para o serviço. Essa configuração é lida pelo Processoservicemanager
durante a inicialização.seapp_contexts
atribui identificadores a processos de apps e/data/data
. Essa configuração é lida pelo processozygote
em cada inicialização do app e peloinstalld
durante a inicialização.mac_permissions.xml
atribui uma tagseinfo
a 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 é lidasystem_server
durante a inicialização.keystore2_key_contexts
atribui rótulos aos namespaces do Keystore 2.0. Esse namespace é aplicado pelo daemon keystore2. O Keystore sempre os namespaces fornecidos com base em UID/AID. O Keystore 2.0 também aplica sepolicy os namespaces definidos. Confira aqui uma descrição detalhada do formato e das convenções desse arquivo.
Makefile do BoardConfig.mk
Depois de editar ou adicionar os arquivos de política e contexto, atualize o
/device/manufacturer/device-name/BoardConfig.mk
makefile 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
arquivo system/sepolicy/README
.
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
Após a recriação, o dispositivo é ativado com o SELinux. Agora é possível 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 descrito em Validação.
Quando os novos arquivos de política e as atualizações do BoardConfig.mk estiverem em vigor, as novas configurações de política serão criadas automaticamente no arquivo de política do kernel final. Para mais informações sobre como o sepolicy é criado no dispositivo, consulte Como criar o 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:
BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
ouBOARD_BOOTCONFIG := androidboot.selinux=permissive
Isso é apenas para o desenvolvimento inicial da política do dispositivo. Depois de tiver uma política de inicialização inicial, remova esse parâmetro para que dispositivo está aplicando ou falha no CTS. - Inicialize o sistema como permissivo e confira quais negações são encontradas na inicialização:
No Ubuntu 14.04 ou mais recente:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
No Ubuntu 12.04:adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Avalie a saída em busca de 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 identificação.
- Use rótulos novos ou atuais para seus objetos. Analise os
arquivos
*_contexts
para saber como as coisas foram rotuladas anteriormente e use o conhecimento dos significados dos rótulos para atribuir um novo. Idealmente, esse é um rótulo existente que se encaixa na política, mas às vezes um novo rótulo é necessário, e as regras de acesso a ele são necessários. Adicione os rótulos aos arquivos de contexto apropriados. - Identifique domínios/processos que precisam ter domínios de segurança próprios.
Você provavelmente vai precisar escrever uma política completamente nova para cada um. Todos
os serviços gerados a partir 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: '
- Revise
init.device.rc
para identificar os domínios que não têm um tipo de domínio. Forneça um domínio cedo no processo de desenvolvimento para evitar a adição de regras aoinit
ou confundir os acessos doinit
com os que estão na própria política. - Configure
BOARD_CONFIG.mk
para usar variáveisBOARD_SEPOLICY_*
. Consulte a LEIA-ME emsystem/sepolicy
para mais detalhes sobre a configuração. - Examine o arquivo init.device.rc e fstab.device e
verifique se cada uso de
mount
corresponde a um sistema de arquivos corretamente rotulado ou se uma opçãocontext= mount
foi especificada. - Analise cada negação e crie uma política SELinux para processar cada uma delas. Consulte os exemplos em Personalização.
Comece com as políticas do 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 as políticas SELinux associadas:
Links simbólicos: como os links simbólicos aparecem como arquivos, eles são muitas vezes
lidos como arquivos, o que pode levar a exploits. Por exemplo, algumas contas privilegiadas
componentes, como init
, mudam as permissões de determinados arquivos,
muitas vezes fica aberta demais.
Os invasores podem substituir esses arquivos por links simbólicos para o código que controlam, permitindo que o invasor substitua arquivos arbitrários. No entanto, se você souber que o app nunca atravessa um link simbólico, poderá proibir isso com o SELinux.
Arquivos do sistema:considere a classe de arquivos de sistema que
só pode ser modificado pelo servidor do sistema. Ainda assim, desde netd
,
init
e vold
são executadas como raiz, podem acessar
esses arquivos de sistema. Portanto, se o netd
fica comprometido, pode
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 é o servidor do sistema.
Mesmo que o domínio netd
fosse comprometido, não era possível alternar os domínios para o
domínio do servidor do sistema e acessar esses arquivos de sistema, embora seja executado como raiz.
Dados do app: outro exemplo é a classe de funções que precisa ser executada como raiz, mas não pode acessar os dados do app. Isso é muito útil, porque é possível fazer várias declarações, 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 além disso pode ser
proibidas dessas alterações, mesmo pelo acesso raiz. Portanto, um app pode executar
chmod
e chown
em relação aos rotulados
app_data_files
, mas não shell_data_files
ou system_data_files
.