Android 10 enthält den Android-Live-Lock-Daemon (llkd
), der Kernel-Deadlocks erkennen und beheben soll. Die llkd
-Komponente bietet eine standardmäßige eigenständige Implementierung. Alternativ können Sie den llkd
-Code in einen anderen Dienst einbinden, entweder als Teil der Hauptschleife oder als separaten Thread.
Erkennungsszenarien
Für die llkd
gibt es zwei Erkennungsszenarien: Dauerhafter D‑ oder Z‑Zustand und dauerhafte Stacksignatur.
Dauerhafter D- oder Z-Zustand
Wenn sich ein Thread im Status „D“ (unveränderlicher Ruhezustand) oder „Z“ (Zombie) befindet und länger als ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
Minuten lang keine Fortschritte macht, beendet llkd
den Prozess (oder übergeordneten Prozess). Wenn bei einem nachfolgenden Scan derselbe Prozess weiterhin vorhanden ist, bestätigt llkd
eine Live-Sperrung und versetzt den Kernel in Panik, sodass der detaillierteste Fehlerbericht für die Situation erstellt wird.
Der llkd
enthält einen Selbst-Watchdog, der Alarm schlägt, wenn llkd
hängt. Der Watchdog ist doppelt so lang wie die erwartete Zeit, die für die Ausführung des Mainloops erforderlich ist, und die Stichprobenerhebung erfolgt alle ro.llk_sample_ms
.
Persistente Stacksignatur
Bei Releases vom Typ „userdebug“ kann die llkd
Kernel-Live-Sperrungen mithilfe einer persistenten Stacksignaturprüfung erkennen. Wenn ein Thread in einem beliebigen Status außer Z ein dauerhaft aufgeführtes ro.llk.stack
-Kernelsymbol hat, das länger als ro.llk.timeout_ms
oder ro.llk.stack.timeout_ms
gemeldet wird, beendet llkd
den Prozess, auch wenn die Vorwärtsplanung fortschreitet. Wenn bei einem nachfolgenden Scan derselbe Prozess weiterhin vorhanden ist, bestätigt llkd
eine Live-Sperrung und versetzt den Kernel in Panik, um den detailliertesten Fehlerbericht für die Situation zu erhalten.
Die lldk
-Prüfung wird kontinuierlich beibehalten, wenn die Bedingung für die Live-Sperre erfüllt ist, und sucht unter Linux in der Datei /proc/pid/stack
nach den zusammengesetzten Strings symbol+0x
oder symbol.cfi+0x
. Die Liste der Symbole befindet sich in ro.llk.stack
und ist standardmäßig eine durch Kommas getrennte Liste von cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
.
Symbole sollten so selten und kurzlebig sein, dass die Funktion in einem typischen System über das Zeitlimit von ro.llk.stack.timeout_ms
nur einmal in einer Stichprobe zu sehen ist (Beispiele erscheinen alle ro.llk.check_ms
). Aufgrund des fehlenden ABA-Schutzes ist dies die einzige Möglichkeit, einen falschen Trigger zu verhindern. Die Symbolfunktion muss unter der Funktion angezeigt werden, die die fragliche Sperre aufruft. Wenn sich das Schloss unterhalb oder in der Symbolfunktion befindet, wird das Symbol in allen betroffenen Prozessen angezeigt, nicht nur in dem, der das Lockup verursacht hat.
Abdeckung
Die Standardimplementierung von llkd
überwacht keine Spawns vom Typ init
, [kthreadd]
oder [kthreadd]
. Für llkd
, um [kthreadd]
-erzeugte Threads abzudecken:
- Fahrer dürfen sich nicht dauerhaft im D-Status befinden.
ODER
- Treiber müssen Mechanismen zum Wiederherstellen des Threads haben, falls er extern beendet wird. Verwenden Sie z. B.
wait_event_interruptible()
stattwait_event()
.
Wenn eine der oben genannten Bedingungen erfüllt ist, kann die llkd
-Deaktivierungsliste so angepasst werden, dass sie Kernelkomponenten umfasst. Die Stacksymbolprüfung umfasst eine zusätzliche Prozess-Denylist, um Verstöße gegen die SE-Richtlinie bei Diensten zu verhindern, die ptrace
-Vorgänge blockieren.
Android-Properties
Die llkd
reagiert auf mehrere Android-Properties (siehe unten).
- Für Properties mit dem Namen
prop_ms
werden Millisekunden verwendet. - Bei Eigenschaften, in denen für Listen ein Komma (,) als Trennzeichen verwendet wird, wird ein vorangestelltes Trennzeichen verwendet, um den Standardeintrag beizubehalten. Anschließend werden Einträge mit optionalen Pluszeichen (+) bzw. Minus (-) hinzugefügt oder subtrahiert. Bei diesen Listen steht der String
false
für eine leere Liste. Leere oder fehlende Einträge werden durch den angegebenen Standardwert ersetzt.
ro.config.low_ram
Das Gerät ist mit begrenztem Arbeitsspeicher konfiguriert.
ro.debuggable
Das Gerät ist für UserDebug oder Engine-Build konfiguriert.
ro.llk.sysrq_t
Wenn die Property eng
ist, ist der Standardwert nicht ro.config.low_ram
oder ro.debuggable
.
Wenn true
, werden alle Threads gedumpt (sysrq t
).
ro.llk.enable
Aktivieren des Live-Lock-Daemons zulassen. Die Standardeinstellung ist false
.
llk.enable
Für Entwickler-Builds bewertet. Die Standardeinstellung ist ro.llk.enable
.
ro.khungtask.enable
Aktivieren des [khungtask]
-Daemons zulassen. Der Standardwert ist false
.
khungtask.enable
Wird für eng-Builds ausgewertet. Die Standardeinstellung ist ro.khungtask.enable
.
ro.llk.mlockall
Aktivieren Sie den Aufruf von mlockall()
. Der Standardwert ist false
.
ro.khungtask.timeout
[khungtask]
als maximales Zeitlimit. Der Standardwert ist 12 Minuten.
ro.llk.timeout_ms
D oder Z für das maximale Zeitlimit. Der Standardwert ist 10 Minuten. Verdoppeln Sie diesen Wert, um den Alarm-Watchdog für llkd
festzulegen.
ro.llk.D.timeout_ms
D Maximales Zeitlimit Die Standardeinstellung ist ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Z maximales Zeitlimit. Die Standardeinstellung ist ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms
Prüft, ob das Zeitlimit für persistente Stacksymbole überschritten wurde. Der Standardwert ist ro.llk.timeout_ms
. Nur bei userdebug- oder eng-Builds aktiv.
ro.llk.check_ms
Musterbeispiele für D- oder Z-Glieder Der Standardwert ist zwei Minuten.
ro.llk.stack
Prüft auf Kernel-Stack-Symbole, die darauf hinweisen können, dass ein Subsystem gesperrt ist. Der Standardwert ist die durch Kommas getrennte Liste cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
von Kernel-Symbolen. Die Prüfung führt keine Forward-Planung für ABA aus, außer dass alle ro.llk_check_ms
im Zeitraum ro.llk.stack.timeout_ms
abgefragt werden. Daher sollten Stapelsymbole sehr selten und kurzlebig sein (es ist sehr unwahrscheinlich, dass ein Symbol dauerhaft in allen Stichproben des Stacks auftaucht). Prüft bei der Stapelerweiterung auf Übereinstimmung mit symbol+0x
oder symbol.cfi+0x
. Nur für Userdebug- oder eng-Builds verfügbar: Sicherheitsbedenken bei User-Builds führen zu eingeschränkten Berechtigungen, die diese Prüfung verhindern.
ro.llk.blacklist.process
llkd
überwacht die angegebenen Prozesse nicht. Der Standardwert ist 0,1,2
(kernel
, init
und [kthreadd]
) plus die Prozessnamen init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
.
Ein Prozess kann eine comm
-, cmdline
- oder pid
-Referenz sein. Ein automatischer Standard kann größer als die aktuelle maximale Unterkunftsgröße von 92 sein.
ro.llk.blacklist.parent
Die llkd
überwacht keine Prozesse mit den angegebenen übergeordneten Elementen. Der Standardwert ist 0,2,adbd&[setsid]
(kernel
, [kthreadd]
und adbd
nur für Zombiesetsid
). Ein kaufmännisches Und-Zeichen (&) gibt an, dass das übergeordnete Element nur in Kombination mit dem Zielunterprozess ignoriert wird. Das Andzeichen wurde ausgewählt, da es nie Teil eines Prozessnamens ist. Bei einer setprop
in der Shell muss das Andzeichen jedoch mit einem Escape-Zeichen oder in Anführungszeichen gesetzt werden. In der init rc
-Datei, in der dies normalerweise angegeben wird, tritt dieses Problem nicht auf. Ein übergeordneter oder Zielprozess kann eine comm
-, cmdline
- oder pid
-Referenz sein.
ro.llk.blacklist.uid
Die llkd
überwacht keine Prozesse, die mit den angegebenen UIDs übereinstimmen.
Durch Kommas getrennte Liste von UIS-Nummern oder ‑Namen. Der Standardwert ist leer oder false
.
ro.llk.blacklist.process.stack
Der llkd
überwacht die angegebene Teilmenge von Prozessen nicht auf Live-Sperrbalken-Stacksignaturen. Standardmäßig werden Prozessnameninit,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
verwendet. Verhindert den Sepolicy-Verstoß, der mit Prozessen verbunden ist, die ptrace
blockieren, da diese nicht geprüft werden können. Nur bei userdebug- und eng-Builds aktiv. Weitere Informationen zu Build-Typen finden Sie unter Android erstellen.
Architekturbezogene Bedenken
- Attribute sind auf 92 Zeichen beschränkt. Bei Standardeinstellungen, die in der Datei
include/llkd.h
in den Quellen definiert sind, wird dies jedoch ignoriert. - Der integrierte
[khungtask]
-Daemon ist zu allgemein und löst bei Treibercode aus, der zu viel im D-Zustand verharrt. Wenn Sie zu „S“ wechseln, können Aufgaben beendet und bei Bedarf von Treibern wiederhergestellt werden.
Bibliotheksoberfläche (optional)
Optional können Sie llkd
mithilfe der folgenden C-Schnittstelle aus der libllkd
-Komponente in einen anderen privilegierten Daemon einbinden:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Wenn ein Threadname angegeben wird, wird ein Thread automatisch erstellt. Andernfalls muss der Aufrufer llkCheckMilliseconds
in seiner Hauptschleife aufrufen. Die Funktion gibt den Zeitraum vor dem nächsten erwarteten Aufruf an diesen Handler zurück.