يشتمل Android 10 على Android Live-LocK Daemon ( llkd
) ، والذي تم تصميمه لالتقاط وتخفيف الجمود kernel. يوفر المكون 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
، يمكن لـ llkd اكتشاف الأقفال الحية لـ kernel باستخدام التحقق المستمر من توقيع المكدس. إذا كان هناك مؤشر ترابط في أي حالة باستثناء Z يحتوي على رمز نواة ro.llk.stack
مدرج بشكل دائم يتم الإبلاغ عنه لمدة أطول من ro.llk.timeout_ms
أو ro.llk.stack.timeout_ms
، فإن llkd
يقتل العملية (حتى إذا كان هناك إعادة توجيه) جدولة التقدم). إذا أظهر الفحص اللاحق استمرار وجود نفس العملية ، فإن llkd
يؤكد حالة القفل المباشر ويثير الذعر للنواة بطريقة توفر تقرير الأخطاء الأكثر تفصيلاً للحالة.
يستمر فحص lldk
بشكل مستمر عند وجود شرط القفل المباشر ويبحث عن السلاسل المكونة " symbol+0x"
0 ×" أو " 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]
spawns. لكي تغطي llkd
المواضيع التي تم [kthreadd]
:
- يجب ألا يظل السائقون في حالة D المستمرة ،
أو
- يجب أن يكون لدى السائقين آليات لاستعادة الخيط في حالة تعرضه للقتل خارجيًا. على سبيل المثال ، استخدم
wait_event_interruptible()
بدلاً منwait_event()
.
إذا تم استيفاء أحد الشروط المذكورة أعلاه ، فيمكن تعديل القائمة السوداء llkd
لتغطية مكونات kernel. يشتمل فحص رمز المكدس على قائمة سوداء إضافية للعملية لمنع انتهاكات السياسات الانفصالية على الخدمات التي ptrace
عمليات التتبع.
خصائص Android
يستجيب llkd
للعديد من خصائص Android (المدرجة أدناه).
- الخصائص المسماة
prop_ms
هي بالمللي ثانية. - تستخدم الخصائص التي تستخدم فاصلة (،) للقوائم فاصلًا بادئًا للحفاظ على الإدخال الافتراضي ، ثم قم بإضافة أو طرح الإدخالات باستخدام بادئات الجمع الاختيارية (+) والناقص (-) على التوالي. بالنسبة لهذه القوائم ، تكون السلسلة "false" مرادفة لقائمة فارغة ، وتلجأ الإدخالات الفارغة أو المفقودة إلى القيمة الافتراضية المحددة.
ro.config.low_ram
تم تكوين الجهاز بذاكرة محدودة.
ro.debuggable
تم تكوين الجهاز لـ userdebug أو eng build.
ro.llk.sysrq_t
إذا كانت الخاصية "eng" ، فإن القيمة الافتراضية ليست ro.config.low_ram
أو ro.debuggable
. إذا كان هذا صحيحًا ، فقم بتفريغ كافة مؤشرات الترابط ( sysrq t
).
ro.llk.enable
السماح بتمكين البرنامج الخفي للقفل المباشر. الافتراضي هو خطأ.
llk.enable
تم تقييمها للمباني الهندسية. الافتراضي هو ro.llk.enable
.
ro.khungtask.enable
السماح بتمكين البرنامج الخفي [khungtask]
. الافتراضي هو خطأ.
khungtask.enable
تم تقييمها للمباني الهندسية. الافتراضي هو ro.khungtask.enable
.
ro.llk.mlockall
تفعيل الاتصال بـ mlockall()
. الافتراضي هو خطأ.
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
. نشط فقط على userdebug أو eng builds .
ro.llk.check_ms
نماذج من سلاسل الرسائل لـ D أو Z. الافتراضي دقيقتان.
ro.llk.stack
عمليات التحقق من رموز مكدس kernel التي إذا كانت موجودة باستمرار يمكن أن تشير إلى أن النظام الفرعي مغلق. الافتراضي هو cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
قائمة رموز kernel مفصولة بفواصل. لا يقوم الاختيار بإجراء جدولة إعادة توجيه ABA إلا عن طريق الاستقصاء عن كل ro.llk_check_ms
خلال الفترة ro.llk.stack.timeout_ms
، لذلك يجب أن تكون رموز المكدس نادرة وعابرة بشكل استثنائي (من المستبعد جدًا أن يظهر الرمز باستمرار في الكل عينات من المكدس). التحقق من تطابق " symbol+0x"
0 ×" أو " symbol.cfi+0x"
في توسيع المكدس. متاح فقط على userdebug أو eng builds ؛ تؤدي المخاوف الأمنية المتعلقة ببنيات المستخدم إلى امتيازات محدودة تمنع هذا الفحص.
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
فقط لـ zombie setsid
). يحدد فاصل علامة العطف (&) أنه يتم تجاهل الأصل فقط بالاقتران مع العملية الفرعية الهدف. تم اختيار Ampersand لأنه لا يمثل أبدًا جزءًا من اسم العملية ؛ ومع ذلك ، setprop
في الغلاف أن يتم تجاوز علامة العطف أو اقتباسها ، على الرغم من أن ملف init rc
حيث يتم تحديد ذلك عادةً لا يحتوي على هذه المشكلة. يمكن أن تكون العملية الأصل أو الهدف عبارة عن مرجع comm
أو cmdline
أو pid
.
ro.llk.blacklist.uid
لا يراقب llkd
العمليات التي تتطابق مع المعرف (المعرفات) المحدد. قائمة بأرقام التعريف أو الأسماء مفصولة بفواصل. الافتراضي فارغ أو خطأ.
ro.llk.blacklist.process.stack
لا يقوم llkd
بمراقبة المجموعة الفرعية المحددة من العمليات لتوقيعات مكدس القفل المباشر. الافتراضي هو أسماء العمليات init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. يمنع انتهاك الانقطاع المرتبط بالعمليات التي تمنع ptrace
(حيث لا يمكن التحقق منها). نشط فقط على أبنية userdebug و eng . للحصول على تفاصيل حول أنواع الإنشاءات ، راجع إنشاء Android .
الاهتمامات المعمارية
- تقتصر الخصائص على 92 حرفًا (ومع ذلك ، يتم تجاهل هذا بالنسبة إلى الإعدادات الافتراضية المحددة في ملف
include/llkd.h
في المصادر). - إن البرنامج الخفي
[khungtask]
هو عام للغاية ويقوم برحلات على رمز السائق الموجود في الحالة D كثيرًا. التحول إلى S سيجعل المهمة (المهام) قابلة للقتل (ويمكن للسائقين إحيائها إذا لزم الأمر).
واجهة المكتبة (اختياري)
يمكنك دمج llkd
اختياريًا في برنامج خفي ذي امتياز آخر باستخدام واجهة C التالية من مكون libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
إذا تم توفير اسم مؤشر ترابط ، يتم إنشاء سلسلة رسائل تلقائيًا ، وإلا يجب على المتصل استدعاء llkCheckMilliseconds
في الحلقة الرئيسية الخاصة به. ترجع الدالة الفترة الزمنية قبل الاستدعاء التالي المتوقع لهذا المعالج.