Android 10 มี Daemon ล็อกแบบสดของ Android
(llkd
) ซึ่งออกแบบมาเพื่อตรวจจับและลดการหยุดทำงานของเคอร์เนล llkd
จะมีการติดตั้งใช้งานสแตนด์อโลนที่เป็นค่าเริ่มต้น แต่คุณสามารถ
ผสานรวมโค้ด llkd
เข้ากับบริการอื่น โดยอาจเป็นส่วนหนึ่งของ
ลูปหลักหรือเป็นเทรดแยกต่างหาก
สถานการณ์ในการตรวจจับ
llkd
มีสถานการณ์การตรวจจับ 2 แบบ ได้แก่ สถานะ D หรือ Z คงที่และคงที่
สแต็กลายเซ็น
สถานะ D หรือ Z คงที่
หากชุดข้อความอยู่ในสถานะ D (หลับต่อเนื่อง) หรือ Z (ซอมบี้) โดยไม่มีการส่งต่อ
ความคืบหน้านานกว่า ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
llkd
จะหยุดกระบวนการนี้ (หรือกระบวนการระดับบนสุด) หากการสแกนครั้งต่อๆ ไปแสดง
กระบวนการเดิมจะยังคงอยู่ โดย llkd
จะยืนยันเงื่อนไขการล็อกสดและ
ทำให้เคอร์เนลตื่นตระหนกในลักษณะที่จัดทำรายงานข้อบกพร่องโดยละเอียดสำหรับ
llkd
มี Watchdog ที่ส่งเสียงเตือนหาก llkd
ล็อกไว้ Watchdog คือ
2 เท่าของเวลาที่คาดว่าจะไหลผ่านเมนลูปหลักและการสุ่มตัวอย่างคือ
ro.llk_sample_ms
ลายเซ็นสแต็กแบบถาวร
สำหรับรุ่นการแก้ไขข้อบกพร่อง llkd
จะตรวจจับการล็อกสดของเคอร์เนลโดยใช้แบบถาวร
การตรวจสอบลายเซ็นในสแต็ก หากเธรดในสถานะใดๆ ยกเว้น Z มีค่าคงที่
สัญลักษณ์เคอร์เนล ro.llk.stack
ที่แสดงในรายการซึ่งมีการรายงานเป็นระยะเวลานานกว่า
ro.llk.timeout_ms
หรือ ro.llk.stack.timeout_ms
llkd
จะหยุดขั้นตอนนี้
(แม้ว่าจะมีความคืบหน้าในการกำหนดเวลาในอนาคตก็ตาม) หากการสแกนครั้งต่อๆ ไปแสดง
กระบวนการเดิมจะยังคงอยู่ โดย llkd
จะยืนยันเงื่อนไขการล็อกสดและ
ทำให้เคอร์เนลตื่นตระหนกในลักษณะที่จัดทำรายงานข้อบกพร่องโดยละเอียดสำหรับ
การตรวจสอบ lldk
จะยังคงอยู่อย่างต่อเนื่องเมื่อมีเงื่อนไขการล็อกแบบเรียลไทม์อยู่และ
จะค้นหาสตริงที่เขียนแล้ว symbol+0x
หรือ symbol.cfi+0x
ในองค์ประกอบ
/proc/pid/stack
ใน Linux รายการสัญลักษณ์แสดงเป็นภาษา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_ram
หรือ ro.debuggable
หากเป็น true
ให้ดัมพ์ชุดข้อความทั้งหมด (sysrq t
)
ro.llk.enable
อนุญาตให้เปิดใช้ Daemon ล็อกแบบสด ค่าเริ่มต้นคือ false
llk.enable
ประเมินสำหรับบิลด์ทางวิศวกรรม ค่าเริ่มต้นคือ ro.llk.enable
ro.khungtask.enable
อนุญาตให้เปิดใช้ Daemon [khungtask]
รายการ ค่าเริ่มต้นคือ false
khungtask.enable
ประเมินสำหรับบิลด์ทางวิศวกรรม ค่าเริ่มต้นคือ ro.khungtask.enable
ro.llk.mlockall
เปิดใช้การโทรหา mlockall()
ค่าเริ่มต้นคือ false
ro.khungtask.timeout
ขีดจำกัดเวลาสูงสุด [khungtask]
ค่าเริ่มต้นคือ 12 นาที
ro.llk.timeout_ms
จำกัดเวลาสูงสุด D หรือ Z ค่าเริ่มต้นคือ 10 นาที ขยายค่านี้เป็น 2 เท่าเพื่อตั้งค่า
นาฬิกาปลุก Watchdog สำหรับ 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
ใช้งานได้เฉพาะในเวอร์ชัน userdebug หรือ Enging เท่านั้น
ro.llk.check_ms
ตัวอย่างชุดข้อความสําหรับ D หรือ Z ค่าเริ่มต้นคือ 2 นาที
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.blacklist.process
llkd
ไม่ได้ตรวจสอบกระบวนการที่ระบุ ค่าเริ่มต้นคือ 0,1,2
(kernel
,
init
และ [kthreadd]
) บวกชื่อกระบวนการ
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
กระบวนการอาจเป็นข้อมูลอ้างอิง comm
, cmdline
หรือ pid
ค่าเริ่มต้นแบบอัตโนมัติ
ต้องมีขนาดใหญ่กว่าขนาดพร็อพเพอร์ตี้สูงสุดในปัจจุบันที่ 92
ro.llk.blacklist.parent
llkd
จะไม่ตรวจสอบกระบวนการที่มีรายการหลักที่ระบุ ค่าเริ่มต้น
คือ 0,2,adbd&[setsid]
(kernel
, [kthreadd]
และ adbd
สำหรับซอมบี้เท่านั้น
setsid
) ตัวคั่นเครื่องหมายและ (&) ระบุว่าระบบจะไม่สนใจตัวคั่นหลักเท่านั้น
ร่วมกับกระบวนการย่อยเป้าหมาย มีการเลือกเครื่องหมาย "และ" เนื่องจาก
ไม่เป็นส่วนหนึ่งของชื่อกระบวนการ แต่ setprop
ใน Shell จำเป็นต้องมีเมธอด
เครื่องหมาย & เป็นอักขระหลีกหรือยกมา แม้ว่าไฟล์ init rc
ที่
ที่ระบุตามปกติไม่มีปัญหานี้ กระบวนการระดับบนสุดหรือเป้าหมายอาจเป็น
ข้อมูลอ้างอิง comm
, cmdline
หรือ pid
ro.llk.blacklist.uid
llkd
ไม่ตรวจสอบกระบวนการที่ตรงกับ UID ที่ระบุ
รายการหมายเลขหรือชื่อ UIS ที่คั่นด้วยคอมมา ค่าเริ่มต้นเว้นว่างไว้หรือfalse
ro.llk.blacklist.process.stack
llkd
ไม่ได้ตรวจสอบเซ็ตย่อยของกระบวนการที่ระบุไว้สำหรับสแต็กล็อกแบบสด
ลายเซ็น ค่าเริ่มต้นเป็นชื่อกระบวนการ
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
ป้องกัน Sepolicy
การละเมิดที่เกี่ยวข้องกับกระบวนการที่บล็อก ptrace
(เนื่องจากการดำเนินการนี้ไม่
(เลือกไว้) ใช้งานได้เฉพาะในเวอร์ชัน userdebug และ eng สำหรับรายละเอียดเกี่ยวกับบิลด์
ประเภทต่างๆ โปรดดูการสร้าง Android
ข้อกังวลด้านสถาปัตยกรรม
- พร็อพเพอร์ตี้มีอักขระได้ไม่เกิน 92 ตัว (แต่ระบบจะไม่นำส่วนนี้ไปใช้เป็นค่าเริ่มต้น
ที่กำหนดไว้ในไฟล์
include/llkd.h
ในแหล่งที่มา) - Daemon ในตัวของ
[khungtask]
มีความเฉพาะเจาะจงน้อยเกินไปและการเดินทางตามรหัสไดรเวอร์ที่ อยู่ในสถานะ D มากเกินไป การเปลี่ยนไปใช้ S จะทำให้งานปิดลงได้ (และให้คนขับกลับมาใช้ได้ หากจำเป็น)
อินเทอร์เฟซของคลัง (ไม่บังคับ)
คุณสามารถเลือกรวม llkd
เข้ากับ Daemon ที่มีสิทธิ์อีกตัวหนึ่งได้โดยใช้
อินเทอร์เฟซ C ต่อไปนี้จากคอมโพเนนต์ libllkd
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
หากมีการระบุ Threadname แล้ว เทรดจะสร้างขึ้นโดยอัตโนมัติ มิฉะนั้นผู้โทร
ต้องเรียก llkCheckMilliseconds
ในลูปหลัก ฟังก์ชันจะแสดงผลค่า
ระยะเวลาก่อนการเรียกครั้งต่อไปที่คาดไว้ไปยังเครื่องจัดการนี้