O SELinux é configurado para negar por padrão, o que significa que cada acesso para o qual ele tem um gancho no kernel precisa ser permitido explicitamente 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 criar novos dispositivos Android. Já há muitas informações disponíveis sobre o SELinux. Consulte a documentação de suporte para conferir 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 SELinux 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
só afetam a política no diretório do fornecedor. 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
Os arquivos de contexto são onde você especifica rótulos para seus 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 montagens específicas, comovfat
usando a opçãocontext=mount
.property_contexts
atribui rótulos às propriedades do sistema Android para 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) uma referência de vinculação para o serviço. Essa configuração é lida pelo processoservicemanager
durante a inicializaçã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.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 é lida porsystem_server
durante a inicialização.keystore2_key_contexts
atribui rótulos aos namespaces do Keystore 2. Esse namespace é aplicado pelo daemonkeystore2
. O keystore sempre forneceu namespaces baseados em UID/AID. Além disso, o Keystore 2 aplica namespaces definidos pela sepolicy. Confira aqui uma descrição detalhada do formato e das convenções desse arquivo.
Makefile BoardConfig.mk
Depois de editar ou adicionar 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 a 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:
ouBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Isso é apenas para o desenvolvimento inicial da política do dispositivo. Depois de ter uma política de inicialização inicial, remova esse parâmetro para que o dispositivo seja aplicado ou falhe no CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Inicialize o sistema em 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 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 novos arquivos que precisam ser rotulados.
- Use rótulos novos ou já existentes 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. O ideal é que seja um rótulo existente que se encaixe na política, mas às vezes é necessário um novo rótulo e regras para o 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 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: '
- Analise
init.device.rc
para identificar os domínios que não têm um tipo. Forneça um domínio cedo no processo de desenvolvimento para evitar a adição de regras aoinit
ou confundir os acessosinit
com os que estão na própria política. - Configure
BOARD_CONFIG.mk
para usar variáveisBOARD_SEPOLICY_*
. Consulte o README emsystem/sepolicy
para saber como configurar. - Examine o arquivo init.device.rc e fstab.device e
confira se cada uso de
mount
corresponde a um sistema de arquivos corretamente identificado ou se uma opçãocontext= mount
foi especificada. - Analise cada negação e crie uma política SELinux para processar cada uma delas corretamente. 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 eles aparecem como arquivos, geralmente 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 abertos.
Os invasores podem substituir esses arquivos por links simbólicos para o código que eles 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 do sistema que
deve ser modificada apenas pelo servidor do sistema. No entanto, como netd
,
init
e vold
são executados como raiz, eles podem acessar
esses arquivos do sistema. Se o 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 é o servidor do sistema.
Mesmo que o netd
tenha sido comprometido, ele não poderia mudar de domínio para o
domínio do servidor do sistema e acessar esses arquivos do 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 fora disso pode ser
proibida dessas mudanças, mesmo por raiz. Assim, 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
.