Android 10 menyertakan Android Live-Lock Daemon ( llkd
), yang dirancang untuk menangkap dan mengurangi kebuntuan kernel. Komponen llkd
menyediakan implementasi mandiri default, namun Anda juga dapat mengintegrasikan kode llkd
ke layanan lain, baik sebagai bagian dari loop utama atau sebagai thread terpisah.
Skenario deteksi
llkd
memiliki dua skenario deteksi: status D atau Z yang persisten, dan tanda tangan tumpukan yang persisten.
Status D atau Z yang persisten
Jika thread berada dalam status D (uninterruptible sleep) atau Z (zombie) tanpa progres lebih lama dari ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
, llkd
akan menghentikan proses (atau proses induk ). Jika pemindaian berikutnya menunjukkan proses yang sama tetap ada, llkd
mengonfirmasi kondisi live-lock dan membuat kernel panik dengan cara yang memberikan laporan bug paling detail untuk kondisi tersebut.
llkd
mencakup pengawas mandiri yang memberi peringatan jika llkd
terkunci; pengawas adalah dua kali lipat waktu yang diharapkan untuk mengalir melalui mainloop dan pengambilan sampel adalah setiap ro.llk_sample_ms
.
Tanda tangan tumpukan yang persisten
Untuk rilis userdebug, llkd
dapat mendeteksi live-lock kernel menggunakan pemeriksaan tanda tangan tumpukan yang persisten. Jika thread di negara bagian mana pun kecuali Z memiliki simbol kernel ro.llk.stack
yang terdaftar secara persisten dan dilaporkan lebih lama dari ro.llk.timeout_ms
atau ro.llk.stack.timeout_ms
, llkd
akan menghentikan proses (walaupun ada penerusan kemajuan penjadwalan). Jika pemindaian berikutnya menunjukkan proses yang sama tetap ada, llkd
mengonfirmasi kondisi live-lock dan membuat kernel panik dengan cara yang memberikan laporan bug paling detail untuk kondisi tersebut.
Pemeriksaan lldk
berlanjut terus menerus ketika kondisi live lock ada dan mencari string yang tersusun " symbol+0x"
atau " symbol.cfi+0x"
di file /proc/pid/stack
di Linux. Daftar simbol ada di ro.llk.stack
dan defaultnya adalah daftar " cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
" yang dipisahkan koma.
Simbol harus langka dan berumur pendek sehingga pada sistem tipikal, fungsinya hanya terlihat sekali dalam sampel selama periode waktu habis ro.llk.stack.timeout_ms
(sampel muncul setiap ro.llk.check_ms
). Karena kurangnya perlindungan ABA, ini adalah satu-satunya cara untuk mencegah pemicu palsu. Simbol fungsi harus muncul di bawah fungsi pemanggil kunci yang dapat bersaing. Jika kuncinya berada di bawah atau di dalam fungsi simbol, simbol tersebut akan muncul di semua proses yang terpengaruh, bukan hanya proses yang menyebabkan penguncian.
Cakupan
Implementasi default llkd
tidak memantau init
, [kthreadd]
, atau [kthreadd]
muncul. Agar llkd
menutupi [kthreadd]
- thread yang muncul:
- Pengemudi tidak boleh terus-menerus berada dalam kondisi D,
ATAU
- Pengemudi harus memiliki mekanisme untuk memulihkan thread jika thread tersebut dimatikan secara eksternal. Misalnya, gunakan
wait_event_interruptible()
alih-alihwait_event()
.
Jika salah satu kondisi di atas terpenuhi, daftar hitam llkd
dapat disesuaikan untuk mencakup komponen kernel. Pemeriksaan simbol tumpukan melibatkan proses daftar hitam tambahan untuk mencegah pelanggaran sepolicy pada layanan yang memblokir operasi ptrace
.
Properti Android
llkd
merespons beberapa properti Android (tercantum di bawah).
- Properti bernama
prop_ms
dalam milidetik. - Properti yang menggunakan pemisah koma (,) untuk daftar menggunakan pemisah di depan untuk mempertahankan entri default, lalu menambah atau mengurangi entri dengan awalan opsional plus (+) dan minus (-). Untuk daftar ini, string "false" identik dengan daftar kosong, dan entri kosong atau hilang menggunakan nilai default yang ditentukan.
ro.config.low_ram
Perangkat dikonfigurasi dengan memori terbatas.
ro.debuggable
Perangkat dikonfigurasi untuk userdebug atau eng build.
ro.llk.sysrq_t
Jika propertinya "eng", defaultnya bukan ro.config.low_ram
atau ro.debuggable
. Jika benar, buang semua thread ( sysrq t
).
ro.llk.enable
Izinkan daemon live-lock diaktifkan. Standarnya salah.
llk.enable
Dievaluasi untuk build bahasa Inggris. Standarnya adalah ro.llk.enable
.
ro.khungtask.enable
Izinkan daemon [khungtask]
diaktifkan. Standarnya salah.
khungtask.aktifkan
Dievaluasi untuk build bahasa Inggris. Standarnya adalah ro.khungtask.enable
.
ro.llk.mlockall
Aktifkan panggilan ke mlockall()
. Standarnya salah.
ro.khungtask.timeout
[khungtask]
batas waktu maksimum. Standarnya adalah 12 menit.
ro.llk.timeout_ms
Batas waktu maksimum D atau Z. Standarnya adalah 10 menit. Gandakan nilai ini untuk menyetel pengawas alarm untuk llkd
.
ro.llk.D.timeout_ms
D batas waktu maksimum. Standarnya adalah ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Z batas waktu maksimum. Standarnya adalah ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms
Memeriksa batas waktu maksimum simbol tumpukan yang persisten. Standarnya adalah ro.llk.timeout_ms
. Hanya aktif di userdebug atau eng builds .
ro.llk.check_ms
Contoh thread untuk D atau Z. Defaultnya adalah dua menit.
ro.llk.stack
Memeriksa simbol tumpukan kernel yang jika terus ada dapat mengindikasikan subsistem terkunci. Defaultnya adalah cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
Daftar simbol kernel yang dipisahkan koma. Pemeriksaan tidak melakukan penjadwalan maju ABA kecuali dengan melakukan polling setiap ro.llk_check_ms
selama periode ro.llk.stack.timeout_ms
, jadi simbol tumpukan harus sangat jarang dan cepat berlalu (sangat tidak mungkin simbol muncul terus-menerus di semua sampel tumpukan). Memeriksa kecocokan untuk " symbol+0x"
atau " symbol.cfi+0x"
dalam perluasan tumpukan. Hanya tersedia di userdebug atau eng build ; masalah keamanan pada build pengguna mengakibatkan terbatasnya hak istimewa yang mencegah pemeriksaan ini.
ro.llk.blacklist.proses
llkd
tidak memperhatikan proses yang ditentukan. Defaultnya adalah 0,1,2
( kernel
, init
, dan [kthreadd]
) ditambah nama proses init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
. Suatu proses dapat berupa referensi comm
, cmdline
, atau pid
. Default otomatis bisa lebih besar dari ukuran properti maksimum saat ini yaitu 92.
ro.llk.blacklist.parent
llkd
tidak mengawasi proses yang memiliki induk tertentu. Defaultnya adalah 0,2,adbd&[setsid]
( kernel
, [kthreadd]
, dan adbd
hanya untuk zombie setsid
). Pemisah ampersand (&) menetapkan bahwa induk diabaikan hanya jika dikombinasikan dengan proses anak target. Ampersand dipilih karena tidak pernah menjadi bagian dari nama proses; namun, setprop
di shell mengharuskan ampersand di-escape atau dikutip, meskipun file init rc
yang biasanya ditentukan tidak mengalami masalah ini. Proses induk atau target dapat berupa referensi comm
, cmdline
, atau pid
.
ro.llk.blacklist.uid
llkd
tidak mengawasi proses yang cocok dengan uid yang ditentukan. Daftar nomor atau nama uid yang dipisahkan koma. Defaultnya kosong atau salah.
ro.llk.blacklist.proses.stack
llkd
tidak memantau subset proses yang ditentukan untuk tanda tangan tumpukan kunci langsung. Defaultnya adalah nama proses init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. Mencegah pelanggaran sepolicy yang terkait dengan proses yang memblokir ptrace
(karena ini tidak dapat diperiksa). Hanya aktif di userdebug dan eng builds . Untuk mengetahui detail tentang tipe build, lihat Membangun Android .
Masalah arsitektur
- Properti dibatasi hingga 92 karakter (namun, ini diabaikan untuk default yang ditentukan dalam file
include/llkd.h
di sumber). - Daemon
[khungtask]
bawaan terlalu umum dan terlalu sering melakukan trip pada kode driver yang berada dalam status D. Beralih ke S akan membuat tugas dapat dihentikan (dan dapat dihidupkan kembali oleh pengemudi jika diperlukan).
Antarmuka perpustakaan (opsional)
Anda juga dapat memasukkan llkd
ke dalam daemon istimewa lainnya menggunakan antarmuka C berikut dari komponen libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Jika nama thread disediakan, thread otomatis muncul, jika tidak, pemanggil harus memanggil llkCheckMilliseconds
di loop utamanya. Fungsi ini mengembalikan periode waktu sebelum panggilan berikutnya yang diharapkan ke pengendali ini.