Android recomienda encarecidamente a los OEM que prueben minuciosamente sus implementaciones de SELinux. A medida que los fabricantes implementan SELinux, primero deben aplicar la nueva política a un grupo de dispositivos de prueba.
Después de aplicar una nueva política, asegúrese de que SELinux se esté ejecutando en el modo correcto en el dispositivo emitiendo el comando getenforce .
Esto imprime el modo SELinux global: Obligatorio o Permisivo. Para determinar el modo SELinux para cada dominio, debe examinar los archivos correspondientes o ejecutar la última versión de sepolicy-analyze con el indicador ( -p ) apropiado, presente en /platform/system/sepolicy/tools/ .
Leer negaciones
Compruebe si hay errores, que se enrutan como registros de eventos a dmesg y logcat y se pueden ver localmente en el dispositivo. Los fabricantes deben examinar la salida de SELinux a dmesg en estos dispositivos y refinar la configuración antes del lanzamiento público en modo permisivo y eventualmente cambiar al modo de aplicación. Los mensajes de registro de SELinux contienen avc: y, por lo tanto, se pueden encontrar fácilmente con grep . Es posible capturar los registros de denegación en curso ejecutando cat /proc/kmsg o capturar los registros de denegación del arranque anterior ejecutando cat /sys/fs/pstore/console-ramoops .
Con este resultado, los fabricantes pueden identificar fácilmente cuándo los usuarios o componentes del sistema infringen la política de SELinux. Luego, los fabricantes pueden reparar este mal comportamiento, ya sea mediante cambios en el software, la política de SELinux o ambos.
Específicamente, estos mensajes de registro indican qué procesos fallarían en el modo de aplicación y por qué. Aquí hay un ejemplo:
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 esta salida así:
- El
{ connectto }anterior representa la acción que se está realizando. Junto con latclassal final (unix_stream_socket), le dice aproximadamente qué se estaba haciendo a qué. En este caso, algo intentaba conectarse a un socket de flujo de Unix. - El
scontext (u:r:shell:s0)le dice qué contexto inició la acción. En este caso, esto es algo que se ejecuta como shell. - El
tcontext (u:r:netd:s0)le indica el contexto del objetivo de la acción. En este caso, es un unix_stream_socket propiedad denetd. - El
comm="ping"en la parte superior le brinda una pista adicional sobre lo que se estaba ejecutando en el momento en que se generó la denegación. En este caso, es una pista bastante buena.
Otro ejemplo:
adb shell su root dmesg | grep 'avc: '
Producción:
<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
Estos son los elementos clave de esta negación:
- Acción : la acción intentada se resalta entre paréntesis,
read writeosetenforce. - Actor : la entrada
scontext(contexto de origen) representa al actor, en este caso, el demoniormt_storage. - Objeto : la entrada
tcontext(contexto de destino) representa el objeto sobre el que se actúa, en este caso kmem. - Resultado : la
tclass(clase de destino) indica el tipo de objeto sobre el que se actúa, en este caso, unchr_file(dispositivo de caracteres).
Volcado de pilas de usuario y kernel
En algunos casos, la información contenida en el registro de eventos no es suficiente para identificar el origen de la denegación. Suele ser útil recopilar la cadena de llamadas, incluido el kernel y el espacio de usuario, para comprender mejor por qué ocurrió la denegación.
Los núcleos recientes definen un punto de rastreo llamado avc:selinux_audited . Use Android simpleperf para habilitar este punto de seguimiento y capturar la cadena de llamadas.
Configuración admitida
- Linux kernel> = 5.10, en particular, se admiten las ramas principales de Android Common Kernel y android12-5.10 . La rama android12-5.4 también es compatible. Puede usar
simpleperfpara determinar si el punto de rastreo está definido en su dispositivo:adb root && adb shell simpleperf list | grep avc:selinux_audited. Para otras versiones del kernel, puede elegir las confirmaciones dd81662 y 30969bc . - Debería ser posible reproducir el evento que está depurando. Los eventos de tiempo de arranque no son compatibles con simpleperf; sin embargo, es posible que aún pueda reiniciar el servicio para desencadenar el evento.
Captura de la cadena de llamadas
El primer paso es grabar el evento usando simpleperf record :
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
Luego, se debe desencadenar el evento que causó la denegación. Después de eso, la grabación debe detenerse. En este ejemplo, al usar Ctrl-c , la muestra debería haber sido capturada:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Finalmente, se puede usar el simpleperf report para inspeccionar el seguimiento de pila capturado. Por ejemplo:
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
La cadena de llamadas anterior es una cadena de llamadas unificada de kernel y espacio de usuario. Le brinda una mejor vista del flujo de código al iniciar el seguimiento desde el espacio de usuario hasta el kernel donde ocurre la negación. Para obtener más información sobre simpleperf , consulte la referencia de comandos ejecutables de Simpleperf
Cambiando a permisivo
La aplicación de SELinux se puede deshabilitar a través de ADB en compilaciones de depuración de usuarios o eng. Para hacerlo, primero cambia ADB a root ejecutando adb root . Luego, para deshabilitar la aplicación de SELinux, ejecute:
adb shell setenforce 0
O en la línea de comando del kernel (durante la activación inicial del dispositivo):
androidboot.selinux=permissiveandroidboot.selinux=enforcing
O a través de bootconfig en Android 12:
androidboot.selinux=permissiveandroidboot.selinux=enforcing
Uso de audit2allow
La herramienta audit2allow toma las denegaciones de dmesg y las convierte en declaraciones de política de SELinux correspondientes. Como tal, puede acelerar enormemente el desarrollo de SELinux.
Para usarlo, ejecuta:
adb pull /sys/fs/selinux/policyadb logcat -b events -d | audit2allow -p policy
Sin embargo, se debe tener cuidado para examinar cada adición potencial en busca de permisos extralimitados. Por ejemplo, alimentar audit2allow con la denegación de rmt_storage se mostró anteriormente da como resultado la siguiente declaración de política de SELinux sugerida:
#============= shell ==============
allow shell kernel:security setenforce;
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };
Esto le otorgaría a rmt la capacidad de escribir en la memoria del núcleo, un agujero de seguridad evidente. A menudo, las declaraciones audit2allow son solo un punto de partida. Después de emplear estas declaraciones, es posible que deba cambiar el dominio de origen y la etiqueta del destino, así como incorporar las macros adecuadas, para llegar a una buena política. A veces, la denegación que se examina no debería dar lugar a ningún cambio de política; más bien, se debe cambiar la aplicación infractora.