Android 10 incluye el daemon de bloqueo activo de Android
(llkd
), que está diseñado para detectar y mitigar los interbloqueos del kernel. El llkd
proporciona una implementación independiente predeterminada, pero puedes
De manera alternativa, integra el código llkd
en otro servicio, ya sea como parte del
en el bucle principal o como un subproceso independiente.
Situaciones de detección
llkd
tiene dos situaciones de detección: estado D o Z persistente y persistente
firma de pila.
Estado persistente de D o Z
Si un subproceso está en estado D (suspendido ininterrumpido) o Z (zombi) sin reenvío
progreso durante más de ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
, el
llkd
finaliza el proceso (o proceso superior). Si un análisis posterior muestra
sigue existiendo el mismo proceso, llkd
confirma una condición de bloqueo activo y
activa el kernel de una manera que proporciona el informe de errores más detallado para el
estado.
llkd
incluye un perro guardián propio que emite una alarma si llkd
se bloquea. el perro guardián es
el doble del tiempo esperado para fluir a través del bucle principal, y el muestreo es cada
ro.llk_sample_ms
Firma de pila persistente
Para las versiones userdebug, llkd
puede detectar bloqueos en vivo del kernel mediante solicitudes
verificación de firma de pila. Si un subproceso en cualquier estado excepto en Z tiene un valor
el símbolo del kernel ro.llk.stack
que se informa por más de
ro.llk.timeout_ms
o ro.llk.stack.timeout_ms
, llkd
finaliza el proceso.
(incluso si hay progreso en la programación futura). Si un análisis posterior muestra
sigue existiendo el mismo proceso, llkd
confirma una condición de bloqueo activo y
activa el kernel de una manera que proporciona el informe de errores más detallado para el
estado.
La verificación de lldk
persiste de forma continua cuando existe la condición de bloqueo activo
busca las cadenas compuestas symbol+0x
o symbol.cfi+0x
en el
/proc/pid/stack
en Linux. La lista de símbolos está en ro.llk.stack
y
de forma predeterminada a la lista separada por comas de
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
Los símbolos deben ser raros y tener una duración lo suficientemente corta como para que en un sistema típico se
función se ve solo una vez en una muestra durante el tiempo de espera de
ro.llk.stack.timeout_ms
(las muestras se realizan cada ro.llk.check_ms
). Debido a la falta
de protección ABA, esta es la única forma de evitar un activador falso. El símbolo
debe aparecer debajo de la función que llama al bloqueo que podría competir. Si
el candado está debajo o en la función de símbolo, el símbolo aparece en todas las zonas
no solo el que causó el diseño final.
Cobertura
La implementación predeterminada de llkd
no supervisa init
, [kthreadd]
ni
Se genera [kthreadd]
. Para que llkd
cubra los subprocesos generados por [kthreadd]
, haz lo siguiente:
- Los controladores no deben permanecer en un estado D persistente,
O
- Los controladores deben tener mecanismos para recuperar el subproceso en caso de que se cierre.
externamente. Por ejemplo, usa
wait_event_interruptible()
en lugar dewait_event()
Si se cumple una de las condiciones anteriores, la lista de bloqueo de llkd
se puede ajustar a
abarcan los componentes del kernel. La comprobación de símbolos de pila implica un proceso adicional
lista de bloqueo para evitar incumplimientos de política en los servicios que bloquean ptrace
las operaciones.
Propiedades de Android
El llkd
responde a varias propiedades de Android (que se indican a continuación).
- Las propiedades
prop_ms
se expresan en milisegundos. - Las propiedades que usan un separador de coma (,) para las listas usan un separador inicial para
conservar la entrada predeterminada y, luego, agregar o restar entradas con el signo más opcional
Prefijos (+) y menos (-), respectivamente. Para estas listas, la cadena
false
es sinónimo de una lista vacía, y las entradas en blanco o faltantes recurren a valor predeterminado especificado.
ro.config.low_ram
El dispositivo se configuró con memoria limitada.
ro.debuggable.
El dispositivo está configurado para userdebug o eng build.
ro.llk.sysrq_t
Si la propiedad es eng
, el valor predeterminado no es ro.config.low_ram
ni ro.debuggable
.
Si es true
, vuelca todos los subprocesos (sysrq t
).
ro.llk.enable
Permitir que se habilite el daemon de bloqueo activo El valor predeterminado es false
.
llk.enable
Se evaluó para compilaciones de ingeniería. El valor predeterminado es ro.llk.enable
.
ro.khungtask.enable
Permitir que se habilite el daemon [khungtask]
. El valor predeterminado es false
.
khungtask.enable
Se evaluó para compilaciones de ingeniería. El valor predeterminado es ro.khungtask.enable
.
ro.llk.mlockall
Habilitar llamada a mlockall()
. El valor predeterminado es false
.
ro.khungtask.timeout
Límite de tiempo máximo: [khungtask]
. El valor predeterminado es de 12 minutos.
ro.llk.timeout_ms
Límite de tiempo máximo D o Z. El valor predeterminado es 10 minutos. Duplica este valor para definir
perro guardián de la alarma para llkd
.
ro.llk.D.timeout_ms
Límite de tiempo máximo de D. El valor predeterminado es ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Límite de tiempo máximo de Z. El valor predeterminado es ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms.
Verifica el límite de tiempo máximo de símbolos de pila persistentes. La configuración predeterminada es
ro.llk.timeout_ms
Está activo solo en compilaciones userdebug o eng.
ro.llk.check_ms
Muestras de subprocesos para D o Z. El valor predeterminado es de dos minutos.
ro.llk.stack
Comprueba si hay símbolos de la pila del kernel que, si están presentes de forma persistente, pueden indicar una
el subsistema está bloqueado. La configuración predeterminada es
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
Lista de símbolos de kernel separados por comas. La verificación no adelanta la programación
ABA, excepto mediante un sondeo cada ro.llk_check_ms
durante el período
ro.llk.stack.timeout_ms
, por lo que los símbolos de pila deben ser excepcionalmente raros y
fugaz (es muy poco probable que un símbolo aparezca de forma persistente en todos los
de la pila). Busca una coincidencia para symbol+0x
o
symbol.cfi+0x
en la expansión de pila. Disponible solo en userdebug o eng
compilaciones; los problemas de seguridad en compilaciones de usuarios dan como resultado privilegios limitados que
evitar esta verificación.
ro.llk.list.process.
llkd
no mira los procesos especificados. El valor predeterminado es 0,1,2
(kernel
,
init
y [kthreadd]
), más nombres de procesos
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
Un proceso puede ser una referencia comm
, cmdline
o pid
. Valor predeterminado automático
Puede ser mayor que el tamaño máximo de propiedad actual de 92.
ro.llk.get.gru.parent
llkd
no observa los procesos que tienen los elementos superiores especificados. Predeterminada
es 0,2,adbd&[setsid]
(kernel
, [kthreadd]
y adbd
solo para zombis)
setsid
). El separador de signo et (&) especifica que el elemento superior solo se ignora.
en combinación con el proceso secundario de destino. Se seleccionó Ampersand porque
nunca es parte del nombre de un proceso; Sin embargo, un setprop
en la shell requiere el elemento
el signo de unión para escapar o entrecomillado, aunque el archivo init rc
donde se
que se especifica normalmente no tiene este problema. Un proceso superior o de destino puede ser
Contiene la referencia comm
, cmdline
o pid
.
ro.llk.list.uid.
llkd
no observa los procesos que coinciden con los UID especificados.
Lista de números de UIS o nombres separados por comas. El valor predeterminado es vacío o false
.
ro.llk.list.process.stack
llkd
no supervisa el subconjunto de procesos especificado para la pila de bloqueo activa.
las firmas. La configuración predeterminada son nombres de procesos
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
Impide la política
incumplimiento asociado con procesos que bloquean ptrace
(ya que no pueden
(marcado). Está activo solo en compilaciones userdebug y eng. Para obtener detalles sobre la compilación
consulta Cómo compilar Android.
Inquietudes en la arquitectura
- Las propiedades tienen un límite de 92 caracteres (esto se ignora en la configuración predeterminada)
se define en el archivo
include/llkd.h
de las fuentes). - El daemon
[khungtask]
integrado es demasiado genérico y los viajes en el código del controlador que se queda demasiado en estado D. Si cambias a S, las tareas podrían eliminarse. (y los conductores pueden volver a usarlos si es necesario).
Interfaz de la biblioteca (opcional)
De manera opcional, puedes incorporar llkd
a otro daemon con privilegios mediante
La siguiente interfaz de C del componente libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Si se proporciona un nombre de subproceso, este se genera automáticamente; de lo contrario, el llamador
debe llamar a llkCheckMilliseconds
en su bucle principal. La función muestra
de tiempo antes de la próxima llamada prevista a este controlador.