يتضمّن نظام التشغيل Android 10 برنامج Android live-lock daemon
(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
، ويكون المراقب هو
ضعف الوقت المتوقّع للانتقال عبر الحلقة الرئيسية ويتم أخذ العيّنات كل
ro.llk_sample_ms
.
توقيع الحزمة الثابتة
في إصدارات userdebug، يمكن لـ llkd
رصد عمليات قفل kernel المباشرة باستخدام التحقُّق المستمر من توقيع تسلسل استدعاء الدوال البرمجية. إذا كان هناك سلسلة محادثات في أي حالة باستثناء 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
تم ضبط الجهاز على وضع userdebug أو وضع الإصدار الهندسي.
ro.llk.sysrq_t
إذا كانت السمة هي eng
، لا تكون القيمة التلقائية هي ro.config.low_ram
أو ro.debuggable
.
إذا كان true
، يمكنك تفريغ جميع سلاسل المحادثات (sysrq t
).
ro.llk.enable
السماح بتفعيل برنامج "الخادم الدائم لقفل الشاشة" القيمة التلقائية هي false
.
llk.enable
تم تقييمه لإصدارات المهندسين. القيمة التلقائية هي ro.llk.enable
.
ro.khungtask.enable
السماح بتفعيل برنامج [khungtask]
الخفي القيمة التلقائية هي false
.
khungtask.enable
تم تقييمه لإصدارات المهندسين. القيمة التلقائية هي ro.khungtask.enable
.
ro.llk.mlockall
فعِّل الاتصال بـ mlockall()
. القيمة التلقائية هي false
.
cannot translate
[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.
ro.llk.check_ms
عيّنات من الخيوط لـ D أو Z المدة التلقائية هي دقيقتان.
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
في توسيع الحزمة. لا يتوفّر هذا الإجراء إلا في عمليات التجميع من النوع userdebug أو eng، لأنّ المخاوف الأمنية في عمليات التجميع من النوع user تؤدي إلى منح امتيازات محدودة تمنع إجراء هذا التحقّق.
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
في واجهة المستخدم تشترط إلغاء علامة العطف أو الاقتباس منها، علمًا أنّ ملف init rc
الذي يتم تحديده عادةً لا يحتوي على هذه المشكلة. يمكن أن تكون العملية الرئيسية أو الهدف مرجعًا
comm
أو cmdline
أو pid
.
ro.llk.blacklist.uid
لا يراقب llkd
العمليات التي تتطابق مع المعرفات الفريدة المحددة.
قائمة مفصولة بفواصل بأرقام أو أسماء UIS الحقل التلقائي فارغ أو false
.
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
في الحلقة الرئيسية. تعرِض الدالة
المدة الزمنية قبل الطلب المتوقّع التالي لهذا المعالج.