Sanitizer Perilaku yang Tidak Ditentukan

{i>UndefinedBehaviorSanitizer <i}(UBSan) melakukan instrumentasi waktu kompilasi untuk memeriksa berbagai jenis perilaku yang tidak terdefinisi. Meskipun UBSan mampu mendeteksi banyak bug perilaku yang tidak ditentukan, Android mendukung:

  • perataan
  • Bool
  • batas
  • enum
  • {i>float-cast-overflow<i}
  • mengambang-bagi-dengan nol
  • bilangan bulat-pembagian-dengan nol
  • atribut bukan null
  • null
  • return
  • atribut return-nonnull-
  • shift-base
  • eksponen shift
  • tanda tangan bilangan bulat-overflow
  • tidak dapat dijangkau
  • tidak-bilangan bulat-overflow
  • terikat vla

stateless-integer-overflow, sementara secara teknis tidak ditentukan aktif, tercakup dalam sanitizer dan digunakan di banyak modul Android, termasuk komponen server media, untuk menghilangkan integer-overflow laten kerentanan.

Implementasi

Dalam 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 pada tingkat per modul, tetapkan LOCAL_SANITIZE dan tentukan perilaku yang tidak terdefinisi yang 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 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",
            ],
        },
    },

}

Pintasan UBSan

Android juga memiliki dua pintasan, integer dan default-ub, untuk mengaktifkan rangkaian pembersih tangan secara bersamaan. bilangan bulat mengaktifkan integer-divide-by-zero, signed-integer-overflow dan unsigned-integer-overflow. default-ub mengaktifkan pemeriksaan yang memiliki compiler minimal masalah performa: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. Tujuan kelas pembersih integer 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 ditemukan perilaku yang tidak terdefinisi. Secara default, fungsi ini dibatalkan. Namun, mulai Oktober 2016, UBSan di Android memiliki pustaka runtime opsional yang memberikan pelaporan error yang lebih mendetail, termasuk jenis perilaku yang tidak ditentukan ditemukan, file dan informasi baris kode sumber. Untuk mengaktifkan error ini pelaporan dengan pemeriksaan integer akan menambahkan kode berikut ke file Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

Nilai LOCAL_SANITIZE memungkinkan sanitizer selama build. LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih yang ditentukan. Penting memungkinkan untuk menetapkan LOCAL_SANITIZE dan LOCAL_SANITIZE_DIAG ke nilai yang berbeda, tetapi hanya pemeriksaan tersebut di LOCAL_SANITIZE yang diaktifkan. Jika suatu pemeriksaan tidak ditentukan dalam LOCAL_SANITIZE, tetapi ditentukan dalam LOCAL_SANITIZE_DIAG, pemeriksaan ini tidak diaktifkan dan pesan diagnostik tidak diberikan.

Berikut ini contoh informasi yang disediakan 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')

Sanitasi bilangan bulat

Overflow bilangan bulat yang tidak diinginkan dapat menyebabkan kerusakan atau informasi memori kerentanan pengungkapan dalam variabel yang terkait dengan akses memori atau alokasi memori. Untuk mengatasi hal ini, kami menambahkan Clang UndefinedBehaviorSanitizer (UBSan) pembersih bilangan bulat yang bertanda tangan dan tidak ditandatangani untuk memperkeras framework media di Android 7.0. Pada Android 9, kita diperluas UBSan untuk mencakup lebih banyak komponen dan meningkatkan dukungan sistem build untuknya.

Ini dirancang untuk menambahkan pemeriksaan seputar aritmetika Operations&hairsp;/&hairsp;instructions—yang mungkin overflow—untuk membatalkan proses dengan aman jika terjadi overflow. Pembersih ini dapat mengurangi kerusakan seluruh kelas memori dan kerentanan pengungkapan informasi di mana penyebab utama adalah bilangan bulat tambahan, seperti kerentanan Stagefright asli.

Contoh dan sumber

{i>Integer Overflow Sanitization <i}(IntSan) disediakan oleh compiler dan menambahkan instrumentasi ke dalam biner selama waktu kompilasi untuk mendeteksi aritmetika tambahan. Diaktifkan secara default di berbagai komponen di seluruh terkelola, misalnya /platform/external/libnl/Android.bp

Implementasi

IntSan menggunakan sanitizer overflow bilangan bulat yang ditandatangani dan tidak ditandatangani dari UBSan. Ini mitigasi diaktifkan pada tingkat per modul. Hal ini membantu menjaga komponen penting Android aman dan tidak boleh dinonaktifkan.

Kami sangat menganjurkan Anda untuk mengaktifkan Sanitasi Luapan Bilangan Bulat sebagai komponen. Kandidat ideal adalah kode native atau kode native dengan hak istimewa yang mengurai input pengguna yang tidak tepercaya. Ada overhead performa kecil yang terkait dengan pembersih yang bergantung pada penggunaan kode dan prevalensi operasi aritmatika. Akan ada persentase {i>overhead<i} yang kecil dan uji apakah performa menjadi kekhawatiran.

Mendukung IntSan di makefile

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 berupa kumpulan opsi yang sudah dikemas sebelumnya untuk {i>overflow sanitizer<i} bilangan bulat yang ditandatangani dan tidak ditandatangani dengan bawaan BLOKIR.
  • LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk pembersih. Gunakan mode diagnostik hanya selama pengujian karena mode ini tidak pembatalan pada {i>overflow<i}, sepenuhnya mengabaikan keuntungan keamanan dari mitigasi. Lihat Pemecahan masalah untuk detail tambahan.
  • LOCAL_SANITIZE_BLOCKLIST memungkinkan Anda menentukan BLOCKLIST untuk mencegah proses pembersihan fungsi dan file sumber. Lihat Pemecahan masalah untuk informasi tambahan spesifikasi pendukung.

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 sanitasi tambahan 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 halnya file make, properti integer_overflow merupakan paket sekumpulan opsi untuk luapan bilangan bulat individual yang ditandatangani dan tidak ditandatangani pembersih dengan default BLOKIR.

Rangkaian properti diag memungkinkan mode diagnostik untuk pembersih. Gunakan mode diagnostik hanya selama pengujian. Mode diagnostik tidak batalkan pada overflow, yang sepenuhnya mengabaikan keuntungan keamanan dari mitigasi dalam build pengguna. Lihat Pemecahan masalah untuk detail selengkapnya.

Properti BLOCKLIST mengizinkan spesifikasi file BLOCKLIST yang memungkinkan developer mencegah fungsi dan file sumber ditampilkan dibersihkan. Lihat Pemecahan masalah untuk detail tambahan.

Untuk mengaktifkan cairan 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 sanitasi tambahan bilangan bulat dalam komponen baru, atau mengandalkan library platform yang telah memiliki sanitasi tambahan bilangan bulat, Anda mungkin akan beberapa masalah dengan overflow bilangan bulat jinak yang menyebabkan pembatalan. Anda harus menguji dengan sanitasi diaktifkan untuk memastikan luapan yang tidak berbahaya dapat muncul.

Untuk menemukan, pembatalan yang disebabkan oleh sanitasi di build pengguna, telusuri SIGABRT error dengan pesan Batalkan yang menunjukkan bahwa kelebihan beban terdeteksi 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, kelebihan yang terjadi dalam fungsi inline mungkin tidak terlihat dalam pelacakan tumpukan.

Agar lebih mudah menentukan akar masalah, aktifkan diagnostik di library memicu pembatalan dan mencoba mereproduksi {i>error<i}. Dengan diagnostik diaktifkan, proses tidak akan dibatalkan dan sebagai gantinya terus berjalan. Tidak membatalkan akan membantu memaksimalkan jumlah luapan yang tidak berbahaya dalam jalur eksekusi tertentu tanpa harus mengompilasi ulang setelah memperbaiki setiap {i>bug<i}. Diagnostik menghasilkan pesan error yang menyertakan nomor baris dan 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 menu tambahan tidak berbahaya dan dimaksudkan (misalnya, tidak memiliki implikasi keamanan). Anda dapat mengatasi pembatalan melalui cairan pembersih oleh:

  • Memfaktorkan ulang kode untuk menghindari overflow (contoh)
  • Overflow secara eksplisit melalui __builtin_*_overflow Clang fungsi (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 yang paling terperinci. Misalnya, fungsi dengan banyak operasi aritmatika dan satu operasi overflow harus memfaktorkan ulang operasi tunggal, bukan seluruh fungsi DIBLOKIR.

Pola umum yang dapat menyebabkan overflow tidak berbahaya meliputi:

  • Implisit transmisi jika terjadi overflow yang tidak ditandatangani sebelum ditransmisikan ke jenis yang ditandatangani (contoh)
  • Penghapusan daftar tertaut yang mengurangi indeks loop saat penghapusan (contoh)
  • Menetapkan jenis yang tidak ditandatangani ke -1, bukan menentukan nilai maksimum yang sebenarnya (contoh)
  • Loop yang mengurangi bilangan bulat tanpa tanda tangan dalam kondisi (contoh, contoh)

Sebaiknya developer memastikan bahwa kasus di mana cairan pembersih mendeteksi kelebihan bahwa variabel ini memang tidak berbahaya tanpa efek samping atau keamanan yang tidak diinginkan implikasi sebelum menonaktifkan sanitasi.

Nonaktifkan IntSan

Anda dapat menonaktifkan IntSan dengan BLOCKLIST atau atribut fungsi. Nonaktifkan seperlunya dan hanya ketika memfaktorkan ulang kode yang tidak wajar atau jika ada {i>overhead<i} kinerja yang bermasalah.

Lihat dokumentasi Clang upstream untuk informasi selengkapnya tentang cara menonaktifkan IntSan dengan fungsi atribut dan file BLOCKLIST format. BLOCKLISTing harus dicakupkan ke pembersih tertentu dengan menggunakan nama bagian yang menentukan pembersih target agar tidak berdampak pada pembersih.

Validasi

Saat ini, tidak ada uji CTS khusus untuk Sanitasi Tambahan Bilangan Bulat. Sebaliknya, pastikan bahwa uji CTS lulus dengan atau tanpa mengaktifkan IntSan untuk bahwa hal itu tidak mempengaruhi perangkat.

Sanitasi batas

BoundsSanitizer (BoundSan) menambahkan instrumentasi ke biner untuk menyisipkan batas terkait akses array. Pemeriksaan ini ditambahkan jika compiler tidak membuktikan pada waktu kompilasi bahwa aksesnya 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 oleh {i>default<i} di berbagai komponen di seluruh platform.

Implementasi

BoundSan menggunakan UBSan membatasi {i>sanitizer<i}. Mitigasi ini diaktifkan pada tingkat per modul. 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 tergantung pada jumlah akses {i>array<i} yang tidak dapat dibuktikan aman. Dapatkan persentase {i>overhead<i} yang kecil rata-rata dan menguji apakah kinerja menjadi perhatian.

Mengaktifkan BoundSan dalam file blueprint

BoundSan dapat diaktifkan di file blueprint dengan menambahkan "bounds" ke properti sanitasi misc_undefined untuk biner dan library modul:

    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 pada kelebihan beban, yang meniadakan manfaat keamanan dari mitigasi dan membawa overhead performa yang lebih tinggi, sehingga tidak direkomendasikan untuk build produksi.

DAFTAR BLOKIR

Properti BLOCKLIST mengizinkan spesifikasi BLOCKLIST yang dapat digunakan developer untuk mencegah fungsi dan file sumber ditampilkan dibersihkan. Gunakan properti ini hanya jika performa menjadi perhatian Anda dan yang ditargetkan file/fungsi berkontribusi secara substansial. Audit file/fungsi ini secara manual untuk memastikan keamanan akses {i>array<i}. Lihat Pemecahan masalah untuk informasi lainnya spesifikasi pendukung.

Mengaktifkan BoundSan di makefile

BoundSan dapat diaktifkan di 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 oleh koma.

LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik. Gunakan diagnostik mode hanya selama pengujian. Mode diagnostik tidak dibatalkan saat terjadi overflow, yang meniadakan manfaat keamanan dari mitigasi dan memiliki dampak yang overhead performa, jadi tidak disarankan untuk build produksi.

LOCAL_SANITIZE_BLOCKLIST mengizinkan spesifikasi BLOCKLIST file yang memungkinkan developer mencegah fungsi dan file sumber ditampilkan dibersihkan. Gunakan properti ini hanya jika performa menjadi perhatian Anda dan yang ditargetkan file/fungsi berkontribusi secara substansial. Audit file/fungsi ini secara manual untuk memastikan keamanan akses {i>array<i}. Lihat Pemecahan masalah untuk informasi lainnya spesifikasi pendukung.

Nonaktifkan BoundSan

Anda dapat menonaktifkan BoundSan di fungsi dan file sumber dengan BLOCKLIST atau fungsi. Sebaiknya tetap aktifkan BoundSan, jadi hanya nonaktifkan jika fungsi atau file menimbulkan {i>overhead<i} kinerja dalam jumlah besar dan sumber telah ditinjau secara manual.

Untuk Informasi selengkapnya tentang cara menonaktifkan BoundSan dengan function atribut dan file BLOCKLIST format, lihat dokumentasi Clang LLVM. Membuat ruang lingkup BLOKIR ke sanitizer tertentu dengan menggunakan nama bagian yang menentukan target sanitizer agar tidak berdampak pada cairan pembersih lainnya.

Validasi

Tidak ada uji CTS khusus untuk BoundSan. Sebaliknya, pastikan bahwa CTS pengujian 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 tidak terdeteksi akan ditangani.

Error BoundSan dapat dengan mudah diidentifikasi karena mencakup hal berikut pesan pembatalan tombstone:

    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 indeks nilai dicetak ke logcat. Secara {i>default<i}, mode ini tidak menampilkan pesan batalkan. Tinjau logcat untuk memeriksa apakah ada yang sama.

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