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 इससे यह तय होता है कि प्रोसेस को बंद करने के बजाय, ठीक की जा सकने वाली गड़बड़ी होने पर ऐलोकेटर, शून्य वैल्यू दिखा सकता है.
hard_rss_limit_mb 0 0 जब प्रोसेस का आरएसएस इस सीमा तक पहुंच जाता है, तो प्रोसेस बंद हो जाती है.
soft_rss_limit_mb 0 0 जब प्रोसेस का आरएसएस इस सीमा तक पहुंच जाता है, तो आगे के असाइनमेंट पूरे नहीं होते या null दिखाता है. यह allocator_may_return_null की वैल्यू पर निर्भर करता है. ऐसा तब तक होता है, जब तक आरएसएस वापस कम नहीं हो जाता, ताकि नए असाइनमेंट किए जा सकें.
allocator_release_to_os_interval_ms 5000 लागू नहीं यह सिर्फ़ 64-बिट ऐलोकेटर पर असर डालता है. अगर यह विकल्प सेट किया जाता है, तो यह ओएस को इस्तेमाल न की गई मेमोरी को रिलीज़ करने की कोशिश करता है. हालांकि, यह इस इंटरवल (मिलीसेकंड में) से ज़्यादा बार नहीं होता है. अगर वैल्यू नेगेटिव है, तो ओएस को मेमोरी रिलीज़ नहीं की जाती.
abort_on_error true true अगर यह सेट है, तो गड़बड़ी का मैसेज प्रिंट करने के बाद टूल, _exit() के बजाय abort() को कॉल करता है.

Validation

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

समस्या का हल

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

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

  • corrupted chunk header: Chunk हेडर के चेकसम की पुष्टि नहीं हो सकी. ऐसा इन दो वजहों से हो सकता है: हेडर को पूरी तरह या कुछ हद तक बदल दिया गया हो या फ़ंक्शन को पास किया गया पॉइंटर, कोई हिस्सा न हो.
  • 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: आरएसएस फ़ीड के लिए ज़्यादा से ज़्यादा संख्या तय की गई है.

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