Android Live-LocK Daemon (llkd)

يشتمل Android 10 على Android Live-LocK Daemon ( llkd ) ، والذي تم تصميمه لالتقاط وتخفيف الجمود kernel. يوفر المكون llkd افتراضيًا 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 النواة بطريقة توفر تقرير الأخطاء الأكثر تفصيلاً للحالة.

يشتمل llkd على هيئة رقابة ذاتية llkd إذا كان llkd ؛ المراقبة هي ضعف الوقت المتوقع للتدفق خلال الحلقة الرئيسية وأخذ العينات هو كل ro.llk_sample_ms .

توقيع المكدس المستمر

بالنسبة لإصدارات userdebug ، يمكن لـ llkd اكتشاف الأقفال الحية لـ kernel باستخدام التحقق المستمر من توقيع المكدس. إذا كان هناك مؤشر ترابط في أي حالة باستثناء Z يحتوي على رمز نواة ro.llk.stack مدرج بشكل ro.llk.stack يتم الإبلاغ عنه لمدة أطول من ro.llk.timeout_ms أو ro.llk.stack.timeout_ms ، فإن llkd يقتل العملية (حتى إذا كان هناك إعادة توجيه) جدولة التقدم). إذا llkd الفحص اللاحق استمرار وجود نفس العملية ، فإن llkd يؤكد حالة القفل المباشر llkd الذعر للنواة بطريقة توفر تقرير الأخطاء الأكثر تفصيلاً للحالة.

lldk فحص lldk باستمرار عند وجود شرط القفل المباشر ويبحث عن السلاسل المكونة " symbol+0x" " symbol.cfi+0x" أو " symbol.cfi+0x" في ملف /proc/pid/stack على Linux. قائمة الرموز موجودة في ro.llk.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] spawns. ل llkd إلى غطاء [kthreadd] المواضيع -spawned:

  • يجب ألا يظل السائقون في حالة D المستمرة ،

أو

  • يجب أن يكون لدى السائقين آليات لاستعادة الخيط في حالة تعرضه للقتل خارجيًا. على سبيل المثال ، استخدم wait_event_interruptible() بدلاً من wait_event() .

إذا تم استيفاء أحد الشروط المذكورة أعلاه ، فيمكن تعديل القائمة السوداء llkd لتغطية مكونات kernel. يشتمل فحص رمز المكدس على قائمة سوداء إضافية للعملية لمنع انتهاكات السياسات الانفصالية على الخدمات التي ptrace عمليات 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] . الافتراضي هو خطأ.

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" " symbol.cfi+0x" أو " 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] . يمكن أن تكون العملية cmdline comm أو cmdline أو pid . يمكن أن يكون التخلف التلقائي أكبر من الحد الأقصى الحالي لحجم الملكية وهو 92.

ro.llk.blacklist.parent

لا يراقب llkd العمليات التي لها الوالد (الوالدان) llkd . الافتراضي هو 0,2,adbd&[setsid] ( kernel ، [kthreadd] ، و adbd فقط لـ zombie setsid ). يحدد فاصل علامة العطف (&) أنه يتم تجاهل الأصل فقط بالاقتران مع العملية الفرعية الهدف. تم اختيار Ampersand لأنه لا يمثل أبدًا جزءًا من اسم العملية ؛ ومع ذلك ، setprop في الغلاف أن يتم تخطي علامة العطف أو اقتباسها ، على الرغم من أن ملف init rc الذي يتم تحديده عادةً لا يحتوي على هذه المشكلة. يمكن أن تكون العملية الأصل أو الهدف عبارة عن cmdline comm أو cmdline أو pid .

ro.llk.blacklist.uid

لا يراقب llkd العمليات التي تتطابق مع المعرف ( llkd المحدد. قائمة بأرقام التعريف أو الأسماء مفصولة بفواصل. الافتراضي فارغ أو خطأ.

ro.llk.blacklist.process.stack

لا يراقب llkd المجموعة الفرعية المحددة من العمليات لتوقيعات مكدس القفل المباشر. الافتراضي هو أسماء العمليات init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd . يمنع انتهاك الانقطاع المرتبط بالعمليات التي تمنع ptrace (حيث لا يمكن التحقق منها). نشط فقط على أبنية userdebug و eng . للحصول على تفاصيل حول أنواع الإنشاءات ، راجع إنشاء Android .

الاهتمامات المعمارية

  • تقتصر الخصائص على 92 حرفًا (ومع ذلك ، يتم تجاهل هذا بالنسبة إلى الإعدادات الافتراضية المحددة في ملف include/llkd.h في المصادر).
  • إن [khungtask] الخفي [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 في الحلقة الرئيسية الخاصة به. ترجع الدالة الفترة الزمنية قبل الاستدعاء التالي المتوقع لهذا المعالج.