Scudo

Scudo, डाइनैमिक यूज़र-मोड मेमोरी ऐलोकेटर या हीप ऐलोकेटर है. इसे परफ़ॉर्मेंस को बनाए रखते हुए, हीप से जुड़ी कमजोरियों (जैसे कि हीप पर आधारित बफ़र का ओवरफ़्लो, खाली करने के बाद इस्तेमाल करना, और दो बार खाली करना) के लिए डिज़ाइन किया गया है. यह स्टैंडर्ड C एलोकेशन और डिएलोकेशन प्राइमिटिव (जैसे, malloc और free) के साथ-साथ C++ प्राइमिटिव (जैसे, new और delete) भी उपलब्ध कराता है.

Scudo, AddressSanitizer (ASan) जैसे मेमोरी की गड़बड़ी का पता लगाने वाले टूल की तुलना में, गड़बड़ी को कम करने वाला टूल है.

Android 11 रिलीज़ होने के बाद से, सभी नेटिव कोड के लिए scudo का इस्तेमाल किया जाता है. हालांकि, कम मेमोरी वाले डिवाइसों पर अब भी jemalloc का इस्तेमाल किया जाता है. रनटाइम के दौरान, सभी नेटिव हेप के ऐलोकेशन और डिऐलोकेशन की सेवा, Scudo सभी एक्सीक्यूटेबल और उनकी लाइब्रेरी डिपेंडेंसी के लिए करता है. अगर हेप में कोई गड़बड़ी या संदिग्ध व्यवहार का पता चलता है, तो प्रोसेस को रोक दिया जाता है.

Scudo ओपन सोर्स है और यह LLVM के compiler-rt प्रोजेक्ट का हिस्सा है. दस्तावेज़ https://llvm.org/docs/ScudoHardenedAllocator.html पर उपलब्ध है. Scudo रनटाइम, Android टूलचैन का हिस्सा है. साथ ही, Soong और Make में भी इसे जोड़ा गया है, ताकि बाइनरी में एलोकेटर को आसानी से चालू किया जा सके.

नीचे दिए गए विकल्पों का इस्तेमाल करके, ऐलोकेटर में अतिरिक्त मटिगेशन को चालू या बंद किया जा सकता है.

पसंद के मुताबिक बनाएं

एलोकेटर के कुछ पैरामीटर को हर प्रोसेस के हिसाब से कई तरीकों से तय किया जा सकता है:

  • स्टैटिक तौर पर: प्रोग्राम में __scudo_default_options फ़ंक्शन तय करें, जो पार्स की जाने वाली विकल्प स्ट्रिंग दिखाता है. इस फ़ंक्शन के पास यह प्रोटोटाइप होना चाहिए: extern "C" const char *__scudo_default_options().
  • डाइनैमिक तौर पर: एनवायरमेंट वैरिएबल SCUDO_OPTIONS का इस्तेमाल करें. इसमें, पार्स की जाने वाली विकल्प स्ट्रिंग शामिल होती है. इस तरह से तय किए गए विकल्प, __scudo_default_options के ज़रिए तय की गई किसी भी परिभाषा को बदल देते हैं.

ये विकल्प उपलब्ध हैं.

विकल्प 64-बिट डिफ़ॉल्ट डिफ़ॉल्ट रूप से 32-बिट ब्यौरा
QuarantineSizeKb 256 64 क्वॉरंटीन का साइज़ (केबी में), जिसका इस्तेमाल चंक को डिअललोकेट करने में देरी करने के लिए किया जाता है. कम वैल्यू से मेमोरी का इस्तेमाल कम हो सकता है, लेकिन समस्या को कम करने की सुविधा की परफ़ॉर्मेंस पर असर पड़ सकता है. नेगेटिव वैल्यू से डिफ़ॉल्ट वैल्यू लागू हो जाती है. इसे और ThreadLocalQuarantineSizeKb, दोनों को शून्य पर सेट करने से, क्वॉरंटीन की सुविधा पूरी तरह से बंद हो जाती है.
QuarantineChunksUpToSize 2048 512 बाइट में वह साइज़ जिस तक चंक को क्वॉरंटीन किया जा सकता है.
ThreadLocalQuarantineSizeKb 64 16 ग्लोबल क्वॉरंटीन को ऑफ़लोड करने के लिए, हर थ्रेड के कैश मेमोरी का साइज़ (केबी में). कम वैल्यू से मेमोरी का इस्तेमाल कम हो सकता है, लेकिन ग्लोबल क्वॉरंटीन पर कॉन्टेंट को इकट्ठा करने में ज़्यादा समय लग सकता है. इस और QuarantineSizeKb, दोनों को शून्य पर सेट करने पर, क्वॉरंटीन की सुविधा पूरी तरह से बंद हो जाती है.
DeallocationTypeMismatch false false malloc/delete, new/free, new/delete[] पर गड़बड़ी की रिपोर्टिंग की सुविधा चालू करता है
DeleteSizeMismatch true true नए और मिटाए गए डेटा के साइज़ के मेल न खाने पर, गड़बड़ी की रिपोर्टिंग की सुविधा चालू करता है.
ZeroContents false false यह एट्रिब्यूट, एलोकेशन और डिएलोकेशन के दौरान, शून्य चंक वाले कॉन्टेंट को चालू करता है.
allocator_may_return_null false false इससे पता चलता है कि प्रोसेस को खत्म करने के बजाय, ठीक की जा सकने वाली गड़बड़ी होने पर, एलोकेटर null दिखा सकता है.
hard_rss_limit_mb 0 0 जब प्रोसेस का आरएसएस इस सीमा तक पहुंच जाता है, तो प्रोसेस खत्म हो जाती है.
soft_rss_limit_mb 0 0 जब प्रोसेस का आरएसएस इस सीमा तक पहुंच जाता है, तो नए ऐलोकेशन तब तक नहीं किए जा सकते, जब तक आरएसएस फिर से कम नहीं हो जाता. इसके बाद, नए ऐलोकेशन किए जा सकते हैं. हालांकि, यह allocator_may_return_null की वैल्यू पर निर्भर करता है कि आरएसएस की वैल्यू कब कम होगी.null
allocator_release_to_os_interval_ms लागू नहीं 5000 सिर्फ़ 64-बिट एलोकेटर पर असर पड़ता है. अगर यह सेट है, तो ओएस को इस्तेमाल न की गई मेमोरी रिलीज़ करने की कोशिश की जाती है. हालांकि, यह इंटरवल (मिलीसेकंड में) से ज़्यादा बार नहीं की जाती. अगर वैल्यू नेगेटिव है, तो ओएस को मेमोरी रिलीज़ नहीं की जाती.
abort_on_error true true अगर यह सेट है, तो गड़बड़ी का मैसेज प्रिंट करने के बाद, टूल _exit() के बजाय abort() को कॉल करता है.

पुष्टि करें

फ़िलहाल, Scudo के लिए खास तौर पर कोई सीटीएस टेस्ट नहीं है. इसके बजाय, पक्का करें कि किसी बाइनरी के लिए, Scudo की सुविधा चालू होने या न होने पर, सीटीएस टेस्ट पास हो जाएं. इससे यह पुष्टि की जा सकेगी कि बाइनरी का डिवाइस पर कोई असर नहीं पड़ेगा.

समस्या का हल

अगर कोई ऐसी समस्या का पता चलती है जिसे ठीक नहीं किया जा सकता, तो एलोकेटर, स्टैंडर्ड गड़बड़ी के ब्यौरे में गड़बड़ी का मैसेज दिखाता है. इसके बाद, वह प्रोसेस को बंद कर देता है. सिस्टम लॉग में, स्टैक ट्रेस जोड़े जाते हैं. आम तौर पर, आउटपुट Scudo ERROR: से शुरू होता है. इसके बाद, समस्या के बारे में कम शब्दों में जानकारी दी जाती है. साथ ही, उससे जुड़े पॉइंटर भी दिए जाते हैं.

गड़बड़ी के मौजूदा मैसेज और उनकी संभावित वजहों की सूची यहां दी गई है:

  • corrupted chunk header: चंक हेडर के चेकसम की पुष्टि नहीं हो सकी. ऐसा दो वजहों से हो सकता है: हेडर को कुछ हद तक या पूरी तरह से बदल दिया गया हो या फ़ंक्शन में पास किया गया पॉइंटर कोई चंक न हो.
  • race on chunk header: दो अलग-अलग थ्रेड, एक ही समय पर एक ही हेडर में बदलाव करने की कोशिश कर रही हैं. आम तौर पर, यह रेस-कंडीशन या उस चंक पर कार्रवाइयां करते समय लॉकिंग की सामान्य कमी का लक्षण होता है.
  • invalid chunk state: चंक किसी खास कार्रवाई के लिए, उम्मीद के मुताबिक स्थिति में नहीं है. उदाहरण के लिए, उसे खाली करने की कोशिश करते समय उसे ऐलोकेट नहीं किया गया है या उसे फिर से इस्तेमाल करने की कोशिश करते समय उसे क्वॉरंटीन नहीं किया गया है. आम तौर पर, डबल फ़्री होने की वजह से यह गड़बड़ी होती है.
  • misaligned pointer: अलाइनमेंट की बुनियादी ज़रूरी शर्तों को सख्ती से लागू किया जाता है: 32-बिट प्लैटफ़ॉर्म पर 8 बाइट और 64-बिट प्लैटफ़ॉर्म पर 16 बाइट. अगर हमारे फ़ंक्शन में पास किया गया पॉइंटर उनमें फ़िट नहीं होता है, तो इसका मतलब है कि किसी फ़ंक्शन में पास किया गया पॉइंटर अलाइन नहीं है.
  • allocation type mismatch: यह विकल्प चालू होने पर, किसी चंक पर कॉल किए गए डिएलोकेशन फ़ंक्शन का टाइप, उस फ़ंक्शन से मैच करना चाहिए जिसे चंक को ऐलोकेट करने के लिए कॉल किया गया था. इस तरह के मैच न होने की वजह से, सुरक्षा से जुड़ी समस्याएं आ सकती हैं.
  • invalid sized delete: C++14 के साइज़ वाले delete ऑपरेटर का इस्तेमाल करने और ज़रूरी नहीं की जाने वाली जांच चालू होने पर, किसी चंक को डिअललोकेट करते समय दिए गए साइज़ और उसे ऐलोकेट करते समय दिए गए साइज़ में अंतर होता है. आम तौर पर, यह कंपाइलर की समस्या होती है या डिसकाइओकेट किए जा रहे ऑब्जेक्ट के लिए टाइप का भ्रम होता है.
  • RSS limit exhausted: आरएसएस फ़ीड की तय सीमा से ज़्यादा एपिसोड जोड़े गए हैं.

अगर आपको OS में क्रैश की समस्या को डीबग करना है, तो HWASan OS बिल्ड का इस्तेमाल किया जा सकता है. अगर किसी ऐप्लिकेशन में क्रैश की समस्या को डीबग किया जा रहा है, तो HWASan ऐप्लिकेशन बिल्ड का इस्तेमाल भी किया जा सकता है.