GWP-ASan

GWP-ASan, kullanıcıların aradıkları öğeleri bulmanıza kullanımdan sonra kullanın ve yığın-arabellek taşması hatalar. Resmi olmayan adı yinelemeli bir kısaltmadır,"GWP-ASan Will Özelme Atısı SAN'sı". Beğenmeyi kaldır HWASan veya Malloc Hata Ayıklaması, GWP-ASan, kaynak veya yeniden derleme gerektirmez (yani önceden oluşturulmuş) çalışır ve hem 32 hem de 64 bit işlemlerde çalışır (32 bit kilitlenmelerine rağmen) daha az hata ayıklama bilgisi vardır). Bu konu, Google Ads hesabınızda bu özelliği etkinleştirmek için yapmanız gerekenleri uygulamasını indirin. GWP-ASan, Android 11 (API düzeyi 30) veya sonraki sürümleri hedefleyen uygulamalarda kullanılabilir.

Genel Bakış

GWP-ASan, rastgele seçilen bazı sistem uygulamalarında ve platformlarda etkinleştirilmiştir işlem başlatıldığında (veya zigot çatallandığında) yürütülebilir dosyalar. GWP-ASan'ı şurada etkinleştir: hataları bulmanıza ve uygulamanızı yeni kullanıma hazırlamanıza ARM Bellek Etiketleme Uzantısı (MTE) desteği. Tahsis örnekleme mekanizmaları şuna karşı güvenilirlik de sağlar: ölüm sorguları.

Etkinleştirildiğinde GWP-ASan, yığın ayırmaların rastgele seçilmiş bir alt kümesini ve bunları, fark edilmesi zor yığınları yakalayan özel bir bölgeye yerleştirir hataları da olabilir. Yeterli sayıda kullanıcı düşünüldüğünde, düşük örnekleme hızı bile düzenli testlerle bulunamayan yığın bellek güvenliği hatalarını bulma. Örneğin, GWP-ASan çok sayıda hata (çoğu hâlâ kısıtlı görünüm altındadır).

GWP-ASan, yaptığı tüm ayırmalar hakkında ek bilgi toplar. kesmeleridir. Bu bilgiler, GWP-ASan bir bellek güvenliği algıladığında kullanılabilir ve otomatik olarak yerel kilitlenme raporuna yerleştirilir. Bu rapor, hata ayıklamaya önemli ölçüde yardımcı olabilir (örneğe bakın).

GWP-ASan, önemli bir CPU ek yükü oluşturmayacak şekilde tasarlanmıştır. GWP-ASan etkinleştirildiğinde küçük, sabit bir RAM ek yükü getirir. Bu genel gider olduğunu ve şu anda her biri için yaklaşık 70 kibibayt (KiB) destekleyici materyalleri inceleyeceksiniz.

Uygulamanızı dahil edin

GWP-ASan, Uygulama manifest'indeki android:gwpAsanMode etiketi. Aşağıdaki seçenekler şunlardır: desteklenir:

  • Her zaman devre dışı (android:gwpAsanMode="never"): Bu ayar tamamen uygulamanızda GWP-ASan'ı devre dışı bırakır ve sistem dışı uygulamalar için varsayılan değerdir.

  • Varsayılan (android:gwpAsanMode="default" veya belirtilmedi): Android 13 (API) düzey 33) ve bu düzeyin altındaysa GWP-ASan devre dışıdır. Android 14 (API düzeyi 34) ve daha yüksek: Kurtarılabilir GWP-ASan etkin.

  • Her zaman etkin (android:gwpAsanMode="always"): Bu ayar, Uygulamanızdaki GWP-ASan şunları içerir:

    1. İşletim sistemi, GWP-ASan için sabit miktarda RAM ayırır yaklaşık 70 KiB'lık bir sınıra sahip. (Etkinleştir Uygulamanız bellekteki artışlara karşı kritik öneme sahip değilse GWP-ASan hakkında bilgi edinin.)

    2. GWP-ASan, yığın ayırmaların rastgele seçilmiş bir alt kümesini bunları, bellek güvenliğini güvenilir şekilde algılayan özel bir bölgeye yerleştirir. ihlal eder.

    3. Özel bir bölgede bellek güvenliği ihlali meydana geldiğinde GWP-ASan işlemi sonlandırır.

    4. GWP-ASan, kilitlenmedeki hata hakkında ek bilgi sağlar rapordur.

GWP-ASan'i uygulamanızda genel olarak etkinleştirmek için aşağıdakileri ekleyin: AndroidManifest.xml dosyası:

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

Ayrıca, GWP-ASan belirli uygulamalar için açıkça etkinleştirilebilir veya devre dışı bırakılabilir. alt işlemleri açıklanabilir. İşlemleri kullanarak etkinlikleri ve hizmetleri hedefleyebilirsiniz GWP-ASan'a açıkça kaydolmuş veya kapsam dışı bırakılmış kullanıcılar. Aşağıdakilere göz atın: örnek:

<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>

Kurtarılabilir GWP-ASan

Android 14 (API düzeyi 34) ve sonraki sürümler, geliştiriciler, ve üretim sürecinin bir parçasıdır. android:gwpAsanMode şu olduğunda: uygulama, AndroidManifest.xml politikasında belirtilmemişse Kurtarılabilir GWP-ASan.

Kurtarılabilir GWP-ASan, temel GWP-ASan'dan şu bakımlardan farklıdır:

  1. Kurtarılabilir GWP-ASan, uygulama lansmanlarının yalnızca yaklaşık% 1'inde etkindir. değil.
  2. Boş olduğunda yığın kullanımı veya yığın arabellek taşması hatası algılandığında bu hata simgesi görünür. Bu kilitlenme raporu mevcut aracılığıyla ActivityManager#getHistoricalProcessExitReasons API, orijinal GWP-ASan ile aynıdır.
  3. Kilitlenme raporunun dökümünden sonra çıkmak yerine, Kurtarılabilir GWP-ASan uygulama çalışmaya devam eder. Süreç her zamanki gibi devam edebilir ancak uygulama artık eski belirtiliyor. Bellek bozulması nedeniyle uygulama rastgele aralıklarla kilitlenebilir veya kullanıcı tarafından görülebilecek herhangi bir etkisi olmadan devam edebilir.
  4. Kilitlenme raporu dökümünden sonra kurtarılabilir GWP-ASan devre dışı bırakılır. Dolayısıyla, Bir uygulama, uygulama lansmanı başına yalnızca bir Kurtarılabilir GWP-ASan raporu alabilir.
  5. Uygulamada özel bir sinyal işleyici yüklüyse Kurtarılabilir GWP-ASan hatasını gösteren bir SIGSEGV sinyali.

Kurtarılabilir GWP-ASan kilitlenmeleri, gerçek bellek örneklerini gösterir. bozulmadığı için, hataları önceliklendirmenizi ve düzeltmenizi önemle tavsiye ederiz Kurtarılabilir GWP-ASan tarafından yüksek öncelikli olarak tanımlanmıştır.

Geliştirici desteği

Bu bölümlerde, GWP-ASan kullanırken oluşabilecek sorunlar ve bunları ele alın.

Ayırma/ayırma izleri eksik

Eksik görünen bir yerel kilitlenmeyi teşhis ediyorsanız ayırma çerçeveleri kullanıyorsanız, uygulamanız büyük olasılıkla eksik çerçeve işaretçilerini kullanın. GWP-ASan, alan adları için ayırma ve dağıtım izlerini kaydetmek üzere kare işaretçilerini kullanır. performansın neden olduğunu belirler ve devam eder.

Çerçeve işaretçileri, arm64 cihazlarda varsayılan olarak etkin, arm32 için ise varsayılan olarak devre dışıdır. cihazlar. Uygulamaların libc üzerinde kontrolü olmadığından, (genel olarak) GWP-ASan'ın, 32 bit için ayırma/ayırma izlerini toplaması mümkün değildir dosyalar veya uygulamalarla ilgili daha fazla bilgi edinin. 64 bit uygulamalar, bu uygulamaların olmadığından GWP-ASan'ın ayırmaları ve verileri toplayabilmesi için -fomit-frame-pointer ile oluşturulur yığın izlemeleri içerir.

Güvenlik ihlallerini tekrar oluşturma

GWP-ASan, kullanıcı cihazlarındaki yığın bellek güvenliği ihlallerini yakalamak için tasarlanmıştır. GWP-ASan, kilitlenme hakkında mümkün olduğunca fazla bağlam sağlıyor (erişim izi dize ve ayırma/ayırma izlemeleri gibi durumlar yaşanabilir, ancak ihlalin nasıl gerçekleştiğini anlamak zordur. Maalesef hata olarak ancak GWP-ASan raporlarının yeniden üretilmesi çoğu zaman karmaşıktır. yerel cihaz.

Bu gibi durumlarda, hata 64 bit cihazları etkiliyorsa HWAddressSanitizer (HWASan). HWASan, bellek güvenliğini algıladı yığın, yığın ve global öğelerde güvenilir şekilde ihlal edildiğini gösterir. Uygulamanızı şununla çalıştırma HWASan, Google Ad Manager tarafından bildirilen sonucun GWP-ASan.

Uygulamanızı HWASan altında çalıştırmanın bir hataya neden olduğunu öğrendiğinizde, kodu bulanıklaştırma söz konusu olabilir. Fizzleme çalışmalarınızı Temel kod durumunu güvenilir bir şekilde tespit edip ortaya çıkarabilen GWP-ASan raporu neden olabilir.

Örnek

Bu örnek yerel kodda, boşaltıldıktan sonra yığın kullanımı hatası vardır:

#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));
}

Yukarıdaki örnek kodu kullanan bir test çalıştırması için, GWP-ASan ve aşağıdaki kilitlenme raporunu tetikledi. GWP-ASan otomatik olarak kilitlenmenin türü, ayırma meta verileri, ilişkili ayırma ve dağıtım yığını izler.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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)
      ...

Daha fazla bilgi

GWP-ASan uygulama ayrıntıları hakkında daha fazla bilgi için LLVM belgeleri. Öğrenmek için Android yerel kilitlenme raporları hakkında daha fazla bilgi için bkz. Yerel Kilitlenmeleri Teşhis Etme.