O Android incentiva fortemente OEMs a testarem suas implementações do SELinux com cuidado. À medida que os fabricantes implementam o SELinux, eles devem aplicar a nova a um pool de teste de dispositivos primeiro.
Depois de aplicar uma nova política, verifique se o SELinux está sendo executado no
no dispositivo executando o comando getenforce
.
Isso imprime o modo SELinux global: aplicador ou permissivo. Para
determinar o modo SELinux de cada domínio, é preciso examinar o modo
arquivos ou execute a versão mais recente do sepolicy-analyze
com os
sinalização apropriada (-p
), presente em
/platform/system/sepolicy/tools/
.
Leitura de negações
Verifique se há erros, que são roteados como logs de eventos para dmesg
e logcat
e são visíveis localmente no dispositivo. Fabricantes
precisa examinar a saída do SELinux para dmesg
nesses dispositivos e
refinar as configurações antes do lançamento público em modo permissivo e depois mudar
para o modo de aplicação. As mensagens de registro do SELinux contêm avc:
e, portanto,
pode ser encontrado facilmente com grep
. É possível capturar
de negação de serviço executando cat /proc/kmsg
ou para capturar registros de negação
da inicialização anterior executando
cat /sys/fs/pstore/console-ramoops
.
As mensagens de erro do SELinux têm limitação de taxa após a conclusão da inicialização para evitar sobrecarga
dos registros. Para garantir que você veja todas as mensagens relevantes, desative esta opção
executando adb shell auditctl -r 0
.
Com essa saída, os fabricantes podem identificar prontamente quando os usuários do sistema ou estão violando a política do SELinux. Os fabricantes podem fazer reparos esse mau comportamento, seja por mudanças no software, na política do SELinux ou em ambos.
Especificamente, essas mensagens de registro indicam quais processos falhariam na o modo de aplicação e por quê. Confira um exemplo:
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
Interprete o resultado da seguinte forma:
- O
{ connectto }
acima representa a ação realizada. Com otclass
no final (unix_stream_socket
), ele informa aproximadamente o que foi feito com o quê. Nesse caso, algo estava tentando se conectar a um soquete de stream Unix. - O
scontext (u:r:shell:s0)
informa qual contexto iniciou a ação. Em Neste caso, isso é algo que está sendo executado como shell. - O
tcontext (u:r:netd:s0)
informa o contexto do alvo da ação. Em Neste caso, trata-se de um unix_stream_socket de propriedade denetd
. - O
comm="ping"
na parte de cima dá uma dica adicional sobre o que estava sendo no momento em que a negação foi gerada. Nesse caso, é uma dica muito boa.
Outro exemplo:
adb shell su root dmesg | grep 'avc: '
Saída:
<5> type=1400 audit: avc: denied { read write } for pid=177 comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 tcontext=u:object_r:kmem_device:s0 tclass=chr_file
Aqui estão os principais elementos dessa negação:
- Action: a ação é destacada entre colchetes,
read write
ousetenforce
. - Ator: a entrada
scontext
(contexto de origem) representa o ator. Neste caso, o daemonrmt_storage
. - Object: a entrada
tcontext
(contexto de destino) representa objeto sendo usado, neste caso kmem. - Resultado: a entrada
tclass
(classe de destino) indica o tipo. objeto sendo usado, nesse caso, umchr_file
(dispositivo de caractere).
Despejar pilhas de usuário e de kernel
Em alguns casos, as informações contidas no log de eventos não são suficientes para identificar a origem da negação. Muitas vezes, é útil reunir a cadeia de chamadas, incluindo o kernel e espaço do usuário, para entender melhor por que a negação ocorreu.
Os kernels recentes definem um tracepoint chamado avc:selinux_audited
. Usar o Android
simpleperf
para ativar o tracepoint e capturar a cadeia de chamadas.
Configuração compatível
- Kernel do Linux >= 5.10, em especial ramificações do kernel comum do Android
linha principal
e
android12 a 5.10
são suportados.
A biblioteca android12-5.4
a ramificação
também é aceita. Use
simpleperf
para determinar se o tracepoint está definido no seu dispositivo:adb root && adb shell simpleperf list | grep avc:selinux_audited
. Para outras versões do kernel, é possível selecionar os commits dd81662 (link em inglês) e 30969bc (link em inglês). - Deve ser possível reproduzir o evento que você está depurando. Os eventos de tempo de inicialização não são compatível com o simpleperf; No entanto, talvez seja possível reiniciar o serviço para acionar o evento.
Como capturar a cadeia de chamadas
A primeira etapa é gravar o evento usando simpleperf record
:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
Em seguida, o evento que causou a negação deve ser acionado. Depois disso, a gravação deve
ser interrompida. Neste exemplo, usando Ctrl-c
, a amostra deveria ter sido capturada:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Por fim, simpleperf report
pode ser usado para inspecionar o stack trace capturado.
Por exemplo:
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph" [...] Children Self Command Pid Tid Shared Object Symbol 100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init | -- __libc_init | -- main toybox_main toy_exec_which dmesg_main klogctl entry_SYSCALL_64_after_hwframe do_syscall_64 __x64_sys_syslog do_syslog selinux_syslog slow_avc_audit common_lsm_audit avc_audit_post_callback avc_audit_post_callback
A cadeia de chamadas acima é um kernel unificado e uma cadeia de chamadas do espaço do usuário. Ele oferece uma experiência
do fluxo do código iniciando o rastro desde o espaço do usuário até o kernel, onde
a negação acontece. Para mais informações sobre simpleperf
, consulte a
Referência de comandos executáveis do Simpleperf
Alternando para permissivo
A aplicação do SELinux pode ser desativada via ADB em builds userdebug ou eng. Para isso,
Primeiro, mude o adb para raiz executando adb root
. Em seguida, para desativar o SELinux,
aplicação, execute:
adb shell setenforce 0
Ou na linha de comando do kernel (durante a inicialização do dispositivo):
androidboot.selinux=permissive
androidboot.selinux=enforcing
Ou pelo bootconfig do Android 12:
androidboot.selinux=permissive
androidboot.selinux=enforcing
Como usar audit2allow
A ferramenta audit2allow
recebe dmesg
negações e
os converte em instruções de política do SELinux correspondentes. Por isso, ele pode
agilizam muito o desenvolvimento do SELinux.
Para usá-la, execute:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
No entanto, é preciso ter cuidado ao examinar cada possível adição
que excedem o limite de permissões. Por exemplo, alimentar audit2allow
o
A negação de rmt_storage
mostrada anteriormente resulta no seguinte
declaração de política do SELinux sugerida:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
Isso concederia ao rmt
a capacidade de gravar na memória do kernel, uma
uma brecha de segurança evidente. Muitas vezes, as instruções audit2allow
são apenas uma
ponto de partida. Depois de empregar essas instruções, talvez seja necessário alterar o
domínio de origem e o rótulo do destino, além de incorporar
para chegar a uma boa política. Às vezes, a negação examinada deve
não resultarão em nenhuma alteração na política; e não o aplicativo ofensivo
devem ser alteradas.