Android 10 inclut le daemon de verrouillage en direct Android
(llkd
), conçu pour détecter et atténuer les interblocages du noyau. llkd
fournit une implémentation autonome par défaut, mais vous pouvez
Vous pouvez aussi intégrer le code llkd
dans un autre service, soit dans le cadre de
dans la boucle principale ou
en tant que thread distinct.
Scénarios de détection
Le llkd
comporte deux scénarios de détection: l'état persistant D ou Z, et l'état persistant
la signature de la pile.
État D ou Z persistant
Si un fil de discussion est en état D (veille ininterrompue) ou Z (zombie) sans avancer
progression pendant plus de ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
, la
llkd
tue le processus (ou le processus parent). Si une analyse ultérieure affiche
même processus continue d'exister, le llkd
confirme une condition de verrouillage en direct et
panique le noyau de manière à fournir le rapport de bug le plus détaillé
.
Le llkd
inclut un watchdog automatique qui déclenche une alarme si llkd
se verrouille. le chien de garde est
est deux fois plus longue que le temps
prévu pour passer dans la boucle principale. L'échantillonnage
ro.llk_sample_ms
Signature de pile persistante
Pour les versions userdebug, le llkd
peut détecter les verrouillages en direct du noyau à l'aide de l'objet persistant
la vérification de la signature
de la pile. Si un thread dans un état autre que Z a une couche persistante
listé le symbole de noyau ro.llk.stack
signalé depuis plus longtemps que
ro.llk.timeout_ms
ou ro.llk.stack.timeout_ms
, llkd
tue le processus.
(même en cas de progression de la planification). Si une analyse ultérieure affiche
même processus continue d'exister, le llkd
confirme une condition de verrouillage en direct et
panique le noyau de manière à fournir le rapport de bug le plus détaillé
.
La vérification lldk
persiste en continu lorsque la condition de verrouillage en direct existe et
recherche les chaînes composées symbol+0x
ou symbol.cfi+0x
dans
/proc/pid/stack
sous Linux. La liste des symboles se trouve dans ro.llk.stack
et
par défaut est la liste de valeurs séparées par des virgules
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
Les symboles doivent être rares et avoir une durée de vie suffisamment courte pour que, sur un système classique,
n'est visible qu'une seule fois dans un échantillon au cours du délai d'expiration de
ro.llk.stack.timeout_ms
(les échantillons sont tous les ro.llk.check_ms
). En raison d'un manque
de la protection ABA, c'est le seul moyen
d'éviter un faux déclencheur. Le symbole
doit apparaître sous la fonction appelant le verrou qui pourrait entrer en conflit. Si
le cadenas se trouve en dessous ou dans la fonction de symbole, le symbole apparaît dans tous les
processus, pas seulement celui
qui a provoqué le logo complet.
Couverture
L'implémentation par défaut de llkd
ne surveille pas init
, [kthreadd]
ni
[kthreadd]
est généré. Pour que llkd
couvre les threads générés par [kthreadd]
:
- Les pilotes ne doivent pas rester à l'état "D" persistant,
OU
- Les pilotes doivent disposer de mécanismes pour récupérer le thread en cas de fermeture
en externe. Par exemple, utilisez
wait_event_interruptible()
au lieu dewait_event()
Si l'une des conditions ci-dessus est remplie, la liste de blocage llkd
peut être ajustée pour
les composants du noyau. La vérification des symboles de pile implique un processus supplémentaire
liste de blocage pour éviter le non-respect des règles sur les services qui bloquent ptrace
opérations.
Propriétés Android
llkd
répond à plusieurs propriétés Android (répertoriées ci-dessous).
- Les propriétés nommées
prop_ms
sont exprimées en millisecondes. - Les propriétés qui utilisent une virgule (,) pour les listes doivent être précédées d'un séparateur pour :
conserver l'entrée par défaut, puis ajouter ou soustraire des entrées avec le signe plus (facultatif)
(+) et moins (-), respectivement. Pour ces listes, la chaîne
false
est synonyme de liste vide, et les entrées vides ou manquantes ont recours au la valeur par défaut spécifiée.
ro.config.low_ram
L'appareil est configuré avec une mémoire limitée.
ro.debuggable
L'appareil est configuré pour le débogage utilisateur ou le build eng.
ro.llk.sysrq_t
Si la propriété est eng
, la valeur par défaut n'est pas ro.config.low_ram
ni ro.debuggable
.
Si la valeur est true
, videz tous les threads (sysrq t
).
ro.llk.enable
Autoriser l'activation du daemon de verrouillage en direct. La valeur par défaut est false
.
llk.enable
Évalué pour les builds d'ingénieur. La valeur par défaut est ro.llk.enable
.
ro.kskutask.enable
Autorisez l'activation du daemon [khungtask]
. La valeur par défaut est false
.
kskutask.enable
Évalué pour les builds d'ingénieur. La valeur par défaut est ro.khungtask.enable
.
ro.k.mlockall
Activer l'appel à mlockall()
. La valeur par défaut est false
.
ro.kskutask.timeout
Durée maximale : [khungtask]
. La valeur par défaut est de 12 minutes.
ro.llk.timeout_ms
Limite de temps maximale D ou Z. La valeur par défaut est de 10 minutes. Doublez cette valeur pour définir
watchdog de l'alarme pour llkd
.
ro.llk.D.timeout_ms
D : durée maximale. La valeur par défaut est ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Limite de temps maximale Z. La valeur par défaut est ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms
Vérifie la limite de temps maximale des symboles de pile persistants. La valeur par défaut est
ro.llk.timeout_ms
Actif uniquement sur les builds userdebug ou eng.
ro.llk.check_ms
Échantillons de threads pour D ou Z. La valeur par défaut est de deux minutes.
ro.llk.stack
Vérifie les symboles de pile du noyau qui, s'ils sont présents de manière persistante, peuvent indiquer un
le sous-système est verrouillé. La valeur par défaut est
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
de symboles de noyau séparés par une virgule. La vérification n'effectue pas de planification ultérieure
ABA, sauf en interrogeant tous les ro.llk_check_ms
de la période
ro.llk.stack.timeout_ms
. Les symboles de pile doivent donc être exceptionnellement rares et
brèves (il est très peu probable qu'un symbole apparaisse de façon persistante
échantillons de la pile). Recherche une correspondance pour symbol+0x
ou
symbol.cfi+0x
dans le développement de la pile. Disponible uniquement sur userdebug ou eng
builds; les problèmes de sécurité sur les builds d'utilisateur entraînent des privilèges limités
empêcher cette vérification.
ro.llk.black.process
llkd
ne surveille pas les processus spécifiés. La valeur par défaut est 0,1,2
(kernel
,
init
et [kthreadd]
) ainsi que les noms des processus
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
Un processus peut être une référence comm
, cmdline
ou pid
. Une option automatisée par défaut
peut être supérieure à la taille de propriété maximale actuelle (92).
ro.llk.noir.parent
llkd
ne surveille pas les processus dont les parents sont spécifiés. Par défaut
correspond à 0,2,adbd&[setsid]
(kernel
, [kthreadd]
et adbd
uniquement pour les attaques
setsid
). L'esperluette (&) indique que le parent est uniquement ignoré
en combinaison avec le processus enfant cible. Esperluette a été sélectionnée, car elle
ne fait jamais partie d'un nom de processus ; Toutefois, un setprop
dans le shell nécessite
esperluette doit être échappée ou citée entre guillemets, bien que le fichier init rc
, où il s'agit
spécifié ne présente pas ce problème. Un processus parent ou cible peut être
Référence comm
, cmdline
ou pid
.
ro.llk.noir.uid
llkd
ne surveille pas les processus correspondant aux UID spécifiés.
Liste de numéros ou de noms UIS séparés par une virgule. La valeur par défaut est vide ou false
.
ro.llk.black.process.stack
llkd
ne surveille pas la pile de verrouillage en direct pour le sous-ensemble de processus spécifié
signatures. La valeur par défaut est le nom des processus
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
Empêche la règle sepolicy
de violation associée aux processus qui bloquent ptrace
(car ils ne peuvent pas être
cochée). Actif uniquement sur les builds userdebug et eng. Pour en savoir plus sur la compilation
consultez l'article Compiler Android.
Problèmes architecturaux
- Les propriétés sont limitées à 92 caractères (ce paramètre est ignoré pour les valeurs par défaut)
défini dans le fichier
include/llkd.h
des sources). - Le daemon
[khungtask]
intégré est trop générique et génère des trajets avec du code reste trop souvent à l'état D. Passer à S rendrait les tâches impossibles (et resurresible par les conducteurs si nécessaire).
Interface de la bibliothèque (facultatif)
Vous pouvez éventuellement intégrer llkd
dans un autre daemon privilégié à l'aide de
l'interface C suivante à partir du composant libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Si un nom de thread est fourni, un thread est automatiquement généré, sinon l'appelant
doit appeler llkCheckMilliseconds
dans sa boucle principale. La fonction renvoie
avant le prochain appel attendu de ce gestionnaire.