Android 10 include il daemon Live Lock di Android
(llkd
), progettato per rilevare e mitigare i deadlock del kernel. llkd
componente fornisce un'implementazione autonoma predefinita, ma puoi
in alternativa integrare il codice llkd
in un altro servizio, nell'ambito di
il loop principale o come thread separato.
Scenari di rilevamento
In llkd
sono previsti due scenari di rilevamento: stato D o Z permanente e
la firma dello stack.
Stato D o Z permanente
Se un thread è in stato D (sonno senza interruzioni) o Z (zombie) senza inoltro
di avanzamento per più di ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
,
llkd
termina il processo (o il processo padre). Se una scansione successiva mostra
continua la stessa procedura, llkd
conferma una condizione di Live Lock e
mette in panico il kernel in modo da fornire la segnalazione di bug più dettagliata per il
.
llkd
include un watchdog automatico che si attiva se llkd
si blocca. il watchdog è
il doppio del tempo previsto per il flusso attraverso il mainloop e il campionamento è ogni
ro.llk_sample_ms
.
Firma stack permanente
Per le release userdebug, llkd
può rilevare i live-lock del kernel utilizzando
il controllo della firma dello stack. Se un thread in uno stato qualsiasi tranne Z ha un indirizzo
simbolo del kernel ro.llk.stack
elencato che è segnalato per più di
ro.llk.timeout_ms
o ro.llk.stack.timeout_ms
, llkd
interrompe il processo
(anche in caso di avanzamento della pianificazione in avanti). Se una scansione successiva mostra
continua la stessa procedura, llkd
conferma una condizione di Live Lock e
mette in panico il kernel in modo da fornire la segnalazione di bug più dettagliata per il
.
Il controllo lldk
persiste in modo continuo quando esiste la condizione di blocco in tempo reale.
cerca le stringhe composte symbol+0x
o symbol.cfi+0x
nel
/proc/pid/stack
su Linux. L'elenco di simboli è in ro.llk.stack
e
il valore predefinito è l'elenco separato da virgole di
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
.
I simboli dovrebbero essere rari e di breve durata che, in un sistema tipico,
viene visualizzata una sola volta in un campione nel periodo di timeout di
ro.llk.stack.timeout_ms
(gli esempi si verificano ogni ro.llk.check_ms
). Per mancanza
della protezione ABA, questo è l'unico modo per evitare un falso trigger. Il simbolo
deve essere visualizzata sotto la funzione che chiama il blocco che potrebbe competere. Se
il lucchetto si trova sotto o nella funzione di simbolo, il simbolo appare in tutte le
i processi, non solo quello che ha causato il logo completo.
Copertura
L'implementazione predefinita di llkd
non monitora init
, [kthreadd]
o
[kthreadd]
germogli. Per consentire a llkd
di coprire [kthreadd]
thread visualizzati:
- I driver non devono rimanere in stato D permanente
OPPURE
- I driver devono disporre di meccanismi per recuperare il thread nel caso in cui venga interrotto
all'esterno. Ad esempio, utilizza
wait_event_interruptible()
anzichéwait_event()
.
Se una delle condizioni precedenti è soddisfatta, la lista bloccata llkd
può essere modificata in
per coprire i componenti del kernel. Il controllo dei simboli di stack comporta un processo aggiuntivo
lista bloccata per evitare violazioni delle norme sui servizi che bloccano ptrace
operazioni.
Proprietà Android
llkd
risponde a diverse proprietà Android (elencate di seguito).
- Le proprietà denominate
prop_ms
sono in millisecondi. - Le proprietà che utilizzano la virgola (,) come separatore per gli elenchi utilizzano un separatore iniziale per
conserva la voce predefinita, quindi aggiungi o sottrai voci con il segno più facoltativo
rispettivamente (+) e meno (-). Per questi elenchi, la stringa
false
è sinonimo di elenco vuoto, dove le voci vuote o mancanti ricorrono alla al valore predefinito specificato.
ro.config.low_ram
Il dispositivo è configurato con memoria limitata.
debuggable
Il dispositivo è configurato per il debug dell'utente o la build coinvolta.
ro.llk.sysrq_t
Se la proprietà è eng
, il valore predefinito non è ro.config.low_ram
o ro.debuggable
.
Se true
, esegui il dump di tutti i thread (sysrq t
).
ro.llk.enable
Consenti l'attivazione del daemon live-lock. Il valore predefinito è false
.
llk.enable
Valutazione per le build di eng. Il valore predefinito è ro.llk.enable
.
ro.khungtask.enable
Consenti l'abilitazione del daemon [khungtask]
. Il valore predefinito è false
.
khungtask.enable
Valutazione per le build di eng. Il valore predefinito è ro.khungtask.enable
.
ro.llk.mlockall
Attiva la chiamata al numero mlockall()
. Il valore predefinito è false
.
ro.khungtask.timeout
Limite di tempo massimo: [khungtask]
. Il valore predefinito è 12 minuti.
ro.llk.timeout_ms
Limite di tempo massimo D o Z. Il valore predefinito è 10 minuti. Raddoppia questo valore per impostare
watchdog di sveglia per llkd
.
ro.llk.D.timeout_ms
Limite di tempo massimo D. Il valore predefinito è ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Limite di tempo massimo Z. Il valore predefinito è ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms
Controlla il limite di tempo massimo per i simboli stack permanenti. Il valore predefinito è
ro.llk.timeout_ms
. Attivo solo su build di userdebug o build.
ro.llk.check_ms
Esempi di thread per D o Z. Il valore predefinito è due minuti.
ro.llk.stack
Controlla la presenza di simboli dello stack del kernel che, se presenti in modo permanente, possono indicare
è bloccato. Il valore predefinito è
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
elenco separato da virgole di simboli del kernel. Nel controllo non viene eseguita la pianificazione dell'inoltro
ABA (tranne con sondaggi ogni ro.llk_check_ms
nel corso del periodo)
ro.llk.stack.timeout_ms
, quindi i simboli stack dovrebbero essere eccezionalmente rari e
fugace (è molto improbabile che un simbolo compaia in modo persistente in
esempi dello stack). Cerca una corrispondenza per symbol+0x
o
symbol.cfi+0x
in espansione dello stack. Disponibile solo su userdebug o eng
; I problemi di sicurezza delle build degli utenti comportano privilegi limitati che
impedire questo controllo.
ro.llk.blacklist.processo
llkd
non monitora i processi specificati. Il valore predefinito è 0,1,2
(kernel
,
init
e [kthreadd]
) più i nomi dei processi
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
.
Un processo può essere un riferimento comm
, cmdline
o pid
. Un valore predefinito automatico
può essere superiore all'attuale dimensione massima della proprietà, pari a 92.
ro.llk.blacklist.parente
L'elemento llkd
non controlla i processi per cui sono stati specificati gli elementi principali. Predefinita
è 0,2,adbd&[setsid]
(kernel
, [kthreadd]
e adbd
solo per zombie
setsid
). Il separatore della e commerciale (&) specifica che il separatore principale viene ignorato solo
in combinazione con il processo figlio di destinazione. E commerciale è stata selezionata perché
non fa mai parte del nome di un processo; Tuttavia, un setprop
nella shell richiede
la e commerciale deve essere racchiusa tra caratteri di escape o tra virgolette, sebbene il file init rc
in cui si trova
normalmente specificato non presenta questo problema. Un processo principale o target può essere un
Riferimento comm
, cmdline
o pid
.
ro.llk.blacklist.uid
llkd
non controlla i processi che corrispondono agli UID specificati.
Elenco separato da virgole di numeri o nomi UIS. Il valore predefinito è vuoto o false
.
ro.llk.blacklist.process.stack
llkd
non monitora il sottoinsieme specificato di processi per lo stack di blocchi in tempo reale
firme. Il valore predefinito è i nomi di processo
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. Impedisce il sepolicy
una violazione associata a procedure che bloccano ptrace
(in quanto non possono essere
selezionata). Attivo solo su build di userdebug ed eng. Per i dettagli sulla build
consulta la sezione Creazione di Android.
Problemi di architettura
- Le proprietà hanno un limite di 92 caratteri, che viene però ignorato per i valori predefiniti.
definiti nel file
include/llkd.h
nelle origini). - Il daemon
[khungtask]
integrato è troppo generico e scatta sul codice conducente che rimane troppo nello stato D. Il passaggio a S renderebbe terminabili le attività (e recuperabili dai conducenti, se necessario).
Interfaccia libreria (facoltativa)
Facoltativamente, puoi incorporare llkd
in un altro daemon con privilegi utilizzando
la seguente interfaccia C dal componente libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Se viene fornito un nome thread, viene automaticamente generato un thread, altrimenti il chiamante
deve chiamare llkCheckMilliseconds
nel suo loop principale. La funzione restituisce
prima della successiva chiamata prevista a questo gestore.