Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Pembersih LLVM

LLVM, infrastruktur compiler yang digunakan untuk membangun Android, berisi banyak komponen yang melakukan analisis statis dan dinamis. Dari komponen ini, pembersih — khususnya AddressSanitizer dan UndefinedBehaviorSanitizer — dapat digunakan secara ekstensif untuk menganalisis Android. Sanitizer adalah komponen instrumentasi berbasis kompiler yang terdapat dalam external / compiler-rt yang dapat digunakan selama pengembangan dan pengujian untuk menyingkirkan bug dan membuat Android menjadi lebih baik. Kumpulan pembersih Android saat ini dapat menemukan dan mendiagnosis banyak bug penyalahgunaan memori dan perilaku tidak terdefinisi yang berpotensi berbahaya.

Praktik terbaik untuk build Android adalah mem-boot dan menjalankan pembersih yang diaktifkan, seperti AddressSanitizer dan UndefinedBehaviorSanitizer. Halaman ini memperkenalkan AddressSanitizer, UndefinedBehaviorSanitizer, dan KernelAddressSanitizer, menunjukkan bagaimana keduanya dapat digunakan dalam sistem build Android, dan memberikan contoh file Android.mk dan Android.bp yang membangun komponen asli dengan pembersih ini diaktifkan.

AddressSanitizer

AddressSanitizer (ASan) adalah kapabilitas instrumentasi berbasis kompiler yang mendeteksi banyak jenis kesalahan memori dalam kode C / C ++ saat runtime. ASan dapat mendeteksi banyak kelas kesalahan memori, termasuk:

  • Akses memori di luar batas
  • Gratis ganda
  • Gunakan setelah bebas

Android memungkinkan instrumentasi ASan pada level full-build dan level aplikasi dengan asanwrapper.

AddressSanitizer menggabungkan instrumentasi dari semua panggilan fungsi terkait memori — termasuk alloca, malloc, dan free — dan mengisi semua variabel dan wilayah memori yang dialokasikan dengan memori yang memicu callback ASan saat dibaca atau ditulis.

Instrumentasi memungkinkan ASan mendeteksi bug penggunaan memori yang tidak valid, termasuk ruang lingkup bebas ganda, dan penggunaan setelah, pengembalian, dan bebas, sementara padding wilayah memori mendeteksi pembacaan atau penulisan di luar batas. Jika membaca atau menulis ke wilayah padding ini terjadi, AS dapat menangkapnya dan mengeluarkan informasi untuk membantu mendiagnosis pelanggaran memori, termasuk tumpukan panggilan, peta memori bayangan, jenis pelanggaran memori, apa yang dibaca atau ditulis, instruksi yang menyebabkan pelanggaran, dan isi memori.

pixel-xl:/ # sanitizer-status                                                                                            
=================================================================
==14164==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0032000054b0 at pc 0x005df16ffc3c bp 0x007fc236fdf0 sp 0x007fc236fdd0
WRITE of size 1 at 0x0032000054b0 thread T0
    #0 0x5df16ffc3b in test_crash_malloc sanitizer-status/sanitizer-status.c:36:13
    #1 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #2 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #3 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)

0x0032000054b0 is located 0 bytes to the right of 32-byte region [0x003200005490,0x0032000054b0)
allocated by thread T0 here:
    #0 0x794d0bdc67 in malloc (/system/lib64/libclang_rt.asan-aarch64-android.so+0x74c67)
    #1 0x5df16ffb47 in test_crash_malloc sanitizer-status/sanitizer-status.c:34:25
    #2 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7
    #3 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3)
    #4 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53)
    #5 0x794df78893  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow sanitizer-status/sanitizer-status.c:36:13 in test_crash_malloc

Terkadang, proses penemuan bug tampak non-deterministik, terutama untuk bug yang memerlukan penyiapan khusus atau teknik yang lebih canggih, seperti heap priming atau eksploitasi kondisi balapan. Banyak dari bug ini tidak segera terlihat, dan dapat memunculkan ribuan instruksi dari pelanggaran memori yang merupakan akar penyebab sebenarnya. ASan melengkapi semua fungsi yang berhubungan dengan memori dan data pad dengan area yang tidak dapat diakses tanpa memicu panggilan balik ASan. Ini berarti bahwa pelanggaran memori tertangkap begitu terjadi, alih-alih menunggu kerusakan yang menyebabkan kerusakan. Ini sangat berguna dalam penemuan bug dan diagnosis akar penyebab.

Untuk memverifikasi bahwa ASAN berfungsi pada perangkat target, Android telah menyertakan eksekusi asan_test. Eksekusi asan_test menguji dan memvalidasi fungsionalitas ASAN pada perangkat target, memberikan pesan diagnostik dengan status setiap tes. Saat menggunakan build ASAN Android, build ini terletak di /data/nativetest/asan_test/asan_test atau /data/nativetest64/asan_test/asan_test secara default.

UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku tidak terdefinisi. Meskipun UBSan mampu mendeteksi banyak perilaku yang tidak ditentukan , Android mendukung alignment, bool, bounds, enum, float-cast-overflow, float-divide-by-zero, integer-divide-by-zero, nonnull-attribute, null, return, return-nonnull-attribute, shift-base, shift-exponent, signed-integer-overflow, unreachable, unsigned-integer-overflow, dan vla-bound. unsigned-integer-overflow, meskipun secara teknis bukan perilaku yang tidak ditentukan, disertakan dalam pembersih dan digunakan di banyak modul Android, termasuk komponen mediaserver, untuk menghilangkan kerentanan laten integer-overflow.

Penerapan

Dalam sistem build Android, Anda dapat mengaktifkan UBSan secara global atau lokal. Untuk mengaktifkan UBSan secara global, setel SANITIZE_TARGET di Android.mk. Untuk mengaktifkan UBSan pada tingkat per modul, setel LOCAL_SANITIZE dan tentukan perilaku tidak terdefinisi yang ingin Anda cari di Android.mk. Sebagai contoh:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0

LOCAL_SRC_FILES:= sanitizer-status.c

LOCAL_MODULE:= sanitizer-status

LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer

include $(BUILD_EXECUTABLE)

Sistem build Android belum mendukung diagnostik mendetail dalam file cetak biru seperti yang dilakukan pada file makefile. Berikut adalah padanan terdekat yang ditulis sebagai cetak biru (Android.bp):

cc_binary {

    cflags: [
        "-std=c11",
        "-Wall",
        "-Werror",
        "-O0",
    ],

    srcs: ["sanitizer-status.c"],

    name: "sanitizer-status",

    sanitize: {
        misc_undefined: [
            "alignment",
            "bounds",
            "null",
            "unreachable",
            "integer",
        ],
        diag: {
            undefined : true
        },
    },

}

Pintasan UBSan

Android juga memiliki dua pintasan, integer dan default-ub , untuk mengaktifkan satu set pembersih pada saat yang bersamaan. integer memungkinkan integer-divide-by-zero , signed-integer-overflow dan unsigned-integer-overflow . default-ub mengaktifkan pemeriksaan yang memiliki masalah kinerja compiler minimal: bool, integer-divide-by-zero, return, return-nonnull-attribute, shift-exponent, unreachable dan vla-bound. Kelas pembersih integer dapat digunakan dengan SANITIZE_TARGET dan LOCAL_SANITIZE, sedangkan default-ub hanya dapat digunakan dengan SANITIZE_TARGET.

Pelaporan kesalahan yang lebih baik

Implementasi UBSan default Android memanggil fungsi yang ditentukan saat ditemui perilaku yang tidak ditentukan. Secara default, fungsi ini dibatalkan. Namun, mulai bulan Oktober 2016, UBSan di Android memiliki pustaka waktu proses opsional yang memberikan pelaporan kesalahan yang lebih mendetail, termasuk jenis perilaku tidak terdefinisi yang dihadapi, file, dan informasi baris kode sumber. Untuk mengaktifkan pelaporan kesalahan ini dengan pemeriksaan bilangan bulat, tambahkan berikut ini ke file Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

Nilai LOCAL_SANITIZE memungkinkan pembersih selama proses pembuatan. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih yang ditentukan. Anda dapat menyetel LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai berbeda, tetapi hanya pemeriksaan di LOCAL_SANITIZE yang diaktifkan. Jika pemeriksaan tidak ditentukan di LOCAL_SANITIZE, tetapi ditentukan di LOCAL_SANITIZE_DIAG, pemeriksaan tersebut tidak diaktifkan dan pesan diagnostik tidak diberikan.

Berikut adalah contoh informasi yang disediakan oleh perpustakaan runtime UBSan:

pixel-xl:/ # sanitizer-status ubsan
sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')

Pembersih Alamat Kernel

Mirip dengan pembersih berbasis LLVM untuk komponen ruang pengguna, Android menyertakan Kernel Address Sanitizer (KASAN). KASAN adalah kombinasi dari kernel dan modifikasi waktu kompilasi yang menghasilkan sistem berinstrumen yang memungkinkan penemuan bug dan analisis akar penyebab yang lebih sederhana.

KASAN dapat mendeteksi banyak jenis pelanggaran memori di kernel. Ia juga dapat mendeteksi pembacaan dan penulisan di luar batas pada stack, heap, dan variabel global, serta dapat mendeteksi penggunaan-setelah-bebas dan kebebasan ganda.

Mirip dengan ASAN, KASAN menggunakan kombinasi instrumentasi fungsi memori pada waktu kompilasi dan memori bayangan untuk melacak akses memori pada waktu proses. Di KASAN, seperdelapan dari ruang memori kernel didedikasikan untuk memori bayangan, yang menentukan apakah akses memori itu valid atau tidak.

KASAN didukung pada arsitektur x86_64 dan arm64. Ini telah menjadi bagian dari kernel upstream sejak 4.0, dan telah di-backport ke kernel berbasis Android 3.18. KASAN telah diuji pada kernel Android yang dikompilasi dengan gcc berdasarkan 4.9.2.

Selain KASAN, kcov adalah modifikasi kernel lain yang berguna untuk pengujian. kcov dikembangkan untuk memungkinkan pengujian fuzz dengan panduan cakupan di kernel. Ini mengukur cakupan dalam hal input syscall dan berguna dengan sistem fuzzing , seperti syzkaller .

Penerapan

Untuk mengompilasi kernel dengan KASAN dan kcov diaktifkan, tambahkan flag build berikut ke konfigurasi build kernel Anda:

CONFIG_KASAN 
CONFIG_KASAN_INLINE 
CONFIG_TEST_KASAN 
CONFIG_KCOV 
CONFIG_SLUB 
CONFIG_SLUB_DEBUG 
CONFIG_CC_OPTIMIZE_FOR_SIZE

Dan menghapus berikut ini:

CONFIG_SLUB_DEBUG_ON 
CONFIG_SLUB_DEBUG_PANIC_ON 
CONFIG_KASAN_OUTLINE 
CONFIG_KERNEL_LZ4

Kemudian buat dan flash kernel Anda seperti biasa. Kernel KASAN jauh lebih besar dari aslinya. Jika memungkinkan, ubah parameter boot dan pengaturan bootloader untuk mempertimbangkan hal ini.

Setelah menginstal kernel, periksa log booting kernel untuk melihat apakah KASAN sudah aktif dan berjalan. Kernel akan memulai dengan informasi peta memori untuk KASAN, seperti:

...
[    0.000000] c0      0 Virtual kernel memory layout:
[    0.000000] c0      0     kasan   : 0xffffff8000000000 - 0xffffff9000000000   (    64 GB)
[    0.000000] c0      0     vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000   (   182 GB)
[    0.000000] c0      0     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000] c0      0               0xffffffbdc0000000 - 0xffffffbdc3f95400   (    63 MB actual)
[    0.000000] c0      0     PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)
[    0.000000] c0      0     fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)
[    0.000000] c0      0     modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
[    0.000000] c0      0     memory  : 0xffffffc000000000 - 0xffffffc0fe550000   (  4069 MB)
[    0.000000] c0      0       .init : 0xffffffc001d33000 - 0xffffffc001dce000   (   620 KB)
[    0.000000] c0      0       .text : 0xffffffc000080000 - 0xffffffc001d32284   ( 29385 KB)
...

Dan beginilah bug akan terlihat:

[   18.539668] c3      1 ==================================================================
[   18.547662] c3      1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[   18.554689] c3      1 Read of size 8 by task swapper/0/1
[   18.559988] c3      1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G        W      3.18.24-xxx #1
[   18.569275] c3      1 Hardware name: Android Device
[   18.577433] c3      1 Call trace:
[   18.580739] c3      1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
[   18.586985] c3      1 [<ffffffc00008b600>] show_stack+0x10/0x1c
[   18.592889] c3      1 [<ffffffc001481194>] dump_stack+0x74/0xc8
[   18.598792] c3      1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0
[   18.605038] c3      1 [<ffffffc00020286c>] __asan_load8+0x20/0x80
[   18.611115] c3      1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024
[   18.617976] c3      1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c
[   18.624832] c3      1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678
[   18.631082] c3      1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac
[   18.637676] c3      1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364
[   18.644625] c3      1 [<ffffffc001478e20>] kernel_init+0x10/0xd8
[   18.650613] c3      1 ==================================================================

Selain itu, jika modul diaktifkan di kernel Anda, Anda dapat memuat modul kernel test_kasan untuk pengujian lebih lanjut. Modul ini mencoba akses memori di luar batas dan bebas penggunaan setelahnya dan berguna dalam menguji KASAN pada perangkat target.