Android 10, çekirdek kilitlenmelerini yakalamak ve azaltmak için tasarlanmış Android canlı kilit arka plan programını (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
boyunca ileri gitmeyecek şekilde D (kesintisiz uyku) veya Z (zombi) durumundaysa llkd
işlemi (veya üst işlemi) sonlandı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ı
userdebug sürümlerinde llkd
, kalıcı yığın imza kontrolü 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
llkd
'ün varsayılan uygulaması, init
, [kthreadd]
veya [kthreadd]
oluşturma işlemlerini izlemez. llkd
tarafından üretilen [kthreadd]
ileti dizilerinin kapsamı 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
denylist, ç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 mülkler, varsayılan girişi korumak için ön ayırıcı kullanır ve ardından isteğe bağlı artı (+) ve eksi (-) ön ekleriyle girişleri ekler veya çıkarır. 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
eng
ise varsayılan olarak ro.config.low_ram
veya ro.debuggable
değildir.
true
ise tüm ileti dizilerini dökümü (sysrq t
).
ro.llk.enable
Canlı kilit hizmet programının etkinleştirilmesine izin verin. false
varsayılandır.
llk.enable
eng derlemeleri için değerlendirilir. ro.llk.enable
varsayılandır.
ro.khungtask.enable
[khungtask]
daemon'unun etkinleştirilmesine izin verin. Varsayılan değer false
'tir.
khungtask.enable
Mühendislik derlemeleri için değerlendirildi. ro.khungtask.enable
varsayılandır.
ro.llk.mlockall
mlockall()
çağrısını etkinleştir. Varsayılan değer false
'tir.
ro.khungtask.timeout
Maksimum [khungtask]
süre sınırı. Varsayılan ayar 12 dakikadır.
ro.llk.timeout_ms
D veya Z maksimum süre sınırı. Varsayılan değer 10 dakikadır. llkd
için alarm güvenlik zamanlayıcısını
ayarlamak üzere bu değeri ikiye katlayın.
ro.llk.D.timeout_ms
D maksimum süre 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 sembolleri için maksimum süre sınırını kontrol eder. Varsayılan değer ro.llk.timeout_ms
'tir. Yalnızca userdebug veya eng derlemelerinde etkin.
ro.llk.check_ms
D veya Z için iplik örnekleri. Varsayılan değer iki dakikadır.
ro.llk.stack
Kalıcı olarak mevcut olması durumunda bir alt sistemin kilitlendiğini gösterebilecek çekirdek yığını sembollerini kontrol eder. Varsayılan değer, cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
virgülle ayrılmış çekirdek simgelerinin listesidir. Kontrol, ro.llk.stack.timeout_ms
döneminde her ro.llk_check_ms
saniyede bir anket yapmak dışında ABA'yı ileriye dönük planlamaz. Bu nedenle, yığın sembolleri son derece nadir ve kısa süreli olmalıdır (bir sembolün yığının tüm örneklerinde sürekli olarak görünmesi olasılığı çok düşüktür). Grup genişletmesinde symbol+0x
veya symbol.cfi+0x
ile 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]
.
İş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. Bununla birlikte, kabuktaki setprop
, "ve" işaretinin kod dışına alınmasını veya tırnak içine alınmasını gerektirir. Ancak bu değerin 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.blacklist.process.stack
llkd
, canlı kilit yığını imzaları için belirtilen işlem alt kümesini izlemez. İşlem adları varsayılan olarak init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
şeklindedir. ptrace
'yi engelleyen işlemlerle ilişkili sepolicy ihlalini önler (bunlar kontrol edilemediğinden). Yalnızca userdebug ve eng derlemelerinde etkindir. Derleme türleri hakkında ayrıntılı bilgi için Android'i derleme başlıklı makaleyi inceleyin.
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 moduna geçiş, görevlerin kapatılmasını (ve gerekirse sürücüler tarafından yeniden etkinleştirilmesini) sağlar.
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.