Integritas alur kontrol

Hingga 2016, sekitar 86% dari semua kerentanan di Android terkait dengan keamanan memori berkaitan. Sebagian besar kerentanan dieksploitasi oleh penyerang yang mengubah alur kontrol aplikasi untuk melakukan aktivitas berbahaya yang berubah-ubah dengan semua hak istimewa aplikasi yang dieksploitasi. Alur kontrol integritas (CFI) adalah mekanisme keamanan yang tidak mengizinkan perubahan pada grafik alur kontrol asli dari biner yang dikompilasi, membuatnya jauh lebih sulit melakukan serangan tersebut.

Di Android 8.1, kami mengaktifkan implementasi CFI oleh LLVM di stack media. Di beberapa Android 9, kami mengaktifkan CFI di lebih banyak komponen dan juga {i>kernel<i}. CFI Sistem adalah aktif secara {i>default<i} tetapi Anda harus mengaktifkan CFI {i>kernel<i}.

CFI LLVM membutuhkan kompilasi dengan Pengoptimalan Waktu Link (LTO). LTO mempertahankan representasi bitcode LLVM dari file objek sampai link-time, yang memungkinkan compiler untuk berpikir dengan lebih baik tentang pengoptimalan apa dapat dilakukan. Mengaktifkan LTO dapat mengurangi ukuran biner akhir dan meningkatkan berperforma tinggi, tetapi meningkatkan waktu kompilasi. Dalam pengujian di Android, kombinasi LTO dan CFI menghasilkan overhead yang dapat diabaikan untuk ukuran dan performa kode; di beberapa kasus membaik.

Untuk detail teknis lebih lanjut tentang CFI dan bagaimana pemeriksaan kontrol maju lainnya ditangani, lihat desain LLVM dokumentasi tambahan.

Contoh dan sumber

CFI disediakan oleh compiler dan menambahkan instrumentasi ke dalam biner selama waktu kompilasi. Kami mendukung CFI di toolchain Clang dan sistem build Android dalam AOSP.

CFI diaktifkan secara default untuk perangkat Arm64 untuk kumpulan komponen di /platform/build/target/product/cfi-common.mk. Iklan ini juga diaktifkan secara langsung di serangkaian komponen media makefile/blueprint file, seperti /platform/frameworks/av/media/libmedia/Android.bp dan /platform/frameworks/av/cmds/stagefright/Android.mk.

Mengimplementasikan CFI sistem

CFI diaktifkan secara default jika Anda menggunakan Clang dan sistem build Android. Karena CFI membantu menjaga keamanan pengguna Android, Anda tidak boleh menonaktifkannya.

Bahkan, kami sangat menyarankan Anda untuk mengaktifkan CFI untuk komponen tambahan. Kandidat ideal adalah kode native dengan hak istimewa, atau kode native yang memproses input pengguna yang tidak tepercaya. Jika Anda menggunakan {i>clang<i} dan sistem build Android, Anda dapat mengaktifkan CFI di komponen baru dengan menambahkan beberapa baris ke makefile Anda atau cetak biru yang lengkap ini.

Mendukung CFI dalam makefile

Untuk mengaktifkan CFI dalam file make, seperti /platform/frameworks/av/cmds/stagefright/Android.mk, tambahkan:

LOCAL_SANITIZE := cfi
# Optional features
LOCAL_SANITIZE_DIAG := cfi
LOCAL_SANITIZE_BLACKLIST := cfi_blacklist.txt

  • LOCAL_SANITIZE menentukan CFI sebagai pembersih selama buat.
  • LOCAL_SANITIZE_DIAG mengaktifkan mode diagnostik untuk CFI. Mode diagnostik mencetak informasi debug tambahan dalam logcat selama error, yang berguna saat mengembangkan dan menguji build. Merek pastikan Anda menghapus mode diagnostik pada build produksi.
  • LOCAL_SANITIZE_BLACKLIST memungkinkan komponen untuk secara selektif menonaktifkan instrumentasi CFI untuk setiap fungsi atau file sumber. Anda dapat menggunakan daftar hitam sebagai upaya terakhir untuk memperbaiki masalah yang dihadapi pengguna yang jika tidak ada. Untuk detail selengkapnya, lihat Menonaktifkan CFI.

Mendukung CFI dalam file blueprint

Untuk mengaktifkan CFI dalam file blueprint, seperti /platform/frameworks/av/media/libmedia/Android.bp, tambahkan:

   sanitize: {
        cfi: true,
        diag: {
            cfi: true,
        },
        blacklist: "cfi_blacklist.txt",
    },

Pemecahan masalah

Jika Anda mengaktifkan CFI di komponen baru, Anda mungkin mengalami beberapa masalah dengan error ketidakcocokan jenis fungsi dan ketidakcocokan jenis kode assembly error.

Error ketidakcocokan jenis fungsi terjadi karena CFI membatasi panggilan tidak langsung hanya langsung ke fungsi yang memiliki jenis dinamis yang sama dengan jenis statis yang digunakan panggilan telepon. CFI membatasi panggilan fungsi anggota virtual dan non-virtual agar hanya melompat ke objek yang merupakan kelas turunan dari tipe statis objek yang digunakan untuk menelepon. Artinya, saat Anda memiliki kode yang melanggar salah satu asumsi tersebut, maka instrumentasi yang ditambahkan CFI akan dibatalkan. Misalnya, pelacakan tumpukan menunjukkan SIGABRT dan logcat berisi garis tentang alur kontrol integritas data menemukan ketidaksesuaian yang diinginkan.

Untuk memperbaikinya, pastikan fungsi yang dipanggil memiliki jenis yang sama dengan dideklarasikan secara statis. Berikut adalah dua contoh CL:

Masalah lain yang mungkin terjadi adalah mencoba mengaktifkan CFI dalam kode yang berisi panggilan ke assembly. Karena kode assembly tidak diketik, ini menghasilkan jenis tidak cocok.

Untuk memperbaikinya, buat wrapper kode native untuk setiap panggilan assembly, dan berikan membungkus tanda tangan fungsi yang sama dengan penanda panggilan. Wrapper kemudian dapat secara langsung memanggil kode assembly. Karena cabang langsung tidak diinstrumentasikan oleh CFI (tidak dapat ditunjuk kembali saat runtime sehingga tidak menimbulkan risiko keamanan), tindakan ini akan menyelesaikan masalah.

Jika ada terlalu banyak fungsi assembly dan semuanya tidak dapat diperbaiki, Anda dapat juga membuat daftar hitam semua fungsi yang berisi panggilan tidak langsung ke assembly. Ini adalah tidak disarankan karena menonaktifkan pemeriksaan CFI pada fungsi ini, sehingga membuka permukaan serangan.

Menonaktifkan CFI

Kami tidak mengamati overhead performa apa pun, jadi Anda tidak perlu menonaktifkan CFI. Namun, jika ada dampak yang berdampak bagi pengguna, Anda dapat secara selektif menonaktifkan CFI untuk setiap fungsi atau file sumber dengan menyediakan file daftar hitam pembersih pada waktu kompilasi. Daftar hitam menginstruksikan compiler untuk menonaktifkan CFI instrumentasi di lokasi tertentu.

Sistem build Android menyediakan dukungan untuk daftar hitam per komponen (yang memungkinkan Anda untuk memilih file sumber atau fungsi individual yang tidak akan menerima CFI instrumentasi) untuk Make dan Soong. Untuk detail selengkapnya tentang format file daftar hitam, lihat file upstream Dokumen Clang.

Validasi

Saat ini, tidak ada pengujian CTS khusus untuk CFI. Sebagai gantinya, pastikan bahwa Pengujian CTS lulus dengan atau tanpa pengaktifan CFI untuk memverifikasi bahwa CFI tidak memengaruhi perangkat.