Bagian kode yang dapat dieksekusi untuk biner sistem AArch64 secara default ditandai sebagai khusus eksekusi (tidak dapat dibaca) sebagai mitigasi hardening terhadap serangan penggunaan kembali kode just-in-time. Kode yang menggabungkan data dan kode serta kode yang sengaja memeriksa bagian ini (tanpa memetakan ulang segmen memori terlebih dahulu agar dapat dibaca) tidak lagi berfungsi. Aplikasi dengan target SDK 10 (API level 29 atau yang lebih tinggi) akan terpengaruh jika aplikasi mencoba membaca bagian kode library sistem yang mengaktifkan memori khusus eksekusi (XOM) dalam memori tanpa menandai bagian tersebut sebagai dapat dibaca terlebih dahulu.
Untuk mendapatkan manfaat sepenuhnya dari mitigasi ini, dukungan hardware dan kernel diperlukan. Tanpa dukungan ini, mitigasi mungkin hanya diterapkan sebagian. Kernel umum Android 4.9 berisi patch yang sesuai untuk memberikan dukungan penuh untuk ini di perangkat ARMv8.2.
Implementasi
Biner AArch64 yang dihasilkan oleh compiler mengasumsikan bahwa kode dan data tidak tercampur. Mengaktifkan fitur ini tidak memengaruhi performa perangkat secara negatif.
Untuk kode yang harus melakukan introspeksi memori yang disengaja pada
segmen yang dapat dieksekusi, sebaiknya panggil mprotect
pada
segmen kode yang memerlukan pemeriksaan agar dapat dibaca, lalu
hapus keterbacaan saat pemeriksaan selesai.
Implementasi ini menyebabkan pembacaan ke segmen memori yang ditandai sebagai
khusus eksekusi sehingga menyebabkan error segmentasi (SEGFAULT
).
Hal ini dapat terjadi sebagai akibat dari bug, kerentanan, data yang dicampur dengan
kode (penggabungan literal), atau introspeksi memori yang disengaja.
Dukungan dan dampak perangkat
Perangkat dengan hardware atau kernel sebelumnya (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 ke memori khusus eksekusi,
tetapi kode kernel yang secara eksplisit memeriksa apakah halaman dapat dibaca mungkin masih
menerapkan properti ini, seperti process_vm_readv()
.
Flag kernel CONFIG_ARM64_UAO
harus ditetapkan di kernel untuk
memastikan kernel mematuhi halaman userland yang ditandai sebagai hanya eksekusi. Perangkat ARMv8
sebelumnya, atau perangkat ARMv8.2 dengan User Access Override (UAO) dinonaktifkan, mungkin tidak
mendapatkan manfaat sepenuhnya dari hal ini dan mungkin masih dapat membaca halaman khusus eksekusi menggunakan
syscall.
Memfaktorkan ulang kode yang ada
Kode yang telah di-port dari AArch32 mungkin berisi data dan
kode yang tercampur, sehingga menyebabkan masalah. Dalam banyak kasus, memperbaiki masalah ini semudah
memindahkan konstanta ke bagian .data
dalam file assembly.
Assembly tulisan tangan mungkin perlu difaktorkan ulang untuk memisahkan konstanta yang digabungkan secara lokal.
Contoh:
Biner yang dihasilkan oleh compiler Clang seharusnya tidak memiliki masalah dengan data yang tercampur dalam kode. Jika kode yang dihasilkan koleksi compiler GNU (GCC) disertakan (dari library statis), periksa biner output untuk memastikan bahwa konstanta belum digabungkan ke dalam bagian kode.
Jika introspeksi kode diperlukan di bagian kode yang dapat dieksekusi,
panggil mprotect
terlebih dahulu untuk menandai kode agar dapat dibaca. Kemudian, setelah operasi
selesai, panggil mprotect
lagi untuk menandainya sebagai tidak dapat dibaca.
Mengaktifkan XOM
Hanya eksekusi diaktifkan secara default untuk semua biner 64-bit dalam sistem build.
Menonaktifkan XOM
Anda dapat menonaktifkan hanya eksekusi di tingkat modul, berdasarkan seluruh hierarki subdirektori, atau secara global untuk seluruh build.
XOM dapat dinonaktifkan untuk setiap modul yang tidak dapat difaktorkan ulang, atau perlu membaca
kode yang dapat dieksekusi, dengan menetapkan 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 library statis, sistem build akan menerapkan
hal ini ke semua modul dependen dari library statis tersebut. Anda dapat mengganti
hal ini menggunakan xom: true,
.
Untuk menonaktifkan memori khusus eksekusi di subdirektori tertentu (misalnya,
foo/bar/), teruskan nilai ke XOM_EXCLUDE_PATHS
.
make -j XOM_EXCLUDE_PATHS=foo/bar
Atau, Anda dapat menetapkan variabel PRODUCT_XOM_EXCLUDE_PATHS
di konfigurasi produk.
Anda dapat menonaktifkan biner khusus eksekusi secara global dengan meneruskan
ENABLE_XOM=false
ke perintah make
.
make -j ENABLE_XOM=false
Validasi
Tidak ada CTS atau pengujian verifikasi yang tersedia untuk memori
khusus eksekusi. Anda dapat memverifikasi biner secara manual menggunakan readelf
dan memeriksa flag segmen.