Pembersih Perilaku Tidak Terdefinisi

UndefinisiBehaviorSanitizer (UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku tidak terdefinisi. Meskipun UBSan mampu mendeteksi banyak bug perilaku tidak terdefinisi , Android mendukung:

  • penyelarasan
  • bodoh
  • batas
  • enum
  • float-cast-overflow
  • float-bagi-dengan-nol
  • bilangan bulat-bagi-dengan-nol
  • atribut nonnull
  • batal
  • kembali
  • mengembalikan-atribut nonnull
  • basis shift
  • shift-eksponen
  • ditandatangani-integer-overflow
  • tidak dapat dijangkau
  • unsigned-integer-overflow
  • terikat vla

unsigned-integer-overflow, meskipun secara teknis bukan perilaku yang tidak terdefinisi, disertakan dalam sanitizer 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 level per modul, setel LOCAL_SANITIZE dan tentukan perilaku tidak terdefinisi yang ingin Anda cari di Android.mk. Misalnya:

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 cetak biru yang setara (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: {
            misc_undefined: [
                "alignment",
                "bounds",
                "null",
                "unreachable",
                "integer",
            ],
        },
    },

}

Jalan pintas 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 kinerja kompiler minimal: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and 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 ketika ditemukan perilaku yang tidak terdefinisi. Secara default, fungsi ini dibatalkan. Namun, mulai bulan Oktober 2016, UBSan di Android memiliki pustaka runtime opsional yang memberikan pelaporan kesalahan lebih detail, termasuk jenis perilaku tidak terdefinisi yang ditemui, informasi file dan baris kode sumber. Untuk mengaktifkan pelaporan kesalahan 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 pembuatan. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih yang ditentukan. Dimungkinkan untuk menyetel LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai yang berbeda, namun hanya pemeriksaan di LOCAL_SANITIZE yang diaktifkan. Jika pemeriksaan tidak ditentukan dalam LOCAL_SANITIZE, namun ditentukan dalam 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')

Sanitasi Luapan Integer

Kelebihan 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 UndefinisiBehaviorSanitizer (UBSan) Clang yang ditandatangani dan tidak ditandatangani integer overflow sanitizer untuk memperkuat kerangka media di Android 7.0. Di Android 9, kami memperluas UBSan untuk mencakup lebih banyak komponen dan meningkatkan dukungan sistem build untuknya.

Ini dirancang untuk menambahkan pemeriksaan di sekitar operasi/instruksi aritmatika—yang mungkin meluap—untuk membatalkan proses dengan aman jika terjadi luapan. Sanitizer ini dapat memitigasi seluruh kelas kerusakan memori dan kerentanan pengungkapan informasi yang akar masalahnya adalah integer overflow, seperti kerentanan Stagefright yang asli.

Contoh dan sumber

Sanitasi Luapan Integer (IntSan) disediakan oleh kompiler dan menambahkan instrumentasi ke dalam biner selama waktu kompilasi untuk mendeteksi luapan aritmatika. Ini diaktifkan secara default di berbagai komponen di seluruh platform, misalnya /platform/external/libnl/Android.bp .

Penerapan

IntSan menggunakan pembersih integer overflow yang ditandatangani dan tidak ditandatangani UBSan. Mitigasi ini diaktifkan pada tingkat per modul. Ini membantu menjaga komponen penting Android tetap aman dan tidak boleh dinonaktifkan.

Kami sangat menganjurkan Anda untuk mengaktifkan Integer Overflow Sanitization untuk komponen tambahan. Kandidat yang ideal adalah kode asli yang memiliki hak istimewa atau kode asli yang mem-parsing masukan pengguna yang tidak tepercaya. Ada sedikit overhead kinerja yang terkait dengan pembersih yang bergantung pada penggunaan kode dan prevalensi operasi aritmatika. Harapkan persentase overhead yang kecil dan uji apakah kinerja menjadi perhatian.

Mendukung IntSan di makefiles

Untuk mengaktifkan IntSan di makefile, tambahkan:

LOCAL_SANITIZE := integer_overflow
    # Optional features
    LOCAL_SANITIZE_DIAG := integer_overflow
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
  • LOCAL_SANITIZE mengambil daftar pembersih yang dipisahkan koma, dengan integer_overflow menjadi kumpulan opsi yang sudah dikemas sebelumnya untuk pembersih integer overflow individual yang ditandatangani dan tidak ditandatangani dengan BLOCKLIST default .
  • LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih. Gunakan mode diagnostik hanya selama pengujian karena ini tidak akan membatalkan luapan, sehingga sepenuhnya meniadakan keuntungan keamanan mitigasi. Lihat Pemecahan Masalah untuk detail tambahan.
  • LOCAL_SANITIZE_BLOCKLIST memungkinkan Anda menentukan file BLOCKLIST untuk mencegah fungsi dan file sumber dibersihkan. Lihat Pemecahan Masalah untuk detail tambahan.

Jika Anda menginginkan kontrol yang lebih terperinci, aktifkan pembersih satu per satu menggunakan salah 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 cetak biru

Untuk mengaktifkan sanitasi overflow integer dalam file cetak biru, seperti /platform/external/libnl/Android.bp , tambahkan:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Seperti halnya file make, properti integer_overflow adalah serangkaian opsi yang sudah dikemas sebelumnya untuk pembersih integer overflow individual yang ditandatangani dan tidak ditandatangani dengan BLOCKLIST default .

Kumpulan properti diag mengaktifkan mode diagnostik untuk pembersih. Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak membatalkan overflow, yang sepenuhnya meniadakan keuntungan keamanan mitigasi dalam build pengguna. Lihat Pemecahan Masalah untuk detail tambahan.

Properti BLOCKLIST memungkinkan spesifikasi file BLOCKLIST yang memungkinkan pengembang mencegah fungsi dan file sumber dibersihkan. Lihat Pemecahan Masalah untuk 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",
       },

Penyelesaian masalah

Jika Anda mengaktifkan sanitasi luapan bilangan bulat di komponen baru, atau mengandalkan pustaka platform yang telah memiliki sanitasi luapan bilangan bulat, Anda mungkin mengalami beberapa masalah dengan luapan bilangan bulat jinak yang menyebabkan pembatalan. Anda harus menguji komponen dengan sanitasi yang diaktifkan untuk memastikan luapan yang tidak berbahaya dapat muncul ke permukaan.

Untuk menemukan pembatalan yang disebabkan oleh sanitasi pada bangunan pengguna, telusuri kerusakan SIGABRT dengan pesan Batalkan yang menunjukkan luapan yang ditangkap 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, namun luapan yang terjadi pada fungsi sebaris mungkin tidak terlihat dalam pelacakan tumpukan.

Untuk lebih mudah menentukan akar permasalahan, aktifkan diagnostik di pustaka yang memicu pembatalan dan coba buat ulang kesalahan tersebut. Jika diagnostik diaktifkan, proses tidak akan dibatalkan dan malah akan terus berjalan. Tidak membatalkan membantu memaksimalkan jumlah luapan jinak di jalur eksekusi tertentu tanpa harus mengkompilasi ulang setelah memperbaiki setiap bug. Diagnostik menghasilkan pesan kesalahan yang mencakup 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 aritmatika yang bermasalah ditemukan, pastikan bahwa overflow tidak berbahaya dan memang disengaja (misalnya tidak memiliki implikasi keamanan). Anda dapat mengatasi pembatalan pembersih dengan:

  • Memfaktorkan ulang kode untuk menghindari overflow ( contoh )
  • Meluap secara eksplisit melalui fungsi __builtin_*_overflow Clang ( contoh )
  • Menonaktifkan sanitasi dalam fungsi dengan menentukan atribut no_sanitize ( contoh )
  • Menonaktifkan sanitasi fungsi atau file sumber melalui file BLOCKLIST ( contoh )

Anda harus menggunakan solusi sedetail mungkin. Misalnya, fungsi besar dengan banyak operasi aritmatika dan satu operasi overflow harus memiliki operasi tunggal yang difaktorkan ulang, bukan seluruh fungsi yang diBLOCKLIST.

Pola umum yang dapat menyebabkan luapan yang tidak berbahaya meliputi:

  • Pemeran implisit di mana luapan yang tidak ditandatangani terjadi sebelum dilemparkan ke tipe yang ditandatangani ( contoh )
  • Penghapusan daftar tertaut yang mengurangi indeks loop pada penghapusan ( contoh )
  • Menetapkan tipe unsigned ke -1 alih-alih menentukan nilai maksimal sebenarnya ( contoh )
  • Loop yang mengurangi bilangan bulat tak bertanda tangan dalam kondisi ( contoh , contoh )

Disarankan agar pengembang memastikan bahwa kasus di mana pembersih mendeteksi luapan memang tidak berbahaya tanpa efek samping atau implikasi keamanan yang tidak diinginkan sebelum menonaktifkan sanitasi.

Menonaktifkan IntSan

Anda dapat menonaktifkan IntSan dengan BLOCKLIS atau atribut fungsi. Nonaktifkan secara hemat dan hanya jika pemfaktoran ulang kode tidak masuk akal atau jika ada masalah kinerja yang berlebihan.

Lihat dokumentasi Clang upstream untuk informasi lebih lanjut tentang menonaktifkan IntSan dengan atribut fungsi dan format file BLOCKLIST . DAFTAR BLOKLIS harus dibatasi pada pembersih tertentu dengan menggunakan nama bagian yang menentukan target pembersih untuk menghindari dampak pada pembersih lainnya.

Validasi

Saat ini, belum ada tes CTS yang khusus untuk Integer Overflow Sanitization. Sebaliknya, pastikan pengujian CTS lulus dengan atau tanpa mengaktifkan IntSan untuk memverifikasi bahwa pengujian tersebut tidak berdampak pada perangkat.

Sanitasi Batas

BoundsSanitizer (BoundSan) menambahkan instrumentasi ke biner untuk menyisipkan pemeriksaan batas di sekitar akses array. Pemeriksaan ini ditambahkan jika kompiler tidak dapat membuktikan pada waktu kompilasi bahwa akses akan aman dan jika ukuran array akan diketahui pada waktu proses, sehingga dapat diperiksa. Android 10 menerapkan BoundSan dalam Bluetooth dan codec. BoundSan disediakan oleh kompiler dan diaktifkan secara default di berbagai komponen di seluruh platform.

Penerapan

BoundSan menggunakan pembersih batas UBSan . Mitigasi ini diaktifkan pada tingkat per modul. Ini membantu menjaga komponen penting Android tetap aman dan tidak boleh dinonaktifkan.

Kami sangat menganjurkan Anda untuk mengaktifkan BoundSan untuk komponen tambahan. Kandidat yang ideal adalah kode asli yang memiliki hak istimewa atau kode asli kompleks yang memilah masukan pengguna yang tidak tepercaya. Overhead kinerja yang terkait dengan pengaktifan BoundSan bergantung pada jumlah akses array yang tidak dapat dibuktikan aman. Harapkan rata-rata persentase overhead yang kecil dan uji apakah kinerja menjadi perhatian.

Mengaktifkan BoundSan di file cetak biru

BoundSan dapat diaktifkan dalam file cetak biru dengan menambahkan "bounds" ke properti sanitasi misc_undefined untuk modul biner dan perpustakaan:

    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 membatalkan luapan, yang meniadakan keunggulan keamanan mitigasi dan membawa overhead kinerja yang lebih tinggi, sehingga tidak disarankan untuk build produksi.

DAFTAR BLOK

Properti BLOCKLIST memungkinkan spesifikasi file BLOCKLIST yang dapat digunakan pengembang untuk mencegah sanitasi fungsi dan file sumber. Gunakan properti ini hanya jika kinerja menjadi perhatian dan file/fungsi yang ditargetkan memberikan kontribusi besar. Audit file/fungsi ini secara manual untuk memastikan bahwa akses array aman. Lihat Pemecahan Masalah untuk detail tambahan.

Mengaktifkan BoundSan di makefiles

BoundSan dapat diaktifkan di makefile dengan menambahkan "bounds" ke variabel LOCAL_SANITIZE untuk modul biner dan perpustakaan:

    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 luapan, yang meniadakan keunggulan keamanan mitigasi dan membawa overhead kinerja yang lebih tinggi, sehingga tidak disarankan untuk build produksi.

LOCAL_SANITIZE_BLOCKLIST memungkinkan spesifikasi file BLOCKLIST yang memungkinkan pengembang mencegah fungsi dan file sumber dibersihkan. Gunakan properti ini hanya jika kinerja menjadi perhatian dan file/fungsi yang ditargetkan memberikan kontribusi besar. Audit file/fungsi ini secara manual untuk memastikan bahwa akses array aman. Lihat Pemecahan Masalah untuk detail tambahan.

Menonaktifkan BoundSan

Anda dapat menonaktifkan BoundSan dalam fungsi dan file sumber dengan BLOCKLIS atau atribut fungsi. Yang terbaik adalah tetap mengaktifkan BoundSan, jadi nonaktifkan hanya jika fungsi atau file menimbulkan overhead kinerja dalam jumlah besar dan sumbernya telah ditinjau secara manual.

Untuk informasi lebih lanjut tentang menonaktifkan BoundSan dengan atribut fungsi dan format file BLOCKLIST , lihat dokumentasi Clang LLVM. Cakupan DAFTAR BLOKLIS pada pembersih tertentu dengan menggunakan nama bagian yang menentukan target pembersih untuk menghindari dampak pada pembersih lainnya.

Validasi

Tidak ada tes CTS khusus untuk BoundSan. Sebaliknya, pastikan tes CTS lulus dengan atau tanpa BoundSan diaktifkan untuk memverifikasi bahwa tes tersebut tidak berdampak pada perangkat.

Penyelesaian masalah

Uji komponen secara menyeluruh setelah mengaktifkan BoundSan untuk memastikan bahwa akses di luar batas yang sebelumnya tidak terdeteksi telah diatasi.

Kesalahan BoundSan dapat dengan mudah diidentifikasi karena menyertakan pesan pembatalan batu nisan berikut:

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

Saat dijalankan 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 kesalahan apa pun.

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'