يتضمّن نظام التشغيل 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، تكون هذه الطريقة الوحيدة لمنع حدوث مشغّل خطأ. يجب أن يظهر الرمز
function أسفل الدالة التي تستدعي القفل الذي يمكن أن يتعارض مع الرمز. إذا كان
القفل أسفل دالة الرمز أو في دالة الرمز، يظهر الرمز في جميع العمليات
المتأثّرة، وليس فقط العملية التي أدّت إلى حدوث القفل.
التغطية
لا تتتبّع عملية التنفيذ التلقائية لـ 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
.
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.
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 أو
الهندسة. تؤدي المخاوف الأمنية المتعلّقة بعمليات إنشاء المستخدمين إلى الحصول على امتيازات محدودة
تمنع هذا الفحص.
ro.llk.block.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
في القشرة استخدام علامة ESCAPE أو اقتباسات مع علامة العطف، على الرغم من أنّ ملف 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
في حلقة التنفيذ الرئيسية. تعرِض الدالة
المدة الزمنية قبل الطلب المتوقّع التالي لهذا المعالج.