Android canlı kilit arka plan programı (llkd)

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