Android Live-LocK Daemon (llkd)

يشتمل 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 في الحلقة الرئيسية الخاصة به. ترجع الدالة الفترة الزمنية قبل الاستدعاء التالي المتوقع لهذا المعالج.