UndefinedBehaviorSanitizer (UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku tidak terdefinisi. Meskipun UBSan mampu mendeteksi banyak bug perilaku tidak terdefinisi, Android mendukung:
- perataan
- bool
- batas
- enum
- float-cast-overflow
- float-divide-by-zero
- pembagian bilangan bulat dengan nol
- nonnull-attribute
- null
- return
- returns-nonnull-attribute
- shift-base
- shift-exponent
- signed-integer-overflow
- tidak dapat dijangkau
- unsigned-integer-overflow
- vla-bound
unsigned-integer-overflow, meskipun secara teknis bukan perilaku yang tidak terdefinisi, disertakan dalam sanitizer dan digunakan di banyak modul Android, termasuk komponen mediaserver, untuk menghilangkan kerentanan integer-overflow laten.
Implementasi
Di sistem build Android, Anda dapat mengaktifkan UBSan secara global atau lokal. Untuk mengaktifkan UBSan secara global, tetapkan SANITIZE_TARGET di Android.mk. Untuk mengaktifkan UBSan di tingkat per modul, tetapkan LOCAL_SANITIZE dan tentukan perilaku tidak terdefinisi yang ingin Anda cari di Android.mk. 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)
Dan konfigurasi blueprint (Android.bp) yang setara:
cc_binary {
cflags: [
"-std=c11",
"-Wall",
"-Werror",
"-O0",
],
srcs: ["sanitizer-status.c"],
name: "sanitizer-status",
sanitize: {
misc_undefined: [
"alignment",
"bounds",
"null",
"unreachable",
"integer",
],
diag: {
misc_undefined: [
"alignment",
"bounds",
"null",
"unreachable",
"integer",
],
},
},
}
Pintasan UBSan
Android juga memiliki dua pintasan, integer dan
default-ub, untuk mengaktifkan serangkaian pembersih secara bersamaan. Integer
mengaktifkan integer-divide-by-zero,
signed-integer-overflow, dan unsigned-integer-overflow.
default-ub mengaktifkan pemeriksaan yang memiliki masalah performa
pengompilasi minimal: bool, integer-divide-by-zero, return,
returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. Class sanitizer bilangan bulat dapat digunakan dengan SANITIZE_TARGET dan LOCAL_SANITIZE, sedangkan default-ub hanya dapat digunakan dengan SANITIZE_TARGET.
Pelaporan error yang lebih baik
Implementasi UBSan default Android memanggil fungsi tertentu saat perilaku tidak terdefinisi terjadi. Secara default, fungsi ini adalah abort. Namun, mulai Oktober 2016, UBSan di Android memiliki library runtime opsional yang memberikan pelaporan error yang lebih mendetail, termasuk jenis perilaku tidak terdefinisi yang terjadi, informasi file, dan baris kode sumber. Untuk mengaktifkan pelaporan error ini dengan pemeriksaan bilangan bulat, tambahkan kode berikut ke file Android.mk:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
Nilai LOCAL_SANITIZE mengaktifkan sanitizer selama build. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk sanitizer yang ditentukan. Anda dapat menetapkan LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai yang berbeda, tetapi hanya pemeriksaan di LOCAL_SANITIZE yang diaktifkan. Jika pemeriksaan tidak ditentukan di LOCAL_SANITIZE, tetapi ditentukan di LOCAL_SANITIZE_DIAG, pemeriksaan tidak diaktifkan dan pesan diagnostik tidak diberikan.
Berikut adalah contoh informasi yang diberikan oleh library 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')
Pembersihan luapan bilangan bulat
Overflow bilangan bulat yang tidak disengaja dapat menyebabkan kerusakan memori atau kerentanan pengungkapan informasi dalam variabel yang terkait dengan akses memori atau alokasi memori. Untuk mengatasi hal ini, kami menambahkan sanitizer overflow bilangan bulat bertanda dan tidak bertanda UndefinedBehaviorSanitizer (UBSan) Clang untuk memperkuat framework media di Android 7.0. Di Android 9, kami memperluas UBSan untuk mencakup lebih banyak komponen dan meningkatkan dukungan sistem build untuknya.
Hal ini dirancang untuk menambahkan pemeriksaan seputar operasi/instruksi aritmatika—yang mungkin meluap—untuk menghentikan proses dengan aman jika terjadi luapan. Sanitizer ini dapat memitigasi seluruh class kerentanan pengungkapan informasi dan kerusakan memori yang penyebab utamanya adalah overflow bilangan bulat, seperti kerentanan Stagefright asli.
Contoh dan sumber
Sanitasi Overflow Integer (IntSan) disediakan oleh compiler dan menambahkan
instrumentasi ke dalam biner selama waktu kompilasi untuk mendeteksi overflow
aritmatika. Fitur ini diaktifkan secara default di berbagai komponen di seluruh
platform, misalnya
/platform/external/libnl/Android.bp.
Implementasi
IntSan menggunakan sanitizer overflow bilangan bulat bertanda dan tidak bertanda UBSan. Mitigasi ini diaktifkan di tingkat per modul. Fitur ini membantu menjaga keamanan komponen penting Android dan tidak boleh dinonaktifkan.
Sebaiknya Anda mengaktifkan Sanitasi Overflow Integer untuk komponen tambahan. Target yang ideal adalah kode native yang memiliki hak istimewa atau kode native yang mem-parsing input pengguna yang tidak tepercaya. Ada sedikit overhead performa yang terkait dengan sanitizer yang bergantung pada penggunaan kode dan prevalensi operasi aritmatika. Perkirakan persentase overhead kecil dan uji jika performa menjadi masalah.
Mendukung IntSan di makefile
Untuk mengaktifkan IntSan dalam makefile, tambahkan:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZEmenggunakan daftar sanitizer yang dipisahkan koma, denganinteger_overflowadalah serangkaian opsi yang telah dikemas sebelumnya untuk sanitizer overflow bilangan bulat bertanda dan tidak bertanda dengan default BLOCKLIST.LOCAL_SANITIZE_DIAGmengaktifkan mode diagnostik untuk sanitizer. Gunakan mode diagnostik hanya selama pengujian karena mode ini tidak akan membatalkan operasi saat terjadi overflow, sehingga sepenuhnya meniadakan keuntungan keamanan dari mitigasi. Lihat Pemecahan masalah untuk mengetahui detail tambahan.LOCAL_SANITIZE_BLOCKLISTmemungkinkan Anda menentukan file BLOCKLIST untuk mencegah fungsi dan file sumber dibersihkan. Lihat Pemecahan masalah untuk mengetahui detail tambahan.
Jika Anda menginginkan kontrol yang lebih terperinci, aktifkan setiap sanitizer menggunakan satu atau kedua tanda berikut:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Mendukung IntSan dalam file cetak biru
Untuk mengaktifkan pembersihan overflow bilangan bulat dalam file blueprint, seperti
/platform/external/libnl/Android.bp,
tambahkan:
sanitize: {
integer_overflow: true,
diag: {
integer_overflow: true,
},
BLOCKLIST: "modulename_BLOCKLIST.txt",
},
Seperti file make, properti integer_overflow adalah serangkaian opsi yang telah dikemas sebelumnya untuk setiap sanitizer overflow bilangan bulat bertanda dan tidak bertanda dengan default
BLOCKLIST.
Kumpulan properti diag mengaktifkan mode diagnostik untuk
sanitizer. Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak
membatalkan saat terjadi overflow, yang sepenuhnya meniadakan keuntungan keamanan dari
mitigasi dalam build pengguna. Lihat Pemecahan masalah untuk mengetahui detail tambahan.
Properti BLOCKLIST memungkinkan spesifikasi file BLOCKLIST
yang memungkinkan developer mencegah fungsi dan file sumber di-sanitize. Lihat Pemecahan masalah untuk mengetahui detail tambahan.
Untuk mengaktifkan sanitizer satu per satu, gunakan:
sanitize: {
misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
diag: {
misc_undefined: ["signed-integer-overflow",
"unsigned-integer-overflow",],
},
BLOCKLIST: "modulename_BLOCKLIST.txt",
},Pemecahan masalah
Jika Anda mengaktifkan pembersihan overflow bilangan bulat di komponen baru, atau mengandalkan library platform yang telah memiliki pembersihan overflow bilangan bulat, Anda mungkin mengalami beberapa masalah dengan overflow bilangan bulat yang tidak berbahaya yang menyebabkan pembatalan. Anda harus menguji komponen dengan sanitasi yang diaktifkan untuk memastikan overflow yang tidak berbahaya dapat ditampilkan.
Untuk menemukan penghentian yang disebabkan oleh pembersihan dalam build pengguna, telusuri error
SIGABRT dengan pesan Abort yang menunjukkan overflow yang tertangkap
oleh UBSan, seperti:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
Stack trace harus menyertakan fungsi yang menyebabkan pembatalan, tetapi overflow yang terjadi dalam fungsi inline mungkin tidak terlihat dalam stack trace.
Untuk menentukan akar masalah dengan lebih mudah, aktifkan diagnostik di library yang memicu pembatalan dan coba reproduksi error. Dengan diagnostik diaktifkan, proses tidak akan dibatalkan dan akan terus berjalan. Tidak membatalkan akan membantu memaksimalkan jumlah overflow yang tidak berbahaya dalam jalur eksekusi tertentu tanpa harus mengompilasi ulang setelah memperbaiki setiap bug. Diagnostik menghasilkan pesan error yang mencakup nomor baris dan file sumber yang menyebabkan penghentian:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Setelah operasi aritmatika yang bermasalah ditemukan, pastikan bahwa overflow tidak berbahaya dan dimaksudkan (misalnya, tidak memiliki implikasi keamanan). Anda dapat mengatasi pembatalan sanitizer dengan:
- Memfaktorkan ulang kode untuk menghindari overflow (contoh)
- Overflow secara eksplisit melalui fungsi __builtin_*_overflow Clang (contoh)
- Menonaktifkan sanitasi dalam fungsi dengan menentukan atribut
no_sanitize(contoh) - Menonaktifkan pembersihan fungsi atau file sumber melalui file BLOCKLIST (contoh)
Anda harus menggunakan solusi yang paling terperinci. Misalnya, fungsi besar dengan banyak operasi aritmatika dan satu operasi yang meluap harus difaktorkan ulang satu operasinya, bukan seluruh fungsi yang masuk dalam DAFTAR BLOKIR.
Pola umum yang dapat menyebabkan overflow tidak berbahaya meliputi:
- Transmisi implisit saat terjadi overflow yang tidak bertanda sebelum ditransmisikan ke jenis bertanda (contoh)
- Penghapusan daftar tertaut yang mengurangi indeks loop saat penghapusan (contoh)
- Menetapkan jenis yang tidak bertanda ke -1, bukan menentukan nilai maks sebenarnya (contoh)
- Loop yang mengurangi bilangan bulat tidak bertanda dalam kondisi (contoh, contoh)
Sebaiknya developer memastikan bahwa jika sanitizer mendeteksi overflow, overflow tersebut memang tidak berbahaya tanpa efek samping atau implikasi keamanan yang tidak diinginkan sebelum menonaktifkan sanitasi.
Menonaktifkan IntSan
Anda dapat menonaktifkan IntSan dengan BLOCKLIST atau atribut fungsi. Nonaktifkan dengan hemat dan hanya jika pemfaktoran ulang kode tidak masuk akal atau jika ada overhead performa yang bermasalah.
Lihat dokumentasi Clang upstream untuk mengetahui informasi selengkapnya tentang menonaktifkan IntSan dengan atribut fungsi dan pemformatan file BLOCKLIST. BLOCKLISTing harus dicakup ke sanitizer tertentu dengan menggunakan nama bagian yang menentukan target sanitizer agar tidak memengaruhi sanitizer lain.
Validasi
Saat ini, tidak ada pengujian CTS khusus untuk Sanitasi Overflow Integer. Sebagai gantinya, pastikan pengujian CTS lulus dengan atau tanpa IntSan diaktifkan untuk memverifikasi bahwa IntSan tidak memengaruhi perangkat.
Sanitasi batas
BoundsSanitizer (BoundSan) menambahkan instrumentasi ke biner untuk menyisipkan pemeriksaan batas di sekitar akses array. Pemeriksaan ini ditambahkan jika compiler tidak dapat membuktikan pada waktu kompilasi bahwa akses akan aman dan jika ukuran array akan diketahui pada waktu runtime, sehingga dapat diperiksa. Android 10 men-deploy BoundSan di Bluetooth dan codec. BoundSan disediakan oleh compiler dan diaktifkan secara default di berbagai komponen di seluruh platform.
Implementasi
BoundSan menggunakan sanitizer batas UBSan. Mitigasi ini diaktifkan di tingkat per modul. Fitur ini membantu menjaga keamanan komponen penting Android dan tidak boleh dinonaktifkan.
Sebaiknya Anda mengaktifkan BoundSan untuk komponen tambahan. Kandidat yang ideal adalah kode native istimewa atau kode native kompleks yang mem-parsing input pengguna yang tidak tepercaya. Overhead performa yang terkait dengan mengaktifkan BoundSan bergantung pada jumlah akses array yang tidak dapat terbukti aman. Anda akan mendapatkan persentase overhead kecil secara rata-rata dan uji apakah performa menjadi masalah.
Mengaktifkan BoundSan dalam file blueprint
BoundSan dapat diaktifkan dalam file blueprint dengan menambahkan "bounds"
ke properti pembersihan misc_undefined untuk modul biner dan library:
sanitize: {
misc_undefined: ["bounds"],
diag: {
misc_undefined: ["bounds"],
},
BLOCKLIST: "modulename_BLOCKLIST.txt",diag
Properti diag mengaktifkan mode diagnostik untuk sanitizer.
Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak membatalkan saat terjadi
overflow, yang meniadakan keuntungan keamanan dari mitigasi dan menimbulkan
overhead performa yang lebih tinggi, sehingga tidak direkomendasikan untuk build produksi.
DAFTAR YANG TIDAK DISETUJUI
Properti BLOCKLIST memungkinkan spesifikasi file BLOCKLIST
yang dapat digunakan developer untuk mencegah fungsi dan file sumber dibersihkan. Gunakan properti ini hanya jika performa menjadi masalah dan file/fungsi yang ditargetkan memberikan kontribusi yang besar. Audit file/fungsi ini secara manual
untuk memastikan akses array aman. Lihat Pemecahan masalah untuk mengetahui detail tambahan.
Mengaktifkan BoundSan di makefile
BoundSan dapat diaktifkan dalam makefile dengan menambahkan "bounds"
ke variabel LOCAL_SANITIZE untuk modul biner dan library:
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE menerima daftar pembersih yang dipisahkan dengan
koma.
LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik. Gunakan mode
diagnostik hanya selama pengujian. Mode diagnostik tidak membatalkan saat terjadi overflow, yang
meniadakan keunggulan keamanan mitigasi dan menimbulkan overhead
performa yang lebih tinggi, sehingga tidak direkomendasikan untuk build produksi.
LOCAL_SANITIZE_BLOCKLIST memungkinkan spesifikasi file BLOCKLIST
yang memungkinkan developer mencegah fungsi dan file sumber dibersihkan. Gunakan properti ini hanya jika performa menjadi masalah dan file/fungsi yang ditargetkan memberikan kontribusi yang besar. Audit file/fungsi ini secara manual
untuk memastikan akses array aman. Lihat Pemecahan masalah untuk mengetahui detail tambahan.
Menonaktifkan BoundSan
Anda dapat menonaktifkan BoundSan dalam fungsi dan file sumber dengan BLOCKLIST atau atribut fungsi. Sebaiknya tetap aktifkan BoundSan, jadi nonaktifkan hanya jika fungsi atau file menyebabkan overhead performa yang besar dan sumber telah ditinjau secara manual.
Untuk mengetahui informasi selengkapnya tentang cara menonaktifkan BoundSan dengan atribut fungsi dan pemformatan file BLOCKLIST, lihat dokumentasi Clang LLVM. Cakupan BLOCKLIST ke sanitizer tertentu dengan menggunakan nama bagian yang menentukan target sanitizer untuk menghindari dampak pada sanitizer lain.
Validasi
Tidak ada pengujian CTS khusus untuk BoundSan. Sebagai gantinya, pastikan pengujian CTS lulus dengan atau tanpa BoundSan diaktifkan untuk memverifikasi bahwa BoundSan tidak memengaruhi perangkat.
Pemecahan masalah
Uji komponen secara menyeluruh setelah mengaktifkan BoundSan untuk memastikan bahwa akses di luar batas yang sebelumnya tidak terdeteksi telah ditangani.
Error BoundSan dapat diidentifikasi dengan mudah karena mencakup pesan pembatalan tombstone berikut:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
Saat berjalan dalam mode diagnostik, file sumber, nomor baris, dan nilai
indeks dicetak ke logcat. Secara default, mode ini tidak
memunculkan pesan pembatalan. Tinjau logcat untuk memeriksa
error.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'