Daemon ล็อกแบบสดของ Android (llkd)

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 ในลูปหลัก ฟังก์ชันจะแสดงผลค่า ระยะเวลาก่อนการเรียกครั้งต่อไปที่คาดไว้ไปยังเครื่องจัดการนี้