Pembersih LLVM

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

Ini adalah praktik terbaik untuk build Android untuk boot dan dijalankan dengan pembersih yang diaktifkan, seperti AddressSanitizer dan UndefinedBehaviorSanitizer. Halaman ini memperkenalkan AddressSanitizer, UndefinedBehaviorSanitizer, dan KernelAddressSanitizer, menunjukkan bagaimana mereka dapat digunakan dalam sistem pembangunan Android, dan memberikan contoh file Android.mk dan Android.bp yang membuat komponen asli dengan pembersih ini diaktifkan.

Pembersih Alamat

AddressSanitizer (ASan) adalah kemampuan instrumentasi berbasis compiler 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 di level build penuh 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 panggilan balik ASan saat dibaca atau ditulis.

Instrumentasi memungkinkan ASan mendeteksi bug penggunaan memori yang tidak valid, termasuk double-free, dan use-after scope, return, dan free, sedangkan padding wilayah memori mendeteksi pembacaan atau penulisan di luar batas. Jika membaca atau menulis ke wilayah padding ini terjadi, ASan 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 dapat tampak tidak deterministik, terutama untuk bug yang memerlukan pengaturan 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 menginstrumentasikan semua fungsi terkait memori dan data pad dengan area yang tidak dapat diakses tanpa memicu panggilan balik ASan. Ini berarti bahwa pelanggaran memori ditangkap 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 asan_test yang dapat dieksekusi. Eksekusi asan_test menguji dan memvalidasi fungsionalitas ASAN pada perangkat target, memberikan pesan diagnostik dengan status setiap pengujian. Saat menggunakan ASAN Android build, terletak di /data/nativetest/asan_test/asan_test atau /data/nativetest64/asan_test/asan_test secara default.

Pembersih Perilaku Tidak Terdefinisi

UndefinedBehaviorSanitizer (UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku tidak terdefinisi. Sementara UBSan mampu mendeteksi banyak perilaku yang tidak terdefinisi , Android mendukung penyelarasan, bool, batas, 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 server media, untuk menghilangkan kerentanan laten integer-overflow.

Penerapan

Di 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 halnya 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 secara bersamaan. integer memungkinkan integer-divide-by-zero , signed-integer-overflow dan unsigned-integer-overflow . default-ub mengaktifkan pemeriksaan yang memiliki masalah kinerja kompiler minimal: bool, integer-divide-by-zero, return, return-nonnull-attribute, shift-exponent, unreachable, dan vla-bound. Kelas integer sanitizer 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 tertentu saat ditemukan perilaku yang tidak ditentukan. Secara default, fungsi ini dibatalkan. Namun, mulai Oktober 2016, UBSan di Android memiliki pustaka waktu proses opsional yang memberikan pelaporan kesalahan yang lebih mendetail, termasuk jenis perilaku tidak terdefinisi yang ditemui, 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 mengaktifkan pembersih selama pembuatan. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih yang ditentukan. Dimungkinkan untuk menyetel LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai yang berbeda, tetapi hanya pemeriksaan di LOCAL_SANITIZE yang diaktifkan. Jika pemeriksaan tidak ditentukan dalam LOCAL_SANITIZE, tetapi ditentukan dalam LOCAL_SANITIZE_DIAG, pemeriksaan 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 Pembersih Alamat Kernel (KASAN). KASAN adalah kombinasi modifikasi kernel dan waktu kompilasi yang menghasilkan sistem terinstrumentasi yang memungkinkan penemuan bug dan analisis akar penyebab yang lebih sederhana.

KASAN dapat mendeteksi banyak jenis pelanggaran memori di kernel. Itu juga dapat mendeteksi pembacaan dan penulisan di luar batas pada tumpukan, tumpukan, dan variabel global, dan dapat mendeteksi penggunaan setelah bebas dan bebas ganda.

Mirip dengan ASAN, KASAN menggunakan kombinasi instrumentasi fungsi memori pada waktu kompilasi dan memori bayangan untuk melacak akses memori saat runtime. Di KASAN, seperdelapan dari ruang memori kernel didedikasikan untuk memori bayangan, yang menentukan apakah akses memori 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 yang dipandu 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 yang berikut ini:

CONFIG_SLUB_DEBUG_ON 
CONFIG_SLUB_DEBUG_PANIC_ON 
CONFIG_KASAN_OUTLINE 
CONFIG_KERNEL_LZ4

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

Setelah mem-flash kernel, periksa log boot kernel untuk melihat apakah KASAN diaktifkan 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 tampilan bug:

[   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 mencoba akses memori di luar batas dan penggunaan setelah bebas dan berguna dalam menguji KASAN pada perangkat target.