Daemon de bloqueo activo de Android (llkd)

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 de wait_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.