Execute-only memory (XOM) untuk biner AArch64

Bagian kode yang dapat dieksekusi untuk biner sistem AArch64 ditandai secara default eksekusi-saja (tidak dapat dibaca) sebagai mitigasi pengerasan terhadap kode tepat waktu serangan {i>restart<i}. Kode yang mencampur data dan kode bersama-sama dan membuat kode yang sengaja memeriksa bagian ini (tanpa terlebih dahulu memetakan ulang segmen memori sebagai dapat dibaca) tidak lagi berfungsi. Aplikasi dengan SDK target 10 (API level 29 atau yang lebih tinggi) akan terpengaruh jika aplikasi mencoba membaca bagian kode dari {i>Execute-only memory<i} (XOM) yang mengaktifkan library sistem di memori tanpa terlebih dahulu menandai bagian tersebut sebagai dapat dibaca.

Untuk memanfaatkan sepenuhnya mitigasi ini, dukungan perangkat keras dan {i>kernel<i} tidak diperlukan. Tanpa dukungan ini, mitigasi mungkin hanya diterapkan sebagian. Tujuan Kernel umum Android 4.9 berisi patch yang sesuai untuk menyediakan dukungan untuk ini di perangkat ARMv8.2.

Implementasi

Biner AArch64 yang dihasilkan oleh compiler menganggap bahwa kode dan data tidak bercampur. Mengaktifkan fitur ini tidak berdampak negatif terhadap performa perangkat.

Untuk kode yang harus melakukan introspeksi memori yang disengaja pada segmen yang dapat dieksekusi, sebaiknya panggil mprotect di segmen kode yang membutuhkan pemeriksaan agar bisa dibaca, maka menghilangkan keterbacaan saat pemeriksaan selesai.
Implementasi ini menyebabkan pembacaan ke segmen memori yang ditandai sebagai jalankan saja untuk menghasilkan kesalahan segmentasi (SEGFAULT). Hal ini dapat terjadi sebagai akibat dari {i>bug<i}, kerentanan, data yang tercampur dengan kode (penggabungan literal), atau introspeksi memori yang disengaja.

Dampak dan dukungan perangkat

Perangkat dengan perangkat keras yang lebih lawas atau kernel yang lebih lawas (lebih rendah dari 4,9) tanpa {i>patch<i} yang diperlukan mungkin tidak sepenuhnya mendukung atau memanfaatkan fitur ini. Perangkat tanpa dukungan {i>kernel<i} tidak dapat memberlakukan akses pengguna ke memori {i>execute-only<i}, Namun, kode {i>kernel<i} yang secara eksplisit memeriksa apakah suatu laman dapat dibaca mungkin menerapkan properti ini, seperti process_vm_readv().

Flag kernel CONFIG_ARM64_UAO harus ditetapkan dalam kernel agar memastikan bahwa {i>kernel<i} mengikuti laman pengguna yang ditandai sebagai {i>execute-only<i}. ARMv8 sebelumnya perangkat ARMv8.2 dengan User Access Override (UAO) nonaktif, mungkin tidak memanfaatkan sepenuhnya fungsi ini dan mungkin masih dapat membaca laman khusus eksekusi dengan menggunakan {i>syscall<i}.

Memfaktorkan ulang kode yang ada

Kode yang telah ditransfer dari AArch32 mungkin berisi data campuran dan kode tertentu, yang menyebabkan munculnya masalah. Dalam banyak kasus, memperbaiki masalah ini semudah sebagai memindahkan konstanta ke bagian .data dalam file assembly.

Rakitan tulisan tangan mungkin perlu difaktorkan ulang untuk memisahkan penggabungan secara lokal konstanta.

Contoh:

Biner yang dihasilkan oleh compiler Clang seharusnya tidak memiliki masalah data dicampur dalam kode. Jika kode yang dihasilkan GNU compiler collection (GCC) adalah disertakan (dari {i>library<i} statis), memeriksa biner {i>output<i} untuk memastikan bahwa konstanta belum dikumpulkan ke dalam bagian kode.

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

Aktifkan XOM

Hanya jalankan diaktifkan secara default untuk semua biner 64-bit dalam build sistem file.

Nonaktifkan XOM

Anda dapat menonaktifkan execution-only di level modul, oleh seluruh hierarki subdirektori, atau secara global untuk seluruh build.

XOM dapat dinonaktifkan untuk modul individu yang tidak dapat difaktorkan ulang, atau perlu membaca kode yang dapat dieksekusi, dengan menyetel LOCAL_XOM dan xom variabel 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 ini untuk semua modul dependen dari {i>library<i} statis itu. Anda dapat mengganti ini menggunakan xom: true,.

Untuk menonaktifkan memori execution-only di subdirektori tertentu (misalnya, foo/bar/), teruskan nilai ke XOM_EXCLUDE_PATHS.

make -j XOM_EXCLUDE_PATHS=foo/bar

Atau, Anda dapat menetapkan PRODUCT_XOM_EXCLUDE_PATHS variabel dalam konfigurasi produk Anda.

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

make -j ENABLE_XOM=false

Validasi

Tidak ada pengujian CTS atau verifikasi yang tersedia untuk dijalankan saja memori. Anda dapat memverifikasi biner secara manual menggunakan readelf dan memeriksanya penanda segmen.