हार्डवेयर की मदद से काम करने वाला AddressSanitizer

HWASan क्रैश की जानकारी पढ़ने के तरीके के बारे में जानने के लिए, HWASan रिपोर्ट को समझना लेख पढ़ें!

हार्डवेयर की मदद से काम करने वाला AddressSanitizer (HWASan), मेमोरी में होने वाली गड़बड़ियों का पता लगाने वाला टूल है. यह AddressSanitizer की तरह ही काम करता है. HWASan, ASan की तुलना में बहुत कम रैम का इस्तेमाल करता है. इसलिए, यह पूरे सिस्टम को सैनिटाइज़ करने के लिए सही है. HWASan सिर्फ़ Android 10 और इसके बाद के वर्शन पर उपलब्ध है. साथ ही, यह सिर्फ़ AArch64 हार्डवेयर पर काम करता है.

HWASan मुख्य रूप से C/C++ कोड के लिए फ़ायदेमंद है. हालांकि, यह Java कोड को डीबग करने में भी मदद कर सकता है. इस कोड की वजह से, Java इंटरफ़ेस लागू करने के लिए इस्तेमाल किए गए C/C++ में क्रैश होते हैं. यह इसलिए मददगार है, क्योंकि इससे मेमोरी से जुड़ी गड़बड़ियों का पता चलता है. साथ ही, आपको सीधे तौर पर उस कोड के बारे में जानकारी मिलती है जिसकी वजह से गड़बड़ी हुई है.

क्लासिक ASan की तुलना में, HWASan में ये सुविधाएं हैं:

  • सीपीयू का ओवरहेड, दोनों में एक जैसा है (~2x)
  • कोड के साइज़ में मिलता-जुलता ओवरहेड (40 से 50%)
  • RAM का इस्तेमाल बहुत कम (10% से 35%) होता है

HWASan, ASan की तरह ही बग का पता लगाता है:

  • स्टैक और हीप बफ़र ओवरफ़्लो/अंडरफ़्लो
  • फ़्री किए गए हीप का इस्तेमाल
  • स्कोप से बाहर स्टैक का इस्तेमाल किया गया
  • डबल फ़्री/वाइल्ड फ़्री

इसके अलावा, HWASan, फ़ंक्शन से वापस आने के बाद स्टैक के इस्तेमाल का पता लगाता है.

HWASan (ASan की तरह) UBSan के साथ काम करता है. दोनों को एक ही समय में किसी टारगेट पर चालू किया जा सकता है.

लागू करने से जुड़ी जानकारी और सीमाएं

HWASan, मेमोरी टैगिंग के सिद्धांत पर काम करता है. इसमें, एक छोटी सी रैंडम टैग वैल्यू को पॉइंटर और मेमोरी पतों की रेंज, दोनों के साथ जोड़ा जाता है. मेमोरी ऐक्सेस के मान्य होने के लिए, पॉइंटर और मेमोरी टैग का मेल खाना ज़रूरी है. HWASan, ARMv8 की टॉप बाइट इग्नोर (टीबीआई) सुविधा का इस्तेमाल करता है. इसे वर्चुअल अड्रेस टैगिंग भी कहा जाता है. इसका इस्तेमाल, अड्रेस के सबसे ज़्यादा बिट में पॉइंटर टैग को सेव करने के लिए किया जाता है.

Clang के दस्तावेज़ वाली साइट पर जाकर, HWASan के डिज़ाइन के बारे में ज़्यादा जानें.

HWASan में, ASan की तरह ओवरफ़्लो का पता लगाने के लिए, सीमित साइज़ वाले रेडज़ोन नहीं होते. साथ ही, इसमें ASan की तरह फ़्री होने के बाद इस्तेमाल का पता लगाने के लिए, सीमित क्षमता वाला क्वारंटीन नहीं होता. इस वजह से, HWASan किसी बग का पता लगा सकता है. भले ही, ओवरफ़्लो कितना भी बड़ा हो या मेमोरी को डीऐलोकेट किए हुए कितना भी समय हो गया हो. इससे HWASan को ASan की तुलना में ज़्यादा फ़ायदा मिलता है.

हालांकि, HWASan में टैग की वैल्यू की संख्या सीमित (256) होती है. इसका मतलब है कि प्रोग्राम के एक बार चलने के दौरान, किसी भी बग के छूट जाने की संभावना 0.4% होती है.

ज़रूरी शर्तें

Android के सामान्य कर्नल के नए वर्शन (4.14+) में, HWASan की सुविधा पहले से मौजूद होती है. Android 10 की कुछ खास ब्रांच में, HWASan काम नहीं करता.

HWASan के लिए, यूज़रस्पेस की सुविधा Android 11 से उपलब्ध है.

अगर किसी दूसरे कर्नल का इस्तेमाल किया जा रहा है, तो HWASan के लिए यह ज़रूरी है कि Linux कर्नल, सिस्टम कॉल के आर्ग्युमेंट में टैग किए गए पॉइंटर स्वीकार करे. इस सुविधा को अपस्ट्रीम पैचसेट में लागू किया गया था:

अगर कस्टम टूलचेन का इस्तेमाल करके बनाया जा रहा है, तो पक्का करें कि इसमें LLVM कमिट c336557f तक की सभी चीज़ें शामिल हों.

HWASan का इस्तेमाल करना

HWASan का इस्तेमाल करके पूरे प्लैटफ़ॉर्म को बनाने के लिए, इन कमांड का इस्तेमाल करें:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

आसानी के लिए, प्रॉडक्ट की परिभाषा में SANITIZE_TARGET सेटिंग जोड़ी जा सकती है. यह सेटिंग, aosp_coral_hwasan की तरह होती है.

AddressSanitizer के बारे में जानने वाले उपयोगकर्ताओं के लिए, बिल्ड की जटिलता कम हो गई है:

  • make को दो बार चलाने की ज़रूरत नहीं है.
  • इंक्रीमेंटल बिल्ड की सुविधा पहले से मौजूद होती है.
  • उपयोगकर्ता के डेटा को फ़्लैश करने की ज़रूरत नहीं है.

AddressSanitizer से जुड़ी कुछ पाबंदियां भी हटा दी गई हैं:

  • स्टैटिक एक्ज़ीक्यूटेबल काम करते हैं.
  • libc के अलावा, किसी अन्य टारगेट को सैनिटाइज़ करने की प्रोसेस को छोड़ा जा सकता है. ASan के उलट, इसमें यह ज़रूरी नहीं है कि अगर किसी लाइब्रेरी को सैनिटाइज़ किया गया है, तो उसे लिंक करने वाले किसी भी एक्ज़ीक्यूटेबल को भी सैनिटाइज़ किया जाना चाहिए.

एक ही (या इससे ज़्यादा) बिल्ड नंबर पर, HWASan और सामान्य इमेज के बीच स्विच किया जा सकता है. डिवाइस को वाइप करने की ज़रूरत नहीं है.

किसी मॉड्यूल को सैनिटाइज़ करने की प्रोसेस को स्किप करने के लिए, LOCAL_NOSANITIZE := hwaddress (Android.mk) या sanitize: { hwaddress: false } (Android.bp) का इस्तेमाल करें.

अलग-अलग टारगेट को सैनिटाइज़ करना

HWASan को हर टारगेट के लिए चालू किया जा सकता है. इसके लिए, सामान्य (अनसैनिटाइज़्ड) बिल्ड का इस्तेमाल किया जा सकता है. हालांकि, इसके लिए यह ज़रूरी है कि libc.so को भी सैनिटाइज़ किया गया हो. bionic/libc/Android.bp में मौजूद "libc_defaults" में, सैनिटाइज़ ब्लॉक में hwaddress: true जोड़ें. इसके बाद, जिस टारगेट पर काम किया जा रहा है उसमें भी ऐसा ही करें.

ध्यान दें कि libc को सैनिटाइज़ करने से, सिस्टम-वाइड हीप मेमोरी के सभी हिस्सों को टैग किया जा सकता है. साथ ही, libc.so में मेमोरी ऑपरेशन के लिए टैग की जांच की जा सकती है. इससे बाइनरी में भी गड़बड़ियां पकड़ी जा सकती हैं. भले ही, HWASan को चालू न किया गया हो. ऐसा तब होता है, जब मेमोरी का गलत ऐक्सेस libc.so में हो (उदाहरण के लिए, delete() किए गए म्यूटेक्स पर pthread_mutex_unlock().

अगर पूरे प्लैटफ़ॉर्म को HWASan का इस्तेमाल करके बनाया गया है, तो किसी भी बिल्ड फ़ाइल को बदलने की ज़रूरत नहीं है.

बेहतर स्टैक ट्रेस

HWASan, फ़्रेम-पॉइंटर पर आधारित फ़ास्ट अनवाइंडर का इस्तेमाल करता है. इससे प्रोग्राम में मेमोरी के हर ऐलोकेशन और डीऐलोकेशन इवेंट के लिए स्टैक ट्रेस रिकॉर्ड किया जाता है. Android, AArch64 कोड में फ़्रेम पॉइंटर को डिफ़ॉल्ट रूप से चालू करता है. इसलिए, यह सुविधा बहुत अच्छी तरह से काम करती है. अगर आपको मैनेज किए गए कोड के ज़रिए अनवाइंड करना है, तो प्रोसेस एनवायरमेंट में HWASAN_OPTIONS=fast_unwind_on_malloc=0 सेट करें. ध्यान दें कि मेमोरी ऐक्सेस स्टैक के खराब होने की वजह से होने वाली गड़बड़ियों के ट्रेस के लिए, डिफ़ॉल्ट रूप से "स्लो" अनवाइंडर का इस्तेमाल किया जाता है. यह सेटिंग सिर्फ़ मेमोरी के बंटवारे और बंटवारे को रद्द करने से जुड़े ट्रेस पर असर डालती है. लोड के आधार पर, इस विकल्प में सीपीयू का इस्तेमाल बहुत ज़्यादा हो सकता है.

सिंबॉलिकेशन

"HWASan रिपोर्ट को समझना" में, सिंबोलाइज़ेशन देखें.

ऐप्लिकेशन में HWASan

AddressSanitizer की तरह, HWASan भी Java कोड को नहीं देख सकता. हालांकि, यह JNI लाइब्रेरी में मौजूद गड़बड़ियों का पता लगा सकता है. Android 14 से पहले, HWASan की सुविधा वाले ऐप्लिकेशन को HWASan की सुविधा के बिना काम करने वाले डिवाइस पर नहीं चलाया जा सकता था.

HWASan डिवाइस पर, ऐप्लिकेशन की जांच HWASan की मदद से की जा सकती है. इसके लिए, ऐप्लिकेशन के कोड को Make में SANITIZE_TARGET:=hwaddress या कंपाइलर फ़्लैग में -fsanitize=hwaddress के साथ बनाया जाता है. HWASan के बिना काम करने वाले डिवाइस (Android 14 या उसके बाद के वर्शन पर काम करने वाला) पर, wrap.sh फ़ाइल की सेटिंग LD_HWASAN=1 को जोड़ना होगा. ज़्यादा जानकारी के लिए, ऐप्लिकेशन डेवलपर का दस्तावेज़ देखें.