UndefinedBehaviorSanitizer

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, dengan integer_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]'