एंड्रॉइड लाइव-लॉक डेमॉन (एलएलकेडी)

एंड्रॉइड 10 में एंड्रॉइड लाइव-लॉक डेमॉन ( llkd ) शामिल है, जिसे कर्नेल गतिरोध को पकड़ने और कम करने के लिए डिज़ाइन किया गया है। llkd घटक एक डिफ़ॉल्ट स्टैंडअलोन कार्यान्वयन प्रदान करता है, लेकिन आप वैकल्पिक रूप से llkd कोड को किसी अन्य सेवा में एकीकृत कर सकते हैं, या तो मुख्य लूप के भाग के रूप में या एक अलग थ्रेड के रूप में।

पता लगाने के परिदृश्य

llkd में दो डिटेक्शन परिदृश्य हैं: परसिस्टेंट D या Z स्टेट, और परसिस्टेंट स्टैक सिग्नेचर।

लगातार डी या जेड राज्य

यदि कोई थ्रेड D (अनइंटरप्टिबल स्लीप) या Z (ज़ोंबी) अवस्था में है, जिसमें ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms से अधिक समय तक कोई आगे की प्रगति नहीं है, तो llkd प्रक्रिया (या पैरेंट प्रक्रिया) को समाप्त कर देता है ) यदि बाद के स्कैन से पता चलता है कि वही प्रक्रिया मौजूद है, तो llkd लाइव-लॉक स्थिति की पुष्टि करता है और कर्नेल को इस तरह से आतंकित करता है जो स्थिति के लिए सबसे विस्तृत बग रिपोर्ट प्रदान करता है।

llkd में एक स्वयं प्रहरी शामिल है जो llkd के लॉक होने पर अलार्म करता है; वॉचडॉग मेनलूप के माध्यम से प्रवाहित होने में अपेक्षित समय से दोगुना है और नमूनाकरण प्रत्येक ro.llk_sample_ms है।

लगातार स्टैक हस्ताक्षर

यूजरडेबग रिलीज के लिए, llkd लगातार स्टैक सिग्नेचर चेकिंग का उपयोग करके कर्नेल लाइव-लॉक का पता लगा सकता है। यदि Z को छोड़कर किसी भी राज्य में एक थ्रेड में लगातार सूचीबद्ध ro.llk.stack कर्नेल प्रतीक है जो ro.llk.timeout_ms या ro.llk.stack.timeout_ms से अधिक समय तक रिपोर्ट किया जाता है, तो llkd प्रक्रिया को समाप्त कर देता है (भले ही आगे शेड्यूलिंग प्रगति)। यदि बाद के स्कैन से पता चलता है कि वही प्रक्रिया मौजूद है, तो llkd लाइव-लॉक स्थिति की पुष्टि करता है और कर्नेल को इस तरह से आतंकित करता है जो स्थिति के लिए सबसे विस्तृत बग रिपोर्ट प्रदान करता है।

lldk चेक लगातार तब भी जारी रहता है जब लाइव लॉक की स्थिति मौजूद होती है और लिनक्स पर /proc/pid/stack फ़ाइल में कंपोज़ किए गए स्ट्रिंग्स " symbol+0x" या " symbol.cfi+0x" की तलाश करता है। प्रतीकों की सूची 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 होते हैं)। एबीए सुरक्षा की कमी के कारण, झूठे ट्रिगर को रोकने का यही एकमात्र तरीका है। प्रतीक फ़ंक्शन उस लॉक को कॉल करने वाले फ़ंक्शन के नीचे दिखाई देना चाहिए जो विरोध कर सकता है। यदि लॉक नीचे है या प्रतीक फ़ंक्शन में है, तो प्रतीक सभी प्रभावित प्रक्रियाओं में प्रकट होता है, न कि केवल लॉकअप का कारण बनने वाली प्रक्रियाओं में।

कवरेज

llkd का डिफ़ॉल्ट कार्यान्वयन init , [kthreadd] , या [kthreadd] स्पॉन की निगरानी नहीं करता है। llkd के लिए [kthreadd] -स्पॉन्डेड थ्रेड्स को कवर करने के लिए:

  • ड्राइवरों को लगातार डी स्थिति में नहीं रहना चाहिए,

या

  • यदि बाहरी रूप से इसे मारा जाना चाहिए तो ड्राइवरों के पास थ्रेड को पुनर्प्राप्त करने के लिए तंत्र होना चाहिए। उदाहरण के लिए, wait_event_interruptible() wait_event() उपयोग करें।

यदि उपरोक्त में से कोई एक शर्त पूरी होती है, तो llkd ब्लैकलिस्ट को कर्नेल घटकों को कवर करने के लिए समायोजित किया जा सकता है। स्टैक सिंबल चेकिंग में ptrace ऑपरेशंस को ब्लॉक करने वाली सेवाओं पर सेपॉलिसी उल्लंघनों को रोकने के लिए एक अतिरिक्त प्रक्रिया ब्लैकलिस्ट शामिल है।

Android गुण

llkd कई Android गुणों (नीचे सूचीबद्ध) के प्रति प्रतिक्रिया करता है।

  • prop_ms नाम के गुण मिलीसेकंड में हैं।
  • गुण जो सूचियों के लिए अल्पविराम (,) विभाजक का उपयोग करते हैं, डिफ़ॉल्ट प्रविष्टि को संरक्षित करने के लिए एक अग्रणी विभाजक का उपयोग करते हैं, फिर क्रमशः वैकल्पिक प्लस (+) और माइनस (-) उपसर्गों के साथ प्रविष्टियां जोड़ते या घटाते हैं। इन सूचियों के लिए, स्ट्रिंग "गलत" एक खाली सूची का पर्याय है, और रिक्त या अनुपलब्ध प्रविष्टियाँ निर्दिष्ट डिफ़ॉल्ट मान का सहारा लेती हैं।

ro.config.low_ram

डिवाइस सीमित मेमोरी के साथ कॉन्फ़िगर किया गया है।

आरओ.डीबग करने योग्य

डिवाइस को userdebug या eng बिल्ड के लिए कॉन्फ़िगर किया गया है।

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] डेमॉन को सक्षम होने दें। डिफ़ॉल्ट गलत है।

खुंगटास्क.सक्षम

इंजी बिल्ड के लिए मूल्यांकन किया गया। डिफ़ॉल्ट ro.khungtask.enable है।

ro.llk.mlockall

कॉल को mlockall() पर सक्षम करें। डिफ़ॉल्ट गलत है।

ro.khungtask.timeout

[khungtask] अधिकतम समय सीमा। डिफ़ॉल्ट 12 मिनट है।

ro.llk.timeout_ms

डी या जेड अधिकतम समय सीमा। डिफ़ॉल्ट 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 के लिए थ्रेड्स के नमूने। डिफ़ॉल्ट दो मिनट है।

आरओ.एलएलके.स्टैक

कर्नेल स्टैक प्रतीकों के लिए जाँच करता है कि यदि लगातार मौजूद है तो यह संकेत कर सकता है कि एक सबसिस्टम लॉक हो गया है। डिफ़ॉल्ट cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable अल्पविराम से अलग कर्नेल प्रतीकों की सूची है। ro.llk.stack.timeout_ms अवधि के दौरान प्रत्येक ro.llk_check_ms को मतदान के अलावा चेक अग्रेषित शेड्यूलिंग ABA नहीं करता है, इसलिए स्टैक प्रतीक असाधारण रूप से दुर्लभ और क्षणभंगुर होने चाहिए (किसी प्रतीक के सभी में लगातार दिखाई देने की अत्यधिक संभावना नहीं है) ढेर के नमूने)। स्टैक विस्तार में " symbol+0x" +0x" या " symbol.cfi+0x" के लिए एक मैच के लिए जाँच करता है। केवल userdebug या eng बिल्ड पर उपलब्ध है ; उपयोगकर्ता बिल्ड पर सुरक्षा चिंताओं का परिणाम सीमित विशेषाधिकारों में होता है जो इस चेक को रोकते हैं।

ro.llk.ब्लैकलिस्ट.प्रोसेस

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.ब्लैकलिस्ट.पैरेंट

llkd प्रक्रियाओं को नहीं देखता है जिनमें निर्दिष्ट माता-पिता हैं। डिफ़ॉल्ट 0,2,adbd&[setsid] ( kernel , [kthreadd] और adbd केवल ज़ॉम्बी setsid के लिए है)। एक एम्परसेंड (&) विभाजक निर्दिष्ट करता है कि माता-पिता को केवल लक्ष्य चाइल्ड प्रक्रिया के संयोजन में अनदेखा किया जाता है। एम्परसेंड को इसलिए चुना गया क्योंकि यह कभी भी किसी प्रक्रिया के नाम का हिस्सा नहीं होता है; हालांकि, खोल में एक setprop को एम्परसेंड से बचने या उद्धृत करने की आवश्यकता होती है, हालांकि init rc आरसी फ़ाइल जहां इसे सामान्य रूप से निर्दिष्ट किया जाता है, में यह समस्या नहीं होती है। माता-पिता या लक्ष्य प्रक्रिया एक comm , cmdline , या pid ​​​​संदर्भ हो सकती है।

ro.llk.blacklist.uid

llkd निर्दिष्ट यूआईडी से मेल खाने वाली प्रक्रियाओं को नहीं देखता है। यूआईडी नंबरों या नामों की अल्पविराम से अलग की गई सूची। डिफ़ॉल्ट खाली या गलत है।

ro.llk.blacklist.process.stack

llkd लाइव लॉक स्टैक हस्ताक्षर के लिए प्रक्रियाओं के निर्दिष्ट सबसेट की निगरानी नहीं करता है। डिफ़ॉल्ट प्रक्रिया नाम है init,lmkd.llkd,llkd,keystore,ueventd,apexd,logdptrace को ब्लॉक करने वाली प्रक्रियाओं से जुड़े सेपॉलिसी उल्लंघन को रोकता है (क्योंकि इन्हें चेक नहीं किया जा सकता है)। केवल userdebug और eng बिल्ड पर सक्रिय है । बिल्ड प्रकारों के विवरण के लिए, बिल्डिंग एंड्रॉइड देखें।

वास्तु संबंधी चिंताएं

  • गुण 92 वर्णों तक सीमित हैं (हालांकि, स्रोतों में include/llkd.h फ़ाइल में परिभाषित डिफ़ॉल्ट के लिए इसे अनदेखा किया जाता है)।
  • बिल्ट-इन [khungtask] डेमॉन बहुत सामान्य है और ड्राइवर कोड पर यात्राएं करता है जो डी राज्य में बहुत अधिक बैठता है। S पर स्विच करने से कार्य (ओं) को मार डाला जा सकता है (और यदि आवश्यक हो तो ड्राइवरों द्वारा पुनरुत्थित)।

लाइब्रेरी इंटरफ़ेस (वैकल्पिक)

आप libllkd घटक से निम्नलिखित C इंटरफ़ेस का उपयोग करके वैकल्पिक रूप से llkd को किसी अन्य विशेषाधिकार प्राप्त डेमॉन में शामिल कर सकते हैं:

#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void)   /* ms to sleep for next check */

यदि एक थ्रेडनाम प्रदान किया जाता है, तो एक थ्रेड स्वचालित रूप से उत्पन्न होता है, अन्यथा कॉलर को अपने मुख्य लूप में llkCheckMilliseconds को कॉल करना होगा। फ़ंक्शन इस हैंडलर को अगली अपेक्षित कॉल से पहले की अवधि लौटाता है।