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() को कॉल करता है.

सत्यापन

फ़िलहाल, 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 के साइज़ वाले डिलीट ऑपरेटर का इस्तेमाल किया जाता है और वैकल्पिक जांच चालू होती है, तो चंक को डीऐलोकेट करते समय पास किए गए साइज़ और उसे ऐलोकेट करते समय अनुरोध किए गए साइज़ के बीच अंतर होता है. आम तौर पर, यह कंपाइलर की समस्या होती है या डी-एलॉकेट किए जा रहे ऑब्जेक्ट पर टाइप कन्फ़्यूज़न की समस्या होती है.
  • RSS limit exhausted: आरएसएस फ़ीड के लिए ज़्यादा से ज़्यादा विकल्प तय किए गए हैं.

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