UndefinedBehaviorSanitizer (UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku yang tidak ditentukan. Meskipun UBSan mampu mendeteksi banyak bug perilaku yang tidak ditentukan, Android mendukung:
- perataan
- bool
- batas
- enum
- float-cast-overflow
- float-divide-by-zero
- integer-divide-by-zero
- 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 ditentukan, disertakan dalam pembersih 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 level per modul, tetapkan LOCAL_SANITIZE dan tentukan perilaku yang tidak ditentukan 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. bilangan bulat
mengaktifkan integer-divide-by-zero
,
signed-integer-overflow
, dan unsigned-integer-overflow
.
default-ub
mengaktifkan pemeriksaan yang memiliki masalah performa compiler
minimal: bool, integer-divide-by-zero, return,
returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
. Class
pembersih 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 yang ditentukan saat perilaku yang tidak ditentukan ditemukan. 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 yang tidak ditentukan yang ditemukan, informasi baris kode file dan 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 pembersih selama build. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih yang ditentukan. Anda dapat menetapkan LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai yang berbeda, tetapi hanya pemeriksaan tersebut 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 overflow 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 UndefinedBehaviorSanitizer (UBSan) Clang yang ditandatangani dan tidak ditandatangani 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 di sekitar operasi aritmetika / petunjuk—yang mungkin mengalami overflow—untuk membatalkan proses dengan aman jika overflow terjadi. Pembersih ini dapat memitigasi seluruh class kerentanan kerusakan memori dan pengungkapan informasi dengan akar masalah berupa overflow bilangan bulat, seperti kerentanan Stagefright asli.
Contoh dan sumber
Integer Overflow Sanitization (IntSan) disediakan oleh compiler dan menambahkan
instrumentasi ke dalam biner selama waktu kompilasi untuk mendeteksi overflow
aritmetika. Fitur ini diaktifkan secara default di berbagai komponen di seluruh
platform, misalnya
/platform/external/libnl/Android.bp
.
Implementasi
IntSan menggunakan sanitizer overflow bilangan bulat yang ditandatangani dan tidak ditandatangani UBSan. Mitigasi ini diaktifkan di tingkat per modul. Fitur ini membantu menjaga keamanan komponen penting Android dan tidak boleh dinonaktifkan.
Sebaiknya aktifkan Integer Overflow Sanitization untuk komponen tambahan. Kandidat ideal adalah kode native dengan hak istimewa atau kode native yang mengurai input pengguna yang tidak tepercaya. Ada overhead performa kecil yang terkait dengan pembersih yang bergantung pada penggunaan kode dan prevalensi operasi aritmetika. Harap perkirakan persentase overhead yang kecil dan uji apakah performa menjadi masalah.
Mendukung IntSan dalam 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_SANITIZE
menggunakan daftar pembersihan yang dipisahkan koma, denganinteger_overflow
sebagai kumpulan opsi yang dikemas sebelumnya untuk setiap pembersihan overflow bilangan bulat yang ditandatangani dan tidak ditandatangani dengan BLOCKLIST default.LOCAL_SANITIZE_DIAG
mengaktifkan mode diagnostik untuk pembersih. Gunakan mode diagnostik hanya selama pengujian karena hal ini tidak akan dibatalkan saat terjadi overflow, yang sepenuhnya meniadakan keunggulan keamanan mitigasi. Lihat Pemecahan masalah untuk mengetahui detail tambahan.LOCAL_SANITIZE_BLOCKLIST
memungkinkan 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 pembersih satu per satu menggunakan satu atau kedua tanda:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Mendukung IntSan dalam file blueprint
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 kumpulan opsi
prapaket untuk setiap pembersihan overflow bilangan bulat bertanda tangan dan tidak bertanda tangan
dengan BLOCKLIST
default.
Kumpulan properti diag
memungkinkan mode diagnostik untuk
penginsan. Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak
berhenti saat terjadi overflow, yang sepenuhnya meniadakan keunggulan keamanan
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
dibersihkan. Lihat Pemecahan masalah untuk
mengetahui detail tambahan.
Untuk mengaktifkan pembersih 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 jinak yang menyebabkan pembatalan. Anda harus menguji komponen dengan pembersihan yang diaktifkan untuk memastikan overflow yang tidak berbahaya dapat ditampilkan.
Untuk menemukan, pembatalan 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'
Pelacakan tumpukan harus menyertakan fungsi yang menyebabkan pembatalan, tetapi, overflow yang terjadi dalam fungsi inline mungkin tidak terlihat dalam pelacakan tumpukan.
Untuk menentukan akar masalah dengan lebih mudah, aktifkan diagnostik di library yang memicu pembatalan dan coba buat ulang error. Dengan mengaktifkan diagnostik, proses tidak akan dibatalkan dan akan terus berjalan. Tidak membatalkan membantu memaksimalkan jumlah overflow jinak di jalur eksekusi tertentu tanpa harus mengompilasi ulang setelah memperbaiki setiap bug. Diagnostik menghasilkan pesan error yang menyertakan nomor baris dan file sumber yang menyebabkan pembatalan:
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 aritmetika yang bermasalah ditemukan, pastikan bahwa overflow tidak berbahaya dan disengaja (misalnya, tidak memiliki implikasi keamanan). Anda dapat mengatasi pemberhentian pembersih dengan:
- Memfaktorkan ulang kode untuk menghindari overflow (contoh)
- Overflow secara eksplisit melalui fungsi __builtin_*_overflow Clang (contoh)
- Menonaktifkan pembersihan 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 aritmetika dan satu operasi yang meluap harus memfaktorkan ulang satu operasi, bukan memblokir seluruh fungsi.
Pola umum yang dapat menyebabkan overflow jinak meliputi:
- Pemetaan implisit saat overflow tanpa tanda terjadi sebelum ditransmisikan ke jenis bertanda (contoh)
- Penghapusan linked list yang mengurangi indeks loop saat penghapusan (contoh)
- Menetapkan jenis tanpa tanda tangan ke -1, bukan menentukan nilai maksimum sebenarnya (contoh)
- Loop yang mengurangi bilangan bulat tanpa tanda tangan dalam kondisi (contoh, contoh)
Sebaiknya developer memastikan bahwa kasus saat pembersih mendeteksi overflow memang tidak berbahaya tanpa efek samping atau implikasi keamanan yang tidak diinginkan sebelum menonaktifkan pembersihan.
Menonaktifkan IntSan
Anda dapat menonaktifkan IntSan dengan BLOCKLIST atau atribut fungsi. Nonaktifkan seperlunya 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 cara menonaktifkan IntSan dengan atribut fungsi dan pemformatan file BLOCKLIST. BLOCKLISTing harus dicakup untuk pembersih tertentu dengan menggunakan nama bagian yang menentukan pembersih target agar tidak memengaruhi pembersih lainnya.
Validasi
Saat ini, tidak ada pengujian CTS khusus untuk Sanitasi Integer Overflow. Sebagai gantinya, pastikan pengujian CTS lulus dengan atau tanpa mengaktifkan IntSan untuk memverifikasi bahwa pengujian tersebut 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 saat 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 sanitasi batas UBSan. Mitigasi ini diaktifkan di tingkat per modul. Fitur ini membantu menjaga komponen penting Android tetap aman dan tidak boleh dinonaktifkan.
Sebaiknya Anda mengaktifkan BoundSan untuk komponen tambahan. Kandidat ideal adalah kode native dengan hak istimewa atau kode native kompleks yang mengurai input pengguna yang tidak tepercaya. Overhead performa yang terkait dengan pengaktifan BoundSan bergantung pada jumlah akses array yang tidak dapat dibuktikan aman. Rata-rata, Anda akan mendapatkan persentase overhead yang kecil dan menguji 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 pembersih.
Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak dibatalkan saat
overflow, yang meniadakan keunggulan keamanan mitigasi dan membawa
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 berkontribusi secara substansial. Audit file/fungsi ini secara manual
untuk memastikan akses array aman. Lihat Pemecahan masalah untuk mengetahui detail
tambahan.
Mengaktifkan BoundSan dalam 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 dibatalkan saat terjadi overflow, yang
akan menghilangkan 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 berkontribusi secara substansial. 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 hanya nonaktifkan jika fungsi atau file menghasilkan overhead performa dalam jumlah besar dan sumber telah ditinjau secara manual.
Untuk Informasi selengkapnya tentang cara menonaktifkan BoundSan dengan atribut fungsi dan pemformatan file BLOCKLIST, lihat dokumentasi Clang LLVM. Cakupkan BLOCKLIST ke pembersih tertentu dengan menggunakan nama bagian yang menentukan pembersih target agar tidak memengaruhi pembersih lainnya.
Validasi
Tidak ada pengujian CTS khusus untuk BoundSan. Sebagai gantinya, pastikan pengujian CTS lulus dengan atau tanpa mengaktifkan BoundSan untuk memverifikasi bahwa pengujian tersebut 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 menyertakan 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 akan dicetak ke logcat
. Secara default, mode ini tidak
menampilkan pesan pembatalan. Tinjau logcat
untuk memeriksa error.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'