Android canlı kilit arka plan programı (llkd)

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() yerine wait_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.