जीडब्ल्यूपी-असैन

GWP-ASan, एक नेटिव मेमोरी ऐलोकेटर सुविधा है, जो इस्तेमाल के बाद, बिना किसी शुल्क के और हीप-बफ़र-ओवरफ़्लो गड़बड़ियां. इसका अनौपचारिक नाम बार-बार इस्तेमाल होने वाला शॉर्ट फ़ॉर्म है,"GWP-ASan Will अलग जगह SANity". नापसंद करें HWASan या Malloc डीबग, GWP-ASan को सोर्स या रीकंपाइलेशन की ज़रूरत नहीं होती. इसका मतलब है कि यह इनके साथ काम करता है: पहले से मौजूद होता है) और 32- और 64-बिट दोनों प्रोसेस पर काम करता है (हालांकि, 32-बिट क्रैश हो जाता है) डीबग करने की जानकारी कम होनी चाहिए). इस विषय में उन कार्रवाइयों के बारे में बताया गया है जिनकी मदद से, अपने ऐप्लिकेशन में इस सुविधा को चालू किया जा सकता है है. GWP-ASan, उन ऐप्लिकेशन के लिए उपलब्ध है जो Android 11 (एपीआई लेवल 30) या उसके बाद के वर्शन को टारगेट करते हैं.

खास जानकारी

GWP-ASan को किसी भी क्रम में चुने गए कुछ सिस्टम ऐप्लिकेशन और प्लैटफ़ॉर्म पर चालू किया गया है प्रोसेस शुरू होने पर या ज़ीगोट फ़ोर्क होने पर, एक्ज़ीक्यूटेबल. इसमें GWP-ASan को चालू करें आपका अपना ऐप्लिकेशन हो, जिससे आपको मेमोरी से जुड़ी गड़बड़ियां ढूंढने में मदद मिल सके और आप ऐप्लिकेशन को ARM मेमोरी टैगिंग एक्सटेंशन (एमटीई) सहायता. सैंपलिंग के तरीकों का इस्तेमाल करने से, उपयोगकर्ताओं को मौत के बारे में पूछताछ.

चालू होने के बाद, GWP-ASan, हीप ऐलोकेशन के किसी भी क्रम में चुने गए सबसेट को इंटरसेप्ट करता है. और उन्हें एक ऐसे खास इलाके में डाल देता है जहां ढेर सारे कोड का पता लगाना मुश्किल होता है मेमोरी में गड़बड़ी होने की गड़बड़ियां. काफ़ी उपयोगकर्ता होने पर, सैंपलिंग की यह कम दर भी हीप मेमोरी सुरक्षा से जुड़ी गड़बड़ियों को ढूंढना होगा, जो नियमित टेस्ट में नहीं मिल पा रहे हैं. उदाहरण के लिए, GWP-ASan ने कई गड़बड़ियां को लोड किया है (इनमें से कई अब भी प्रतिबंधित व्यू में हैं).

GWP-ASan ने जितने भी बजट असाइन किए हैं उनके बारे में ज़्यादा जानकारी इकट्ठा की है इंटरसेप्ट करते हैं. यह जानकारी तब उपलब्ध होती है, जब GWP-ASan को स्टोरेज की सुरक्षा का पता चलता है उल्लंघन होता है और उसे अपने-आप नेटिव क्रैश रिपोर्ट में डाल दिया जाता है, जो डीबग करने में काफ़ी मदद करता है (उदाहरण देखें).

GWP-ASan को इस तरह से डिज़ाइन किया गया है कि वह सीपीयू से जुड़े ज़्यादा ओवरहेड न लगे. जीडब्ल्यूपी-असैन चालू होने पर, छोटा, फ़िक्स्ड रैम ओवरहेड देता है. इस ओवरहेड का फ़ैसला इन्होंने किया है यह Android सिस्टम पर काम करता है और मौजूदा समय में हर एक के लिए, यह करीब 70 किबीबाइट (KiB) है प्रभावित प्रक्रिया.

अपने ऐप्लिकेशन के लिए ऑप्ट-इन करें

GWP-ASan को, ऐप्लिकेशन की ओर से हर प्रोसेस के लेवल पर चालू किया जा सकता है. ऐसा करने के लिए, ऐप्लिकेशन मेनिफ़ेस्ट में android:gwpAsanMode टैग जोड़ा है. ये विकल्प मौजूद हैं: समर्थित:

  • हमेशा बंद (android:gwpAsanMode="never"): यह सेटिंग पूरी तरह से बंद है यह आपके ऐप्लिकेशन में GWP-ASan को बंद कर देता है. साथ ही, यह नॉन-सिस्टम ऐप्लिकेशन के लिए डिफ़ॉल्ट तौर पर लागू होता है.

  • डिफ़ॉल्ट (android:gwpAsanMode="default" या जानकारी नहीं दी गई): Android 13 (एपीआई) लेवल 33) और उससे पहले के लेवल - GWP-ASan को बंद किया गया है. Android 14 (एपीआई लेवल 34) और बाद वाली सेटिंग - रिकवर किए जा सकने वाले GWP-ASan को चालू किया गया हो.

  • हमेशा चालू रहने वाला (android:gwpAsanMode="always"): इस सेटिंग से चालू होती है आपके ऐप्लिकेशन में GWP-ASan से जुड़ी जानकारी जिसमें ये शामिल हैं:

    1. GWP-ASan के लिए, ऑपरेटिंग सिस्टम रैम की एक तय रकम सुरक्षित रखता है ऑपरेशन, प्रभावित होने वाली हर प्रोसेस के लिए करीब ~70KiB. (चालू करें अगर आपका ऐप्लिकेशन, मेमोरी बढ़ाने के लिए ज़्यादा संवेदनशील नहीं है, तो GWP-ASan इस्तेमाल करें.)

    2. GWP-ASan, हीप ऐलोकेशन के रैंडम तरीके से चुने गए सबसेट को इंटरसेप्ट करता है और उन्हें एक ऐसी खास जगह पर रखता है जो मेमोरी की सुरक्षा का भरोसेमंद तरीके से पता लगाती है उल्लंघन.

    3. किसी खास इलाके में मेमोरी की सुरक्षा से जुड़ा उल्लंघन होने पर, GWP-ASan प्रक्रिया को खत्म कर देता है.

    4. GWP-ASan, क्रैश की गड़बड़ी के बारे में ज़्यादा जानकारी देता है रिपोर्ट.

अपने ऐप्लिकेशन के लिए GWP-ASan को दुनिया भर में चालू करने के लिए, इन्हें अपने AndroidManifest.xml फ़ाइल:

<application android:gwpAsanMode="always">
  ...
</application>

इसके अलावा, GWP-ASan को खास जानकारी के लिए, साफ़ तौर पर चालू या बंद किया जा सकता है सबप्रोसेस पर लागू होती है. प्रोसेस का इस्तेमाल करके, गतिविधियों और सेवाओं को टारगेट किया जा सकता है जिन्होंने GWP-ASan से ऑप्ट-इन या ऑप्ट-आउट किया है. नीचे दिए गए निर्देशों का पालन करके उदाहरण:

<application>
  <processes>
    <!-- Create the (empty) application process -->
    <process />

    <!-- Create subprocesses with GWP-ASan both explicitly enabled and disabled. -->
    <process android:process=":gwp_asan_enabled"
               android:gwpAsanMode="always" />
    <process android:process=":gwp_asan_disabled"
               android:gwpAsanMode="never" />
  </processes>

  <!-- Target services and activities to be run on either the GWP-ASan enabled or disabled processes. -->
  <activity android:name="android.gwpasan.GwpAsanEnabledActivity"
            android:process=":gwp_asan_enabled" />
  <activity android:name="android.gwpasan.GwpAsanDisabledActivity"
            android:process=":gwp_asan_disabled" />
  <service android:name="android.gwpasan.GwpAsanEnabledService"
           android:process=":gwp_asan_enabled" />
  <service android:name="android.gwpasan.GwpAsanDisabledService"
           android:process=":gwp_asan_disabled" />
</application>

वापस पाया जा सकने वाला GWP-ASan

Android 14 (एपीआई लेवल 34) और उसके बाद के वर्शन की मदद से, रिकवर किया जा सकने वाला GWP-ASan से मदद मिलती है. डेवलपर को उपयोगकर्ता अनुभव को कमज़ोर किए बिना प्रोडक्शन के लिए डिज़ाइन किया गया है. जब android:gwpAsanMode होता है AndroidManifest.xml में नहीं बताया गया है, तो ऐप्लिकेशन 'वापस पाएं' सुविधा का इस्तेमाल करता है जीडब्ल्यूपी-असैन.

वापस पाया जा सकने वाला GWP-ASan, GWP-ASan के बेस को इन तरीकों से अलग करता है:

  1. वापस पाए जा सकने वाले GWP-ASan को सिर्फ़ 1% ऐप्लिकेशन लॉन्च पर चालू किया जा सकता है, इस्तेमाल करने पर ध्यान देना चाहिए.
  2. जब 'हीप-यूज़-आफ़्टर-फ़्री' या हीप-बफ़र-ओवरफ़्लो गड़बड़ी का पता चलता है, तो यह गड़बड़ी होती है क्रैश रिपोर्ट (टूंबस्टोन) में दिखती है. यह क्रैश रिपोर्ट उपलब्ध है से ActivityManager#getHistoricalProcessExitReasons एपीआई, मूल GWP-ASan के जैसा है.
  3. क्रैश रिपोर्ट को डंप करने के बाद बाहर निकलने के बजाय, वापस पाया जा सकने वाला GWP-ASan इससे मेमोरी खराब हो जाती है और ऐप्लिकेशन बिना किसी रुकावट के चलता रहता है. यह प्रोसेस पहले की तरह जारी रह सकती है. हालांकि, ऐप्लिकेशन काम नहीं करेगा बताया गया है. मेमोरी के खराब होने की वजह से, ऐप्लिकेशन आर्बिट्रेरी तरीके से क्रैश हो सकता है भविष्य में नहीं कर सकते या यह उपयोगकर्ताओं को दिखाई देने वाले प्रभाव के बिना जारी रह सकता है.
  4. क्रैश रिपोर्ट को डंप करने के बाद, वापस पाया जा सकने वाला GWP-ASan बंद हो जाता है. इसलिए, किसी ऐप्लिकेशन को हर ऐप्लिकेशन के लॉन्च के लिए, वापस पाई जा सकने वाली सिर्फ़ एक GWP-ASan रिपोर्ट मिल सकती है.
  5. अगर ऐप्लिकेशन में कोई कस्टम सिग्नल हैंडलर इंस्टॉल किया गया है, तो इसे कभी भी कॉल नहीं किया जाता SIGSEGV सिग्नल, जो वापस पाए जा सकने वाले GWP-ASan की गड़बड़ी का पता लगाता है.

क्योंकि रिकवर किए जा सकने वाले GWP-ASan के क्रैश से, मेमोरी के असल इंस्टेंस का पता चलता है असली उपयोगकर्ताओं के डिवाइसों पर गड़बड़ी है. इसलिए, हम गड़बड़ियों की जांच करने और उन्हें ठीक करने का सुझाव देते हैं इसकी पहचान, रिकवर किए जा सकने वाले GWP-ASan के ज़रिए की जाती है. हालांकि, इसे सबसे ज़्यादा प्राथमिकता दी जाती है.

डेवलपर सहायता

इन सेक्शन में, GWP-ASan का इस्तेमाल करते समय होने वाली समस्याओं और समस्याओं को हल करने का तरीका बताया गया है समस्या से निपटना.

ऐलोकेशन/डिलोकेशन ट्रेस मौजूद नहीं हैं

अगर आपको किसी ऐसे नेटिव क्रैश का पता चलता है जो मौजूद नहीं है ऐलोकेशन/डिलोकेशन फ़्रेम, शायद आपका ऐप्लिकेशन मौजूद न हो फ़्रेम पॉइंटर के तौर पर मार्क किया जा सकता है. GWP-ASan, फ़्रेम पॉइंटर का इस्तेमाल करके, इनके लिए ऐलोकेशन और डीललोकेशन ट्रेस रिकॉर्ड करता है की परफ़ॉर्मेंस कैसी होती है. साथ ही, अगर ऐसा नहीं होता है, तो स्टैक ट्रेस को चालू नहीं किया जा सकता उपस्थित.

फ़्रेम पॉइंटर, आर्म64 डिवाइसों के लिए डिफ़ॉल्ट रूप से चालू होते हैं और आर्म32 के लिए, डिफ़ॉल्ट रूप से बंद होते हैं डिवाइस. ऐप्लिकेशन का libc पर कंट्रोल नहीं होता, इसलिए (सामान्य तौर पर) GWP-ASan के लिए, 32-बिट के लिए ऐलोकेशन/डिलोकेशन ट्रेस इकट्ठा करना मुमकिन नहीं है या ऐप्लिकेशन न हो. 64-बिट ऐप्लिकेशन को यह पक्का करना चाहिए कि वे हों को -fomit-frame-pointer के साथ बनाया जाता है, ताकि GWP-ASan को बजट इकट्ठा करने और डील-लोकेशन स्टैक ट्रेस.

सुरक्षा से जुड़े उल्लंघनों को फिर से लागू करना

GWP-ASan को उपयोगकर्ता के डिवाइसों पर, मेमोरी की सुरक्षा से जुड़े ही उल्लंघनों का पता लगाने के लिए डिज़ाइन किया गया है. GWP-ASan, क्रैश के बारे में ज़्यादा से ज़्यादा जानकारी देता है (इसका ऐक्सेस ट्रेस उल्लंघन, वजह स्ट्रिंग, और ऐलोकेशन/डिलोकेशन ट्रेस) अब भी यह पता लगाना मुश्किल है कि उल्लंघन कैसे हुआ. माफ़ करें, गड़बड़ी की वजह से पता लगाना संभावित है, लेकिन GWP-ASan की रिपोर्ट को समझना अक्सर पेचीदा होता है. इसमें, स्थानीय डिवाइस.

ऐसे मामलों में, अगर गड़बड़ी 64-बिट वाले डिवाइसों पर असर डालती है, तो आपको HWAddressSanitizer (HWASan). HWASan, मेमोरी की सुरक्षा का पता लगाता है का इस्तेमाल किया जाता है. इसके साथ आपका ऐप्लिकेशन चलाया जा रहा है HWASan भरोसेमंद तरीके से वही नतीजा दिखा सकता है जो रिपोर्ट किया जा रहा है जीडब्ल्यूपी-असैन.

ऐसे मामलों में जहां HWASan के तहत आपके ऐप्लिकेशन को चलाना काफ़ी नहीं होता है की वजह से गड़बड़ी हो रही है, तो आपको कोड को फ़ज़ करें सवाल है. आप GWP-ASan रिपोर्ट, जो कोड की मौजूदा स्थिति का भरोसेमंद तरीके से पता लगा सकती है और उसकी जानकारी दे सकती है समस्याएं.

उदाहरण

इस उदाहरण में दिए गए नेटिव कोड में, हीप इस्तेमाल के बाद होने वाली गड़बड़ी की गड़बड़ी है:

#include <jni.h>
#include <string>
#include <string_view>

jstring native_get_string(JNIEnv* env) {
   std::string s = "Hellooooooooooooooo ";
   std::string_view sv = s + "World\n";

   // BUG: Use-after-free. `sv` holds a dangling reference to the ephemeral
   // string created by `s + "World\n"`. Accessing the data here is a
   // use-after-free.
   return env->NewStringUTF(sv.data());
}

extern "C" JNIEXPORT jstring JNICALL
Java_android11_test_gwpasan_MainActivity_nativeGetString(
    JNIEnv* env, jobject /* this */) {
  // Repeat the buggy code a few thousand times. GWP-ASan has a small chance
  // of detecting the use-after-free every time it happens. A single user who
  // triggers the use-after-free thousands of times will catch the bug once.
  // Alternatively, if a few thousand users each trigger the bug a single time,
  // you'll also get one report (this is the assumed model).
  jstring return_string;
  for (unsigned i = 0; i < 0x10000; ++i) {
    return_string = native_get_string(env);
  }

  return reinterpret_cast<jstring>(env->NewGlobalRef(return_string));
}

ऊपर दिए गए उदाहरण कोड का इस्तेमाल करके टेस्ट रन के लिए, GWP-ASan ने और नीचे दी गई क्रैश रिपोर्ट ट्रिगर की गई है. GWP-ASan अपने-आप रिपोर्ट को बेहतर बनाने के लिए, क्रैश के टाइप के बारे में जानकारी दी, ऐलोकेशन मेटाडेटा, और उनसे जुड़े ऐलोकेशन और डीललोकेशन स्टैक ट्रेस.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/sargo/sargo:10/RPP3.200320.009/6360804:userdebug/dev-keys'
Revision: 'PVT1.0'
ABI: 'arm64'
Timestamp: 2020-04-06 18:27:08-0700
pid: 16227, tid: 16227, name: 11.test.gwpasan  >>> android11.test.gwpasan <<<
uid: 10238
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x736ad4afe0
Cause: [GWP-ASan]: Use After Free on a 32-byte allocation at 0x736ad4afe0

backtrace:
      #00 pc 000000000037a090  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckNonHeapValue(char, art::(anonymous namespace)::JniValueType)+448)
      #01 pc 0000000000378440  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&, char, art::(anonymous namespace)::JniValueType)+204)
      #02 pc 0000000000377bec  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*)+612)
      #03 pc 000000000036dcf4  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+708)
      #04 pc 000000000000eda4  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (_JNIEnv::NewStringUTF(char const*)+40)
      #05 pc 000000000000eab8  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+144)
      #06 pc 000000000000edf8  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
      ...

deallocated by thread 16227:
      #00 pc 0000000000048970  /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::AllocationMetadata::CallSiteInfo::RecordBacktrace(unsigned long (*)(unsigned long*, unsigned long))+80)
      #01 pc 0000000000048f30  /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::GuardedPoolAllocator::deallocate(void*)+184)
      #02 pc 000000000000f130  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (std::__ndk1::_DeallocateCaller::__do_call(void*)+20)
      ...
      #08 pc 000000000000ed6c  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::~basic_string()+100)
      #09 pc 000000000000ea90  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+104)
      #10 pc 000000000000edf8  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
      ...

allocated by thread 16227:
      #00 pc 0000000000048970  /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::AllocationMetadata::CallSiteInfo::RecordBacktrace(unsigned long (*)(unsigned long*, unsigned long))+80)
      #01 pc 0000000000048e4c  /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::GuardedPoolAllocator::allocate(unsigned long)+368)
      #02 pc 000000000003b258  /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan_malloc(unsigned long)+132)
      #03 pc 000000000003bbec  /apex/com.android.runtime/lib64/bionic/libc.so (malloc+76)
      #04 pc 0000000000010414  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (operator new(unsigned long)+24)
      ...
      #10 pc 000000000000ea6c  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+68)
      #11 pc 000000000000edf8  /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
      ...

ज़्यादा जानकारी

GWP-ASan को लागू करने की जानकारी के बारे में ज़्यादा जानने के लिए, LLVM दस्तावेज़. सीखने में Android नेटिव क्रैश रिपोर्ट के बारे में ज़्यादा जानें, नेटिव क्रैश का पता लगाना.