Android Live-LockK Daemon (llkd)

يتضمن Android 10 برنامج Android Live-LockK 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 .

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

بالنسبة لإصدارات userdebug، يمكن لـ llkd اكتشاف الأقفال المباشرة لـ kernel باستخدام التحقق المستمر من توقيع المكدس. إذا كان هناك مؤشر ترابط في أي حالة باستثناء Z يحتوي على رمز kernel 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 .

خصائص الروبوت

يستجيب llkd للعديد من خصائص Android (المدرجة أدناه).

  • الخصائص المسماة prop_ms موجودة بالمللي ثانية.
  • الخصائص التي تستخدم الفاصلة (،) للقوائم تستخدم فاصلًا بادئًا للحفاظ على الإدخال الافتراضي، ثم تضيف أو تطرح الإدخالات مع بادئات الجمع (+) والناقص (-) الاختيارية على التوالي. بالنسبة لهذه القوائم، تكون السلسلة "خطأ" مرادفة لقائمة فارغة، وتلجأ الإدخالات الفارغة أو المفقودة إلى القيمة الافتراضية المحددة.

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] . الافتراضي خطأ.

kungtask.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

د الحد الأقصى للوقت. الافتراضي هو 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" في توسيع المكدس. متاح فقط على 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 ). يحدد فاصل علامة العطف (&) أنه سيتم تجاهل الأصل فقط مع العملية الفرعية المستهدفة. تم تحديد علامة الضم لأنها لا تشكل أبدًا جزءًا من اسم العملية؛ ومع ذلك، فإن setprop في الصدفة يتطلب الهروب من علامة الضم أو الاقتباس، على الرغم من أن ملف init rc حيث يتم تحديد ذلك عادةً لا يحتوي على هذه المشكلة. يمكن أن تكون العملية الأصلية أو المستهدفة عبارة عن مرجع comm أو cmdline أو pid .

ro.llk.blacklist.uid

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

ro.llk.blacklist.process.stack

لا يراقب llkd المجموعة الفرعية المحددة من العمليات لتوقيعات مكدس القفل المباشر. الافتراضي هو أسماء العمليات init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd . يمنع انتهاك الخصوصية المرتبط بالعمليات التي تمنع ptrace (حيث لا يمكن التحقق منها). نشط فقط على userdebug وeng builds . للحصول على تفاصيل حول أنواع البناء، راجع إنشاء 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 في حلقته الرئيسية. تقوم الدالة بإرجاع الفترة الزمنية قبل الاستدعاء المتوقع التالي لهذا المعالج.