AdresDezenfektan

AdresSanitizer (ASan), yerel koddaki bellek hatalarını tespit etmek için hızlı, derleyici tabanlı bir araçtır.

ASan şunları tespit eder:

  • Yığın ve yığın arabellek taşması/az akışı
  • Bedavadan sonra yığın kullanımı
  • Kapsam dışında yığın kullanımı
  • Çift özgür/vahşi özgür

ASan hem 32 bit hem de 64 bit ARM'nin yanı sıra x86 ve x86-64'te çalışır. ASan'ın CPU yükü kabaca 2 kat, kod boyutu yükü %50 ila 2 kat arasında ve büyük bir bellek yükü (tahsis düzenlerinize bağlı olarak ancak 2 kat civarında).

Android 10 ve AArch64'teki AOSP ana şubesi, daha düşük RAM yüküne ve daha geniş bir algılanan hata yelpazesine sahip benzer bir araç olan donanım hızlandırmalı ASan'ı (HWASan) destekler. HWASan, ASan tarafından tespit edilen hatalara ek olarak dönüş sonrasında yığın kullanımını da tespit eder.

HWASan benzer CPU ve kod boyutu yüküne sahiptir ancak çok daha küçük bir RAM yüküne sahiptir (%15). HWASan belirleyici değildir. Yalnızca 256 olası etiket değeri vardır, dolayısıyla herhangi bir hatanın gözden kaçırılma olasılığı %0,4'tür. HWASan, taşmaları tespit etmek için ASan'ın sınırlı boyutlu kırmızı bölgelerine ve serbest kullanımdan sonra kullanımı tespit etmek için sınırlı kapasiteli karantinaya sahip değildir, bu nedenle taşmanın ne kadar büyük olduğu veya belleğin ne kadar zaman önce serbest bırakıldığı HWASan için önemli değildir. Bu HWASan'ı ASan'dan daha iyi kılar. HWASan'ın tasarımı veya HWASan'ın Android'de kullanımı hakkında daha fazla bilgi edinebilirsiniz.

ASan, yığın taşmalarının yanı sıra yığın/genel taşmalarını da algılar ve minimum bellek yüküyle hızlıdır.

Bu belgede ASan ile Android'in bazı bölümlerinin/tümünün nasıl oluşturulacağı ve çalıştırılacağı açıklanmaktadır. ASan ile bir SDK/NDK uygulaması oluşturuyorsanız bunun yerine Adres Temizleyici'ye bakın.

ASan ile bireysel yürütülebilir dosyaların temizlenmesi

Yürütülebilir dosyanın derleme kuralına LOCAL_SANITIZE:=address veya sanitize: { address: true } ekleyin. Mevcut örnekleri bulmak için kodda arama yapabilir veya mevcut diğer dezenfektanları bulabilirsiniz.

Bir hata tespit edildiğinde ASan, hem standart çıktıya hem de logcat ayrıntılı bir rapor yazdırır ve ardından süreci çökertir.

ASan ile paylaşılan kütüphanelerin temizlenmesi

ASan'ın çalışma şekli nedeniyle, ASan ile oluşturulmuş bir kütüphane yalnızca ASan ile oluşturulmuş bir yürütülebilir dosya tarafından kullanılabilir.

Hepsi ASan ile oluşturulmamış birden fazla yürütülebilir dosyada kullanılan paylaşılan bir kitaplığı temizlemek için kitaplığın iki kopyasına ihtiyacınız vardır. Bunu yapmanın önerilen yolu, söz konusu modül için Android.mk aşağıdakileri eklemektir:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Bu, kütüphaneyi /system/lib/asan yerine /system/lib /asan içine yerleştirir. Ardından yürütülebilir dosyanızı şununla çalıştırın:

LD_LIBRARY_PATH=/system/lib/asan

Sistem arka plan programları için, /init.rc veya /init.$device$.rc dosyasının uygun bölümüne aşağıdakini ekleyin.

setenv LD_LIBRARY_PATH /system/lib/asan

/proc/$PID/maps okuyarak, işlemin mevcut olduğunda /system/lib/asan kitaplıkları kullandığını doğrulayın. Değilse SELinux'u devre dışı bırakmanız gerekebilir:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Daha iyi yığın izleri

ASan, programdaki her bellek tahsisi ve serbest bırakma olayı için bir yığın izlemesi kaydetmek üzere hızlı, çerçeve işaretçisi tabanlı bir çözücü kullanır. Android'in çoğu çerçeve işaretçileri olmadan oluşturulmuştur. Sonuç olarak, genellikle yalnızca bir veya iki anlamlı çerçeve elde edersiniz. Bunu düzeltmek için kitaplığı ASan (önerilen!) ile veya şununla yeniden oluşturun:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Veya işlem ortamında ASAN_OPTIONS=fast_unwind_on_malloc=0 ayarlayın. İkincisi, yüke bağlı olarak CPU'yu çok yoğun kullanabilir.

Sembolizasyon

Başlangıçta, ASan raporları ikili dosyalar ve paylaşılan kütüphanelerdeki uzaklıklara referanslar içerir. Kaynak dosya ve satır bilgilerini edinmenin iki yolu vardır:

  • llvm-symbolizer ikili dosyasının /system/bin dosyasında mevcut olduğundan emin olun. llvm-symbolizer third_party/llvm/tools/llvm-symbolizer içindeki kaynaklardan oluşturulmuştur.
  • Raporu external/compiler-rt/lib/asan/scripts/symbolize.py betiğiyle filtreleyin.

İkinci yaklaşım, ana bilgisayardaki sembolize edilmiş kitaplıkların kullanılabilirliği nedeniyle daha fazla veri (yani file:line konumları) sağlayabilir.

Uygulamalarda ASan

ASan, Java kodunu göremez ancak JNI kitaplıklarındaki hataları tespit edebilir. Bunun için yürütülebilir dosyayı ASan ile oluşturmanız gerekir; bu durumda bu /system/bin/app_process( 32|64 ) . Bu, ASan'ın cihazdaki tüm uygulamalarda aynı anda etkinleştirilmesini sağlar, bu da ağır bir yüktür ancak 2 GB RAM'e sahip bir cihazın bunu kaldırabilmesi gerekir.

frameworks/base/cmds/app_process içindeki app_process derleme kuralına LOCAL_SANITIZE:=address ekleyin. Şimdilik aynı dosyadaki app_process__asan hedefini göz ardı edin (eğer bunu okuduğunuz sırada hala oradaysa).

Uygun system/core/rootdir/init.zygote( 32|64 ).rc dosyasının service zygote bölümünü düzenleyerek class main içeren girintili satırlar bloğuna yine aynı miktarda girintili olan aşağıdaki satırları ekleyin:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Oluşturma, adb senkronizasyonu, fastboot flash önyükleme ve yeniden başlatma.

sarma özelliğini kullanma

Önceki bölümdeki yaklaşım ASan'ı sistemdeki her uygulamaya (aslında Zygote sürecinin her soyuna) yerleştirir. ASan ile yalnızca bir (veya daha fazla) uygulamayı çalıştırmak mümkündür, bu da uygulamanın daha yavaş başlatılması için bir miktar bellek yükünü değiştirir.

Bu, uygulamanızı wrap. mülk. Aşağıdaki örnek, Gmail uygulamasını ASan altında çalıştırmaktadır:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

Bu bağlamda asanwrapper , /system/bin/app_process ASan ile oluşturulmuş /system/bin/asan/app_process dosyasına yeniden yazar. Ayrıca dinamik kitaplık arama yolunun başına /system/lib/asan eklenir. Bu şekilde, asanwrapper ile çalışırken /system/lib/asan ASan-araçlı kütüphaneler /system/lib normal kütüphanelere tercih edilir.

Bir hata bulunursa uygulama çöker ve rapor günlüğe yazdırılır.

SANITIZE_TARGET

Android 7.0 ve üzeri, ASan ile tüm Android platformunun aynı anda oluşturulması desteğini içerir. (Android 9'dan daha yüksek bir sürüm oluşturuyorsanız HWASan daha iyi bir seçimdir.)

Aşağıdaki komutları aynı yapı ağacında çalıştırın.

make -j42
SANITIZE_TARGET=address make -j42

Bu modda userdata.img ekstra kütüphaneler içerir ve cihaza da flashlanması gerekir. Aşağıdaki komut satırını kullanın:

fastboot flash userdata && fastboot flashall

Bu, iki grup paylaşılan kitaplık oluşturur: /system/lib normal (ilk make çağrısı) ve /data/asan/lib ASan-instrumented (ikinci make çağrısı). İkinci yapıdaki yürütülebilir dosyalar, ilk yapıdakilerin üzerine yazılır. ASan destekli yürütülebilir dosyalar, PT_INTERP /system/bin/linker_asan /system/lib önce /data/asan/lib içeren farklı bir kitaplık arama yolu alır.

$SANITIZE_TARGET değeri değiştiğinde derleme sistemi ara nesne dizinlerini gizler. Bu, /system/lib altında yüklü ikili dosyaları korurken tüm hedeflerin yeniden oluşturulmasını zorlar.

Bazı hedefler ASan ile oluşturulamaz:

  • Statik olarak bağlantılı yürütülebilir dosyalar
  • LOCAL_CLANG:=false hedefler
  • LOCAL_SANITIZE:=false SANITIZE_TARGET=address için ASan't edilmedi

Bunun gibi yürütülebilir dosyalar SANITIZE_TARGET yapısında atlanır ve ilk make çağrısındaki sürüm /system/bin dosyasında bırakılır.

Bunun gibi kütüphaneler ASan olmadan inşa edilir. Bağlı oldukları statik kitaplıklardan bazı ASan kodlarını içerebilirler.

Destekleyici belgeler