Android 10, çekirdek kilitlenmelerini yakalayıp azaltmak için tasarlanmış Android canlı kilitlenme hizmetini (llkd
) içerir. llkd
bileşeni varsayılan olarak bağımsız bir uygulama sağlar ancak llkd
kodunu ana döngünün parçası olarak veya ayrı bir iş parçacığı olarak başka bir hizmete entegre edebilirsiniz.
Algılama senaryoları
llkd
iki algılama senaryosuna sahiptir: Kalıcı D veya Z durumu ve kalıcı yığın imzası.
Kalıcı D veya Z durumu
Bir iş parçacığı ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
'ten uzun süre boyunca ileriye doğru ilerleme kaydedemeden D (kesintiye uğramayan uyku) veya Z (zombi) durumundaysa llkd
, süreci (veya üst süreci) öldürür. Sonraki taramada, aynı sürecin devam ettiği belirlenirse llkd
, bir canlı kilit koşulunu onaylar ve çekirdeği, durum için en ayrıntılı hata raporunu sağlayacak şekilde panikler.
llkd
, llkd
kilitlenirse alarm veren bir kendi kendine gözetleyici içerir. Gözetleyici, ana döngüde akışın beklenen süresinin iki katı kadardır ve örnekleme her ro.llk_sample_ms
saniyede bir yapılır.
Kalıcı yığın imzası
Kullanıcı hata ayıklama sürümlerinde llkd
, kalıcı yığın imzası kontrolünü kullanarak çekirdek canlı kilitlerini algılayabilir. Z dışındaki herhangi bir durumdaki bir iş parçacığında, ro.llk.timeout_ms
veya ro.llk.stack.timeout_ms
'den daha uzun süre boyunca bildirilen kalıcı bir listelenen ro.llk.stack
çekirdek simgesi varsa llkd
, ileri planlama ilerleme kaydetse bile süreci sonlandırır. Sonraki bir tarama aynı işlemin devam ettiğini gösteriyorsa llkd
, canlı kilit durumunu onaylar ve çekirdeği, durumla ilgili en ayrıntılı hata raporunu sağlayacak şekilde paniğe sürükler.
Canlı kilit koşulu mevcut olduğunda lldk
kontrolü sürekli olarak devam eder ve Linux'daki /proc/pid/stack
dosyasında symbol+0x
veya symbol.cfi+0x
birleşik dizelerini arar. Simge listesi ro.llk.stack
içindedir ve varsayılan olarak virgülle ayrılmış cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
listesindedir.
Semboller, tipik bir sistemde işlevin ro.llk.stack.timeout_ms
zaman aşımı süresi boyunca bir örnekte yalnızca bir kez görülebilecek kadar nadir ve kısa ömürlü olmalıdır (örnekler her ro.llk.check_ms
aralığında olur). ABA koruması olmadığından, yanlış tetiklemeyi önlemenin tek yolu budur. Simge işlevi, kilidi çağıran ve rekabet edebilecek işlevin altında görünmelidir. Kilit, simge işlevinin altında veya içindeyse simge yalnızca kilitlenmeye neden olan işlemde değil, etkilenen tüm işlemlerde görünür.
Kapsam
Varsayılan llkd
uygulaması init
, [kthreadd]
veya [kthreadd]
ortaya çıkanları izlemiyor. llkd
'ün, [kthreadd]
tarafından oluşturulan ileti dizilerini kapsaması için:
- Sürücüler sürekli D durumunda kalmamalıdır.
VEYA
- Sürücüler, harici olarak sonlandırılırsa iş parçacığının kurtarılacağı mekanizmalara sahip olmalıdır. Örneğin,
wait_event()
yerinewait_event_interruptible()
kullanın.
Yukarıdaki koşullardan biri karşılanırsa llkd
ret listesi, çekirdek bileşenlerini kapsayacak şekilde ayarlanabilir. Yığın sembolü kontrolü, ptrace
işlemlerini engelleyen hizmetlerde güvenlik politikası ihlallerini önlemek için ek bir işlem engellenenler listesi içerir.
Android mülkleri
llkd
, çeşitli Android özelliklerine (aşağıda listelenmiştir) yanıt verir.
prop_ms
adlı özellikler milisaniye cinsindendir.- Listeler için virgül (,) ayırıcı kullanan özellikler, varsayılan girişi korumak için baştaki ayırıcıyı kullanır. Ardından, girişleri isteğe bağlı artı (+) ve eksi (-) ön ekleriyle ekleyebilir ya da çıkarabilirsiniz. Bu listelerde
false
dizesi boş listeyle eş anlamlıdır ve boş veya eksik girişler, belirtilen varsayılan değere başvurur.
ro.config.low_ram
Cihaz sınırlı bellekle yapılandırılmış.
ro.debuggable
Cihaz, userdebug veya eng derlemesi için yapılandırılmıştır.
ro.llk.sysrq_t
Mülk eng
ise varsayılan değer ro.config.low_ram
veya ro.debuggable
değildir.
true
ise tüm ileti dizilerini dökümü (sysrq t
).
ro.llk.etkin
Canlı kilit arka plan programının etkinleştirilmesine izin ver. false
varsayılandır.
llk.enable
eng derlemeleri için değerlendirilir. ro.llk.enable
varsayılandır.
ro.khungtask.enable
[khungtask]
arka plan programının etkinleştirilmesine izin ver. Varsayılan değer false
'tir.
khungtask.enable
eng derlemeleri için değerlendirilir. ro.khungtask.enable
varsayılandır.
ro.llk.mlockall
mlockall()
hedefine yapılan aramayı etkinleştirin. Varsayılan değer false
'tir.
ro.khungtask.timeout
[khungtask]
maksimum zaman sınırı. Varsayılan ayar 12 dakikadır.
ro.llk.timeout_ms
D veya Z maksimum süre sınırı. Varsayılan ayar 10 dakikadır. Alarm gözetimini llkd
için ayarlamak üzere bu değeri ikiye katlayın.
ro.llk.D.timeout_ms
Maksimum D zaman sınırı. ro.llk.timeout_ms
varsayılandır.
ro.llk.Z.timeout_ms
Z maksimum zaman sınırı. ro.llk.timeout_ms
varsayılandır.
ro.llk.stack.timeout_ms
Kalıcı yığın simgeleri için maksimum süre sınırı olup olmadığını kontrol eder. Varsayılan değer ro.llk.timeout_ms
'tir. Yalnızca userdebug veya eng derlemelerinde etkindir.
ro.llk.check_ms
D veya Z için ileti dizisi örnekleri. Varsayılan değer iki dakikadır.
ro.llk.stack
Sürekli mevcut olması bir alt sistemin kilitli olduğunu gösterebileceği çekirdek yığını sembolleri olup olmadığını kontrol eder. Varsayılan olarak
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
çekirdek simgelerinin virgülle ayrılmış listesidir. Bu kontrol, ro.llk.stack.timeout_ms
dönemi boyunca her ro.llk_check_ms
yoklama işlemi dışında ABA'yı yönlendirmez. Bu nedenle, yığın simgeleri son derece nadir ve kısa olmalıdır (Bir simgenin, yığının tüm örneklerinde sürekli olarak görünmesi çok düşük bir olasılıktır). Yığın genişletmede symbol+0x
veya symbol.cfi+0x
için eşleşme olup olmadığını kontrol eder. Yalnızca userdebug veya eng derlemelerinde kullanılabilir. Kullanıcı derlemelerindeki güvenlik endişeleri, bu kontrolün yapılmasını engelleyen sınırlı ayrıcalıklara neden olur.
ro.llk.blacklist.process
llkd
, belirtilen işlemleri izlemez. Varsayılan değer, 0,1,2
(kernel
, init
ve [kthreadd]
) ile birlikte işlem adlarıdırinit,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
.
Bir işlem; comm
, cmdline
veya pid
referansı olabilir. Otomatik varsayılan, mevcut maksimum mülk boyutu olan 92'den daha büyük olabilir.
ro.llk.Blacklist.parent
llkd
, belirtilen üst öğelere sahip işlemleri izlemez. Varsayılan değer 0,2,adbd&[setsid]
'tür (yalnızca zombi setsid
için kernel
, [kthreadd]
ve adbd
). & ayırıcı, üst öğenin yalnızca hedef alt işlemle birlikte dikkate alınacağını belirtir. "Ve" işareti, hiçbir zaman bir işlem adının parçası olmadığı için seçilmiştir. Ancak kabukta bir setprop
varsa "ve" işaretinin tırnak içine alınması veya tırnak işareti ile çevrilmesi gerekir. Bununla birlikte, bu işaretin normalde belirtildiği init rc
dosyasında bu sorun yoktur. Üst veya hedef işlem, comm
, cmdline
veya pid
referansı olabilir.
ro.llk.blacklist.uid
llkd
, belirtilen UID'lerle eşleşen işlemleri izlemez.
UIS numaralarının veya adlarının virgülle ayrılmış listesi. Varsayılan değer boş veya false
'tir.
ro.llk.karaliste.süreç.stack
llkd
, canlı kilit yığını imzaları için belirtilen işlem alt kümesini izlemez. Varsayılan değer, işlem adlarıdırinit,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. ptrace
hizmetini engelleyen işlemler (kontrol edilememesi nedeniyle) ile ilişkili sepolicy ihlalini önler. Yalnızca userdebug ve eng derlemelerinde etkindir. Derleme türleriyle ilgili ayrıntılar için Android Derleme konusuna bakın.
Mimari endişeler
- Özellikler 92 karakterle sınırlıdır (ancak kaynaklardaki
include/llkd.h
dosyasında tanımlanan varsayılan değerler için bu sınır yoksayılır). - Yerleşik
[khungtask]
daemon'ı çok geneldir ve D durumunda çok fazla duran sürücü kodunda takılır. S'ye geçmek görevler tamamlanabilir (ve gerekirse sürücüler tarafından yeniden canlanabilir) hâle gelir.
Kitaplık arayüzü (isteğe bağlı)
İsteğe bağlı olarak, libllkd
bileşenindeki aşağıdaki C arayüzünü kullanarak llkd
'ü başka bir ayrıcalıklı daemon'a dahil edebilirsiniz:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Bir ileti dizisi adı sağlanırsa ileti dizisi otomatik olarak oluşturulur. Aksi takdirde, arayan ana döngüsünde llkCheckMilliseconds
çağrısı yapmalıdır. İşlev, bu işleyiciye yapılacak bir sonraki beklenen çağrıdan önceki süreyi döndürür.