Memori Eksekusi Saja (XOM) untuk Biner AArch64

Bagian kode yang dapat dieksekusi untuk biner sistem AArch64 secara default ditandai hanya eksekusi (tidak dapat dibaca) sebagai mitigasi yang lebih kuat terhadap serangan penggunaan kembali kode just-in-time. Kode yang menggabungkan data dan kode bersama-sama dan kode yang dengan sengaja memeriksa bagian ini (tanpa memetakan ulang segmen memori terlebih dahulu agar dapat dibaca) tidak lagi berfungsi. Aplikasi dengan SDK target 10 (API level 29 atau lebih tinggi) akan terpengaruh jika aplikasi mencoba membaca bagian kode dari pustaka sistem yang mengaktifkan memori hanya eksekusi (XOM) di memori tanpa terlebih dahulu menandai bagian tersebut sebagai dapat dibaca.

Untuk mendapatkan manfaat penuh dari mitigasi ini, diperlukan dukungan perangkat keras dan kernel. Tanpa dukungan ini, mitigasi mungkin hanya dapat dilaksanakan sebagian. Kernel umum Android 4.9 berisi patch yang sesuai untuk memberikan dukungan penuh pada perangkat ARMv8.2.

Penerapan

Biner AArch64 yang dihasilkan oleh kompiler berasumsi bahwa kode dan data tidak bercampur. Mengaktifkan fitur ini tidak berdampak negatif terhadap kinerja perangkat.

Untuk kode yang harus melakukan introspeksi memori yang disengaja pada segmen yang dapat dieksekusi, disarankan untuk memanggil mprotect pada segmen kode yang memerlukan pemeriksaan agar dapat dibaca, lalu hapus keterbacaan saat pemeriksaan selesai.
Implementasi ini menyebabkan pembacaan ke dalam segmen memori yang ditandai sebagai hanya eksekusi yang mengakibatkan kesalahan segmentasi ( SEGFAULT ). Hal ini mungkin terjadi akibat bug, kerentanan, data tercampur dengan kode (pengumpulan literal), atau introspeksi memori yang disengaja.

Dukungan dan dampak perangkat

Perangkat dengan perangkat keras lebih lama atau kernel lebih lama (lebih rendah dari 4.9) tanpa patch yang diperlukan mungkin tidak sepenuhnya mendukung atau mendapatkan manfaat dari fitur ini. Perangkat tanpa dukungan kernel mungkin tidak menerapkan akses pengguna pada memori yang hanya dapat dieksekusi, namun kode kernel yang secara eksplisit memeriksa apakah suatu halaman dapat dibaca masih dapat menerapkan properti ini, seperti process_vm_readv() .

Flag kernel CONFIG_ARM64_UAO harus diset di kernel untuk memastikan bahwa kernel menghormati halaman userland yang ditandai hanya untuk dieksekusi. Perangkat ARMv8 sebelumnya, atau perangkat ARMv8.2 dengan User Access Override (UAO) yang dinonaktifkan, mungkin tidak sepenuhnya mendapatkan manfaat dari hal ini dan mungkin masih dapat membaca halaman yang hanya dapat dijalankan menggunakan syscall.

Memfaktorkan ulang kode yang ada

Kode yang telah di-porting dari AArch32 mungkin berisi data dan kode yang bercampur, sehingga menyebabkan munculnya masalah. Dalam banyak kasus, memperbaiki masalah ini semudah memindahkan konstanta ke bagian .data di file perakitan.

Perakitan tulisan tangan mungkin perlu difaktorkan ulang untuk memisahkan konstanta yang dikumpulkan secara lokal.

Contoh:

Biner yang dihasilkan oleh kompiler Clang seharusnya tidak memiliki masalah dengan data yang dicampurkan ke dalam kode. Jika kode yang dihasilkan kumpulan kompiler GNU (GCC) disertakan (dari perpustakaan statis), periksa biner keluaran untuk memastikan bahwa konstanta belum dikumpulkan ke dalam bagian kode.

Jika introspeksi kode diperlukan pada bagian kode yang dapat dieksekusi, panggil mprotect terlebih dahulu untuk menandai kode dapat dibaca. Kemudian setelah operasi selesai, panggil mprotect lagi untuk menandainya tidak dapat dibaca.

Mengaktifkan

Hanya eksekusi diaktifkan secara default untuk semua biner 64-bit di sistem build.

Menonaktifkan

Anda dapat menonaktifkan eksekusi saja pada tingkat modul, pada seluruh pohon subdirektori, atau secara global untuk keseluruhan build.

XOM dapat dinonaktifkan untuk masing-masing modul yang tidak dapat difaktorkan ulang, atau perlu membaca kode yang dapat dieksekusi, dengan menyetel variabel LOCAL_XOM dan xom ke false .

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

Jika memori khusus eksekusi dinonaktifkan di pustaka statis, sistem pembangunan akan menerapkan ini ke semua modul dependen pustaka statis tersebut. Anda dapat menimpanya dengan menggunakan xom: true, .

Untuk menonaktifkan memori khusus eksekusi di subdirektori tertentu (misalnya, foo/bar/), teruskan nilainya ke XOM_EXCLUDE_PATHS .

make -j XOM_EXCLUDE_PATHS=foo/bar

Alternatifnya, Anda dapat mengatur variabel PRODUCT_XOM_EXCLUDE_PATHS di konfigurasi produk Anda.

Anda dapat menonaktifkan binari khusus eksekusi secara global dengan meneruskan ENABLE_XOM=false ke perintah make Anda.

make -j ENABLE_XOM=false

Validasi

Tidak ada tes CTS atau verifikasi yang tersedia untuk memori yang hanya dijalankan. Anda dapat memverifikasi biner secara manual menggunakan readelf dan memeriksa tanda segmen.