Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.
Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

AddressSanitizer

AddressSanitizer (ASan) adalah alat berbasis kompiler cepat untuk mendeteksi bug memori dalam kode asli.

ASan mendeteksi:

  • Stack dan heap buffer overflow / underflow
  • Penggunaan heap setelah gratis
  • Stack digunakan di luar ruang lingkup
  • Bebas ganda / bebas liar

ASan berjalan pada ARM 32-bit dan 64-bit, ditambah x86 dan x86-64. Overhead CPU ASan kira-kira 2x, overhead ukuran kode antara 50% dan 2x, dan overhead memori yang besar (bergantung pada pola alokasi Anda, tetapi dengan urutan 2x).

Android 10 dan cabang master AOSP di AArch64 mendukung hardware-accelerated ASan (HWASan) , alat serupa dengan overhead RAM lebih rendah dan lebih banyak bug terdeteksi. HWASan mendeteksi penggunaan stack setelah dikembalikan, selain bug yang terdeteksi oleh ASan.

HWASan memiliki overhead CPU dan ukuran kode yang serupa, tetapi overhead RAM yang jauh lebih kecil (15%). HWASan tidak bersifat deterministik. Hanya ada 256 kemungkinan nilai tag, jadi ada kemungkinan rata-rata 0,4% kehilangan bug. HWASan tidak memiliki zona merah ukuran terbatas ASan untuk mendeteksi luapan dan karantina berkapasitas terbatas untuk mendeteksi penggunaan setelah bebas, jadi tidak masalah bagi HWASan seberapa besar luapan atau berapa lama memori dibatalkan alokasinya. Hal ini membuat HWASan lebih baik dari ASan. Anda dapat membaca lebih lanjut tentang desain HWASan atau tentang penggunaan HWASan di Android .

ASan mendeteksi tumpukan / luapan global selain luapan heap, dan cepat dengan overhead memori minimal.

Dokumen ini menjelaskan cara membangun dan menjalankan sebagian / semua Android dengan ASan. Jika Anda membuat aplikasi SDK / NDK dengan ASan, lihat Address Sanitizer sebagai gantinya.

Sanitasi file yang dapat dieksekusi dengan ASan

Tambahkan LOCAL_SANITIZE:=address or sanitize: { address: true } ke aturan build untuk executable. Anda dapat mencari kode untuk contoh yang ada atau untuk menemukan pembersih lain yang tersedia.

Ketika bug terdeteksi, ASan mencetak laporan verbose ke output standar dan ke logcat dan kemudian menghentikan proses.

Sanitasi perpustakaan bersama dengan ASan

Karena cara kerja ASan, library yang dibangun dengan ASan hanya dapat digunakan oleh executable yang dibuat dengan ASan.

Untuk membersihkan pustaka bersama yang digunakan di beberapa file yang dapat dieksekusi, tidak semuanya dibangun dengan ASan, Anda memerlukan dua salinan pustaka. Cara yang disarankan untuk melakukannya adalah dengan menambahkan yang berikut ini ke Android.mk untuk modul yang dimaksud:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Ini menempatkan perpustakaan di /system/lib/asan daripada /system/lib . Kemudian, jalankan file yang dapat dieksekusi dengan:

LD_LIBRARY_PATH=/system/lib/asan

Untuk daemon sistem, tambahkan baris berikut ke bagian yang sesuai dari /init.rc atau /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Verifikasi bahwa proses menggunakan pustaka dari /system/lib/asan saat ada dengan membaca /proc/$PID/maps . Jika tidak, Anda mungkin perlu menonaktifkan SELinux:

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.

Jejak tumpukan yang lebih baik

ASan menggunakan unwinder berbasis penunjuk-bingkai yang cepat untuk merekam pelacakan tumpukan untuk setiap alokasi memori dan peristiwa deallocation dalam program. Sebagian besar Android dibuat tanpa penunjuk bingkai. Akibatnya, Anda sering kali hanya mendapatkan satu atau dua bingkai yang bermakna. Untuk memperbaikinya, buat ulang pustaka dengan ASan (disarankan!), Atau dengan:

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

Atau atur ASAN_OPTIONS=fast_unwind_on_malloc=0 di lingkungan proses. Yang terakhir bisa sangat intensif CPU, tergantung pada beban.

Simbolisasi

Awalnya, laporan ASan berisi referensi ke offset dalam biner dan pustaka bersama. Ada dua cara untuk mendapatkan file sumber dan informasi baris:

  • Pastikan biner llvm-symbolizer ada di /system/bin . llvm-symbolizer dibangun dari sumber di third_party/llvm/tools/llvm-symbolizer .
  • Filter laporan melalui external/compiler-rt/lib/asan/scripts/symbolize.py .

Pendekatan kedua dapat memberikan lebih banyak data (yaitu, file:line lokasi file:line ) karena ketersediaan pustaka yang disimbolkan pada host.

ASan dalam aplikasi

ASan tidak dapat melihat ke dalam kode Java, tetapi dapat mendeteksi bug di perpustakaan JNI. Untuk itu, Anda perlu membangun executable dengan ASan, yang dalam hal ini adalah /system/bin/app_process( 32|64 ) . Ini memungkinkan ASan di semua aplikasi pada perangkat pada saat yang sama, yang merupakan beban berat, tetapi perangkat dengan RAM 2 GB seharusnya dapat menangani ini.

Tambahkan LOCAL_SANITIZE:=address ke aturan build app_process di frameworks/base/cmds/app_process . Abaikan target app_process__asan dalam file yang sama untuk saat ini (jika masih ada pada saat Anda membaca ini).

Edit bagian service zygote dari file system/core/rootdir/init.zygote( 32|64 ).rc sesuai untuk menambahkan baris berikut ke blok baris berindentasi yang berisi class main , juga diindentasi dengan jumlah yang sama:

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

Bangun, sinkronisasi adb, boot fastboot flash, dan reboot.

Menggunakan properti wrap

Pendekatan di bagian sebelumnya menempatkan ASan ke dalam setiap aplikasi di sistem (sebenarnya, ke dalam setiap turunan proses Zygote). Dimungkinkan untuk menjalankan hanya satu (atau beberapa) aplikasi dengan ASan, memperdagangkan beberapa overhead memori untuk memulai aplikasi yang lebih lambat.

Ini dapat dilakukan dengan memulai aplikasi Anda dengan wrap. Properti. Contoh berikut menjalankan aplikasi Gmail di bawah ASan:

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

Dalam konteks ini, asanwrapper rewrites /system/bin/app_process ke /system/bin/asan/app_process , yang dibangun dengan ASan. Ia juga menambahkan /system/lib/asan di awal jalur pencarian perpustakaan dinamis. Dengan cara ini pustaka yang diinstrumentasi ASan dari /system/lib/asan lebih disukai daripada pustaka normal di /system/lib saat dijalankan dengan asanwrapper .

Jika bug ditemukan, aplikasi macet, dan laporan dicetak ke log.

SANITIZE_TARGET

Android 7.0 dan lebih tinggi menyertakan dukungan untuk membangun seluruh platform Android dengan ASan sekaligus. (Jika Anda membuat rilis lebih tinggi dari Android 9, HWASan adalah pilihan yang lebih baik.)

Jalankan perintah berikut di pohon build yang sama.

make -j42
SANITIZE_TARGET=address make -j42

Dalam mode ini, userdata.img berisi pustaka tambahan dan harus di-flash ke perangkat juga. Gunakan baris perintah berikut:

fastboot flash userdata && fastboot flashall

Ini membangun dua set pustaka bersama: normal in /system/lib (pemanggilan make pertama), dan ASan-instrumented in /data/asan/lib (pemanggilan make kedua). Executable dari build kedua menimpa yang dari build pertama. File executable yang diinstrumentasi AS mendapatkan jalur pencarian perpustakaan berbeda yang menyertakan /data/asan/lib sebelum /system/lib melalui penggunaan /system/bin/linker_asan di PT_INTERP .

Sistem build mengacaukan direktori objek perantara ketika nilai $SANITIZE_TARGET telah berubah. Ini memaksa pembangunan kembali semua target sambil mempertahankan binari yang diinstal di bawah /system/lib .

Beberapa target tidak dapat dibangun dengan ASan:

  • Dapat dieksekusi yang ditautkan secara statis
  • LOCAL_CLANG:=false target LOCAL_CLANG:=false
  • LOCAL_SANITIZE:=false tidak ASan untuk SANITIZE_TARGET=address

Executable seperti ini dilewati dalam build SANITIZE_TARGET , dan versi dari pemanggilan pertama dibiarkan di /system/bin .

Perpustakaan seperti ini dibangun tanpa ASan. Mereka dapat berisi beberapa kode ASan dari pustaka statis yang mereka andalkan.

Dokumentasi pendukung