Android 即時鎖定 Daemon (llkd)

Android 10 包含 Android 即時鎖定 Daemon (llkd),用於擷取及減少核心死結。llkd 元件提供預設的獨立實作 您也可以將 llkd 程式碼整合到其他服務中, 主迴圈,或做為獨立執行緒。

偵測情境

llkd 有兩種偵測情境:永久 D 或 Z 狀態 堆疊簽章

永久 D 或 Z 狀態

如果執行緒處於 D (無法中斷的睡眠) 或 Z (殭屍) 狀態,但沒有快轉狀態 超過 ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms的進度時 llkd 會終止程序 (或父項程序)。如果後續掃描作業顯示 相同的程序會繼續存在,llkd 會確認即時鎖定條件,並 恐慌,為 值。

llkd 包含自拍狗狗,當 llkd 鎖定時發出鬧鐘提醒。監控計時器是 是每次執行主迴圈的預計時間會加倍 ro.llk_sample_ms

永久堆疊簽章

針對使用者偵錯版本,llkd 可以使用永久性偵測核心即時鎖定 進行堆疊簽章檢查如果處於 Z 以外任何狀態的執行緒 列出來的 ro.llk.stack 個核心符號超過 ro.llk.timeout_msro.llk.stack.timeout_msllkd 會終止程序 (即使有轉寄排程進度)。如果後續掃描作業顯示 相同的程序會繼續存在,llkd 會確認即時鎖定條件,並 恐慌,為 值。

如果有即時鎖定條件,lldk 檢查會持續存在,且 請尋找語句中由 symbol+0xsymbol.cfi+0x 組成的字串 /proc/pid/stack 檔案。符號清單位於 ro.llk.stack 和 預設值為以半形逗號分隔的清單 cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable

符號的使用應該很少,而且使用時間必須夠短,這樣才能在典型系統中 函式在逾時期間的樣本中只會出現一次 ro.llk.stack.timeout_ms (樣本數為每 ro.llk.check_ms)。由於缺少 ABA 保護措施的唯一方法,就是避免觸發錯誤觸發的唯一方法。符號 函式必須顯示在呼叫鎖的函式下方,可以形成連續的鎖定。如果 鎖頭位於下方或符號功能中,所有受影響的符號都會出現這個符號 不只是造成鎖定圖文標誌的程式

涵蓋範圍

llkd 的預設實作不會監控 init[kthreadd] 或 出現 [kthreadd] 次。針對 llkd 涵蓋 [kthreadd] 產生的執行緒:

  • 驅動程式不得處於永久的 D 狀態。

  • 驅動程式必須具有復原執行緒的機制,才能在執行緒終止時加以復原 外部。舉例來說,請使用 wait_event_interruptible() 而非 wait_event()

如果符合上述任一條件,llkd 拒絕清單即可調整為 涵蓋核心元件堆疊符號檢查作業涉及額外的程序 拒絕清單,以免封鎖 ptrace 的服務違反政策 作業。

Android 屬性

llkd 會回應多個 Android 屬性 (如下所列)。

  • 名為 prop_ms 的屬性以毫秒為單位。
  • 屬性如果使用半形逗號 (,) 分隔符,則在屬性前面加上分隔符, 保留預設值,然後視需要加上或減去項目,並可選擇是否加上加號 (+) 和減號 (-) 前置字元。在這些清單中,字串 false 與空白清單同義字,而空白或遺漏項目之餘則 指定的預設值

ro.config.low_ram

裝置設定的記憶體有限。

ro.debuggable

裝置已設定用於使用者偵錯或工程版本。

ro.llk.sysrq_t

如果屬性是 eng,則預設值為 ro.config.low_ramro.debuggable。 如為 true,請傾印所有執行緒 (sysrq t)。

ro.llk.enable

允許啟用即時鎖定 Daemon。預設值為 false

llk.enable

已針對工程版本評估。預設值為 ro.llk.enable

ro.khungtask.enable

允許啟用 [khungtask] Daemon。預設值為 false

khungtask.enable

已針對工程版本評估。預設值為 ro.khungtask.enable

ro.llk.mlockall

啟用對 mlockall() 的通話。預設值為 false

ro.khungtask.timeout

時間上限為 [khungtask]。預設值為 12 分鐘。

ro.llk.timeout_ms

時間上限為 D 或 Z。預設值為 10 分鐘。按兩下這個值即可設定 llkd的鬧鐘監控計時器。

ro.llk.D.timeout_ms

D 時間上限。預設值為 ro.llk.timeout_ms

ro.llk.Z.timeout_ms

Z 時間上限。預設值為 ro.llk.timeout_ms

ro.llk.stack.timeout_ms

檢查永久堆疊符號的時間上限。預設值為 ro.llk.timeout_ms僅在使用者偵錯或 eng 版本上啟用

ro.llk.check_ms

D 或 Z 的執行緒範例。預設值為兩分鐘。

ro.llk.stack

檢查核心堆疊符號,如果持續存在,可能表示 子系統處於鎖定狀態預設值為 cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable 以半形逗號分隔的核心符號清單。這項檢查無法提前安排 ABA (這段期間內每 ro.llk_check_ms輪詢一次) ro.llk.stack.timeout_ms,因此堆疊符號會特別罕見,且 短暫出現 (不太可能持續出現符號) )。檢查內容是否與「symbol+0x」相符,或 堆疊展開中的 symbol.cfi+0x僅適用於使用者偵錯或工程師 版本對使用者版本的安全性疑慮會導致有限的權限, 防止這項檢查

ro.llk.黑名單.process

llkd 不會監控指定的程序。預設值為 0,1,2 (kernelinit[kthreadd]) 以及程序名稱 init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]。 程序可以是 commcmdlinepid 參照。自動預設值 可能大於目前的屬性大小上限 92。

ro.llk.黑名單.parent

llkd 不會監控具有指定父項的程序。預設 是 0,2,adbd&[setsid] (kernel[kthreadd]adbd 僅適用於殭屍 setsid)。分隔符 (&) 分隔符表示只忽略父項 以及目標子項程序選擇 AND 符號,因為這個字詞 絕不屬於程序名稱的一部分;然而,殼層中的 setprop 需要 逸出或引用,但這個 init rc 檔案採用 不會發生這個問題父項或目標程序可以是 參照 commcmdlinepid

ro.llk.黑名單.uid

llkd 不會監控符合指定 UID 的程序。 以半形逗號分隔的 UIS 號碼或名稱清單。預設值為空白或 false

ro.llk.黑名單.process.stack

llkd 不會監控即時鎖定堆疊的指定部分程序 簽章。預設值為程序名稱 init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd。禁止這項政策 違反與封鎖 ptrace 的程序相關的違規事件 (因為 已勾選)。僅在使用者偵錯版本和 eng 版本上啟用。建構詳細資料 請參閱建構 Android

架構問題

  • 屬性長度上限為 92 個字元 (但預設值會忽略此屬性)。 來源的 include/llkd.h 檔案所定義)。
  • 內建的 [khungtask] Daemon 太過籠統,且會佔用驅動程式代碼, 坐在 D 狀態下太久改用 S 會導致工作終止 以及供駕駛人視需要確認。

程式庫介面 (選用)

您可以選擇使用以下項目,將 llkd 併入另一個特殊權限 Daemon 中 libllkd 元件中的下列 C 介面:

#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void)   /* ms to sleep for next check */

如果提供執行緒名稱,執行緒會自動產生執行緒,否則呼叫端 必須在主迴圈中呼叫 llkCheckMilliseconds。這個函式會傳回 時間。