Demon blokady na żywo na Androidzie (llkd)

Android 10 zawiera demona aktywnej blokady Androida (llkd), która służy do wychwytywania i ograniczania wzajemnych blokad jądra. llkd udostępnia domyślną, samodzielną implementację, ale możesz możesz też zintegrować kod llkd z inną usługą, jako część w ramach pętli głównej lub osobnego wątku.

Scenariusze wykrywania

llkd ma 2 scenariusze wykrywania: stały D lub stan Z oraz trwały podpis stosu.

Stały stan D lub Z

Jeśli wątek jest w stanie D (uśpienie niezakłócone) lub Z (zombie) bez przekierowania postęp w czasie dłuższym niż ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms, llkd kończy proces (lub proces nadrzędny). Jeśli podczas kolejnego skanowania zobaczysz nadal trwa ten sam proces, llkd potwierdza warunek blokady transmisji na żywo, a następnie panuje w jądrze w sposób, który dostarcza najdokładniejszego raportu o błędach .

Urządzenie llkd zawiera własny watchdog, który alarmuje, gdy llkd się blokuje. watchdog to dwukrotnie wydłuża spodziewany czas przepływania przez pętlę główną, a próbkowanie ro.llk_sample_ms

Podpis trwałego stosu

W przypadku wersji do debugowania użytkownika llkd może wykrywać blokady aktywnego jądra systemu za pomocą trwałych na stosie kont. Jeśli wątek w dowolnym stanie innym niż Z ma trwały został podany symbol jądra systemu ro.llk.stack, który jest zgłaszany od okresu dłuższego niż ro.llk.timeout_ms lub ro.llk.stack.timeout_ms, llkd eliminuje proces (nawet jeśli trwa planowanie do przodu). Jeśli podczas kolejnego skanowania zobaczysz nadal trwa ten sam proces, llkd potwierdza warunek blokady transmisji na żywo, a następnie panuje w jądrze w sposób, który dostarcza najdokładniejszego raportu o błędach .

Kontrola lldk jest kontynuowana bez przerwy, gdy istnieje warunek aktywnej blokady. wyszukuje utworzone ciągi znaków symbol+0x lub symbol.cfi+0x w funkcji /proc/pid/stack w systemie Linux. Lista symboli znajduje się w językach: ro.llk.stack i domyślnie przyjmuje wartość rozdzielaną przecinkami listę cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable

Symbole powinny być rzadkie i wystarczająco krótkie, aby w typowym systemie jest występująca tylko raz w próbce po upływie limitu czasu wynoszącego ro.llk.stack.timeout_ms (próbki pojawiają się co ro.llk.check_ms). Z powodu braku ochrony ABA, to jedyny sposób zapobiegania błędnemu wywołaniu. Symbol musi być widoczna pod funkcją wywołującą blokadę, która może konkurować. Jeśli kłódka znajduje się poniżej lub w funkcji symboli, symbol jest widoczny we wszystkich odpowiednich z procesów, a nie tylko tych, które doprowadziły do powstania układu.

Pokrycie

Domyślna implementacja llkd nie monitoruje init, [kthreadd] ani Pojawia się [kthreadd]. Aby element llkd obejmował [kthreadd] wątków utworzonych przez użytkownika:

  • Sterowniki nie mogą pozostawać w trwałym stanie D.

LUB

  • Sterowniki muszą mieć mechanizmy umożliwiające odzyskanie wątku w przypadku jego utracenia na zewnątrz. Na przykład użyj wait_event_interruptible() zamiast wait_event()

Jeśli spełniony jest jeden z powyższych warunków, listę odrzuconych llkd można dostosować do: i uwzględniają komponenty jądra. Sprawdzanie symbolu stosu wiąże się z dodatkowym procesem lista odrzuconych, aby zapobiec naruszeniom zasad w usługach, które blokują ptrace operacji.

Usługi na Androida

llkd działa w przypadku kilku usług na Androidzie (wymienionych poniżej).

  • Właściwości o nazwie prop_ms są podane w milisekundach.
  • Właściwości, które używają separatora przecinka (,) w przypadku list, używają separatora wiodącego, aby zachowaj domyślną pozycję, a następnie dodaj lub odejmij wpisy z opcjonalnym plusem prefiksy (+) i minus (-). W przypadku tych list ciąg false jest synonimem pustej listy, a puste lub brakujące wpisy odwołują się do określoną wartość domyślną.

ro.config.low_ram

Urządzenie jest skonfigurowane z ograniczoną pamięcią.

ro.debuggable

Urządzenie jest skonfigurowane na potrzeby debugowania użytkowników lub kompilacji angielskiej.

ro.llk.sysrq_t,

Jeśli właściwość to eng, wartość domyślna nie jest wartością ro.config.low_ram ani ro.debuggable. Jeśli zasada true, powoduje wykonanie zrzutu wszystkich wątków (sysrq t).

ro.llk.enable

Zezwól na włączanie demona aktywnej blokady. Domyślna wartość to false.

llk.enable

Oceniane pod kątem kompilacji rozszerzonych. Domyślna wartość to ro.llk.enable.

ro.khungtask.enable

Zezwalaj na włączanie demona [khungtask]. Wartość domyślna to false.

khungtask.enable

Oceniane pod kątem kompilacji rozszerzonych. Domyślna wartość to ro.khungtask.enable.

ro.llk.mlockall

Włącz połączenie z numerem mlockall(). Wartość domyślna to false.

ro.khungtask.timeout

Maksymalny limit czasu: [khungtask]. Wartość domyślna to 12 minut.

ro.llk.timeout_ms

Maksymalny limit czasu D lub Z. Wartość domyślna to 10 minut. Podwój tę wartość, aby ustawić watchdoga alarmu na llkd.

ro.llk.D.timeout_ms

Maksymalny limit czasu D. Domyślna wartość to ro.llk.timeout_ms.

ro.llk.Z.timeout_ms

Maksymalny limit czasu Z. Domyślna wartość to ro.llk.timeout_ms.

ro.llk.stack.timeout_ms,

Sprawdza maksymalny limit czasu symboli trwałego stosu. Wartość domyślna to ro.llk.timeout_ms Aktywna tylko w przypadku debugowania użytkowników i kompilacji angielskich.

ro.llk.check_ms

Przykłady wątków dla D lub Z. Wartość domyślna to 2 minuty.

ro.llk.stack,

Sprawdza, czy występują symbole stosu jądra, które jeśli są stale obecne, mogą wskazywać podsystem jest zablokowany. Wartość domyślna to cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable rozdzielana przecinkami lista symboli jądra. Sprawdzenie nie powoduje skierowania do przodu ABA z wyjątkiem sondy co ro.llk_check_ms w danym okresie ro.llk.stack.timeout_ms, dlatego symbole stosu powinny być wyjątkowo rzadkie, przelotne (jest mało prawdopodobne, aby symbol był stale widoczny w całym miejscu) przykłady stosu). Sprawdza, czy symbol+0x pasuje do dopasowania lub symbol.cfi+0x w rozwinięciu stosu. Dostępne tylko w przypadku debugowania użytkownika lub instrukcji kompilacje; obawy związane z zabezpieczeniami kompilacji użytkownika skutkują ograniczonymi uprawnieniami, zapobiec tej kontroli.

ro.llk.blacklist.process,

llkd nie obserwuje określonych procesów. Wartość domyślna to 0,1,2 (kernel, init i [kthreadd]) oraz nazwy procesów init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]. Proces może być odwołaniem do comm, cmdline lub pid. Automatyczna wartość domyślna może być większy niż bieżący maksymalny rozmiar usługi wynoszący 92.

ro.llk.blacklist.parent,

llkd nie obserwuje procesów, w których są określone elementy nadrzędne. Domyślne to 0,2,adbd&[setsid] (kernel, [kthreadd] i adbd tylko dla zombie setsid). Separator „&” oznacza, że element nadrzędny jest tylko ignorowany w połączeniu z docelowym procesem podrzędnym. Wybrano znak „ampersand”, ponieważ nie jest nigdy częścią nazwy procesu; jednak setprop w powłoce wymaga ampersand, w którym ma być cudzysłowy lub cudzysłowu, ale w przypadku pliku init rc, w którym zwykle nie występuje. Proces nadrzędny lub docelowy może być Odwołanie do: comm, cmdline lub pid.

ro.llk.blacklist.uid,

llkd nie obserwuje procesów pasujących do określonych identyfikatorów UID. Lista rozdzielonych przecinkami numerów lub nazw UIS. Wartość domyślna jest pusta lub false.

ro.llk.blacklist.process.stack,

llkd nie monitoruje określonego podzbioru procesów na potrzeby bieżącego stosu blokady podpisy. Domyślnie są to nazwy procesów init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd Zapobiega sepolicy naruszenie związane z procesami, które blokują ptrace (ponieważ nie można ich zaznaczono). Aktywna tylko w przypadku debugowania użytkowników i kompilacji angielskich. Szczegółowe informacje o kompilacji można znaleźć w artykule o tworzeniu Androida.

Kwestie architektoniczne

  • Właściwości mogą mieć maksymalnie 92 znaki (ale w przypadku wartości domyślnych są ignorowane). zdefiniowane w pliku include/llkd.h w źródłach).
  • Wbudowany demon [khungtask] jest zbyt ogólny i korzysta z kodu kierowcy, który i za często są w stanie D. Przejście na S uniemożliwiłoby zakończenie zadań (w razie potrzeby być wznowiony przez kierowcę).

Interfejs biblioteki (opcjonalnie)

Opcjonalnie możesz włączyć llkd do innego demona z podwyższonymi uprawnieniami, posługując się ten interfejs C z komponentu libllkd:

#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void)   /* ms to sleep for next check */

Jeśli zostanie podana nazwa wątku, automatycznie pojawi się wątek. W przeciwnym razie obiekt wywołujący musi wywołać funkcję llkCheckMilliseconds w swojej głównej pętli. Funkcja zwraca okres przed kolejnym spodziewanym wywołaniem tego modułu obsługi.