Arm Memory Tagging Extension

Arm v9 memperkenalkan Arm Memory Tagging Extension (MTE), sebuah implementasi perangkat keras dari memori yang diberi tag.

Pada tingkat tinggi, MTE menandai setiap alokasi/dealokasi memori dengan metadata tambahan. Ini memberikan tag ke lokasi memori, yang kemudian dapat dikaitkan dengan pointer yang mereferensikan lokasi memori tersebut. Saat runtime, CPU memeriksa apakah penunjuk dan tag metadata cocok pada setiap pemuatan dan penyimpanan.

Di Android 12, pengalokasi memori heap kernel dan userspace dapat menambah setiap alokasi dengan metadata. Hal ini membantu mendeteksi bug penggunaan setelah bebas dan buffer-overflow, yang merupakan sumber bug keamanan memori paling umum di basis kode kami.

Mode operasi MTE

MTE memiliki tiga mode operasi:

  • Mode sinkron (SYNC)
  • Mode asinkron (ASYNC)
  • Mode asimetris (ASYMM)

Mode sinkron (SYNC)

Mode ini dioptimalkan untuk ketepatan deteksi bug dibandingkan performa dan dapat digunakan sebagai alat deteksi bug yang tepat, ketika overhead performa yang lebih tinggi dapat diterima. Saat diaktifkan, MTE SYNC bertindak sebagai mitigasi keamanan. Jika tag tidak cocok, prosesor segera membatalkan eksekusi dan menghentikan proses dengan SIGSEGV (kode SEGV_MTESERR ) dan informasi lengkap tentang akses memori dan alamat kesalahan.

Kami merekomendasikan penggunaan mode ini selama pengujian sebagai alternatif HWASan/KASAN atau dalam produksi ketika proses target mewakili permukaan serangan yang rentan. Selain itu, ketika mode ASYNC mengindikasikan adanya bug, laporan bug yang akurat dapat diperoleh dengan menggunakan API runtime untuk mengalihkan eksekusi ke mode SYNC.

Saat berjalan dalam mode SYNC, pengalokasi Android mencatat pelacakan tumpukan untuk semua alokasi dan dealokasi dan menggunakannya untuk memberikan laporan kesalahan yang lebih baik yang mencakup penjelasan kesalahan memori, seperti penggunaan setelah bebas, atau buffer-overflow, dan tumpukan jejak peristiwa memori yang relevan. Laporan tersebut memberikan informasi yang lebih kontekstual dan membuat bug lebih mudah dilacak dan diperbaiki.

Mode asinkron (ASYNC)

Mode ini dioptimalkan untuk kinerja dibandingkan keakuratan laporan bug dan dapat digunakan sebagai deteksi overhead rendah untuk bug keamanan memori.
Jika tag tidak cocok, prosesor melanjutkan eksekusi hingga entri kernel terdekat (misalnya, interupsi syscall atau timer), yang kemudian menghentikan proses dengan SIGSEGV (kode SEGV_MTEAERR ) tanpa mencatat alamat kesalahan atau akses memori.
Kami merekomendasikan penggunaan mode ini dalam produksi pada basis kode yang telah diuji dengan baik di mana kepadatan bug keamanan memori diketahui rendah, yang dicapai dengan menggunakan mode SYNC selama pengujian.

Mode asimetris (ASYMM)

Fitur tambahan di Arm v8.7-A, mode MTE Asimetris menyediakan pemeriksaan sinkron pada pembacaan memori, dan pemeriksaan penulisan memori asinkron, dengan kinerja yang mirip dengan mode ASYNC. Dalam sebagian besar situasi, mode ini merupakan peningkatan dari mode ASYNC, dan kami menyarankan untuk menggunakannya daripada ASYNC kapan pun mode tersebut tersedia.

Karena alasan ini, tidak ada API yang dijelaskan di bawah ini yang menyebutkan mode Asimetris. Sebaliknya, OS dapat dikonfigurasi untuk selalu menggunakan mode Asymmetric ketika Asynchronous diminta. Silakan merujuk ke bagian "Mengonfigurasi level MTE pilihan khusus CPU" untuk informasi lebih lanjut.

MTE di ruang pengguna

Bagian berikut menjelaskan bagaimana MTE dapat diaktifkan untuk proses dan aplikasi sistem. MTE dinonaktifkan secara default, kecuali salah satu opsi di bawah ini disetel untuk proses tertentu (lihat komponen apa saja yang diaktifkan MTE di bawah ).

Mengaktifkan MTE menggunakan sistem build

Sebagai properti seluruh proses, MTE dikontrol oleh pengaturan waktu build dari executable utama. Opsi berikut memungkinkan perubahan pengaturan ini untuk masing-masing executable, atau untuk seluruh subdirektori di pohon sumber. Pengaturan ini diabaikan di perpustakaan, atau target apa pun yang tidak dapat dieksekusi atau diuji.

1. Mengaktifkan MTE di Android.bp ( contoh ), untuk proyek tertentu:

Modus MTE Pengaturan
MTE asinkron
  sanitize: {
  memtag_heap: true,
  }
MTE sinkron
  sanitize: {
  memtag_heap: true,
  diag: {
  memtag_heap: true,
  },
  }

atau di Android.mk:

Modus MTE Pengaturan
Asynchronous MTE LOCAL_SANITIZE := memtag_heap
Synchronous MTE LOCAL_SANITIZE := memtag_heap
LOCAL_SANITIZE_DIAG := memtag_heap

2. Mengaktifkan MTE pada subdirektori di pohon sumber menggunakan variabel produk:

Modus MTE Sertakan daftar Kecualikan daftar
asinkron PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS MEMTAG_HEAP_ASYNC_INCLUDE_PATHS PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
sinkronisasi PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS MEMTAG_HEAP_SYNC_INCLUDE_PATHS

atau

Modus MTE Pengaturan
MTE asinkron MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
MTE sinkron MEMTAG_HEAP_SYNC_INCLUDE_PATHS

atau dengan menentukan jalur pengecualian dari file yang dapat dieksekusi:

Modus MTE Pengaturan
MTE asinkron PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
MTE sinkron

Contoh, (penggunaan serupa dengan PRODUCT_CFI_INCLUDE_PATHS )

  PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS=vendor/$(vendor)
  PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS=vendor/$(vendor)/projectA \
                                    vendor/$(vendor)/projectB

Mengaktifkan MTE menggunakan properti sistem

Pengaturan build di atas dapat ditimpa saat runtime dengan mengatur properti sistem berikut:

arm64.memtag.process.<basename> = (off|sync|async)

Dimana basename adalah nama dasar dari file yang dapat dieksekusi.

Misalnya, untuk menyetel /system/bin/ping atau /data/local/tmp/ping agar menggunakan MTE asinkron, gunakan adb shell setprop arm64.memtag.process.ping async .

Mengaktifkan MTE menggunakan variabel lingkungan

Satu lagi cara untuk mengganti pengaturan build adalah dengan mendefinisikan variabel lingkungan: MEMTAG_OPTIONS=(off|sync|async) Jika variabel lingkungan dan properti sistem didefinisikan, variabel akan diutamakan.

Mengaktifkan MTE untuk aplikasi

Jika tidak ditentukan, MTE dinonaktifkan secara default, namun aplikasi yang ingin menggunakan MTE dapat melakukannya dengan menyetel android:memtagMode di bawah tag <application> atau <process> di AndroidManifest.xml .

android:memtagMode=(off|default|sync|async)

Jika disetel pada tag <application> , atribut tersebut memengaruhi semua proses yang digunakan oleh aplikasi, dan dapat diganti untuk masing-masing proses dengan menyetel tag <process> .

Untuk eksperimen, perubahan kompatibilitas dapat digunakan untuk menetapkan nilai default atribut memtagMode untuk aplikasi yang tidak menentukan nilai apa pun dalam manifes (atau menentukan default ).
Ini dapat ditemukan di System > Advanced > Developer options > App Compatibility Changes di menu pengaturan global. Menyetel NATIVE_MEMTAG_ASYNC atau NATIVE_MEMTAG_SYNC mengaktifkan MTE untuk aplikasi tertentu.
Alternatifnya, ini dapat diatur menggunakan perintah am sebagai berikut:

$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.name

Membangun citra sistem MTE

Kami sangat menyarankan untuk mengaktifkan MTE pada semua biner asli selama pengembangan dan pengembangan. Hal ini membantu mendeteksi bug keamanan memori secara dini dan memberikan cakupan pengguna yang realistis, jika diaktifkan dalam pengujian build.

Kami sangat menyarankan untuk mengaktifkan MTE dalam mode Sinkron pada semua biner asli selama pengembangan

SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m

Seperti halnya variabel apa pun dalam sistem pembangunan, SANITIZE_TARGET dapat digunakan sebagai variabel lingkungan atau pengaturan make (misalnya, dalam file product.mk ).
Harap perhatikan bahwa ini mengaktifkan MTE untuk semua proses asli, tetapi tidak untuk aplikasi (yang merupakan cabang dari zygote64 ) yang MTE-nya dapat diaktifkan dengan mengikuti petunjuk di atas .

Mengonfigurasi level MTE pilihan khusus CPU

Pada beberapa CPU, kinerja MTE dalam mode ASYMM atau bahkan SYNC mungkin serupa dengan ASYNC. Hal ini menjadikannya bermanfaat untuk mengaktifkan pemeriksaan yang lebih ketat pada CPU tersebut ketika mode pemeriksaan yang tidak terlalu ketat diminta, untuk mendapatkan manfaat deteksi kesalahan dari pemeriksaan yang lebih ketat tanpa penurunan kinerja.
Secara default, proses yang dikonfigurasi untuk berjalan dalam mode ASYNC akan berjalan dalam mode ASYNC di semua CPU. Untuk mengkonfigurasi kernel agar menjalankan proses ini dalam mode SYNC pada CPU tertentu, nilai sync harus ditulis ke entri sysfs /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred pada waktu boot. Ini dapat dilakukan dengan skrip init. Misalnya, untuk mengkonfigurasi CPU 0-1 untuk menjalankan proses mode ASYNC dalam mode SYNC, dan CPU 2-3 untuk menjalankan proses dalam mode ASYMM, berikut ini dapat ditambahkan ke klausa init dari skrip init vendor:

  write /sys/devices/system/cpu/cpu0/mte_tcf_preferred sync
  write /sys/devices/system/cpu/cpu1/mte_tcf_preferred sync
  write /sys/devices/system/cpu/cpu2/mte_tcf_preferred asymm
  write /sys/devices/system/cpu/cpu3/mte_tcf_preferred asymm

Batu nisan dari proses mode ASYNC yang berjalan dalam mode SYNC akan berisi jejak tumpukan yang tepat dari lokasi kesalahan memori. Namun, mereka tidak akan menyertakan jejak tumpukan alokasi atau dealokasi. Pelacakan tumpukan ini hanya tersedia jika proses dikonfigurasi untuk berjalan dalam mode SYNC.

int mallopt(M_THREAD_DISABLE_MEM_INIT, level)

dimana level 0 atau 1.
Menonaktifkan inisialisasi memori di malloc, dan menghindari perubahan tag memori kecuali diperlukan untuk kebenaran.

int mallopt(M_MEMTAG_TUNING, level)

dimana level adalah:

  • M_MEMTAG_TUNING_BUFFER_OVERFLOW
  • M_MEMTAG_TUNING_UAF

Memilih strategi alokasi tag.

  • Setelan bawaannya adalah M_MEMTAG_TUNING_BUFFER_OVERFLOW .
  • M_MEMTAG_TUNING_BUFFER_OVERFLOW - memungkinkan deteksi deterministik dari bug buffer overflow dan underflow linier dengan menetapkan nilai tag yang berbeda ke alokasi yang berdekatan. Mode ini memiliki peluang yang sedikit lebih kecil untuk mendeteksi bug penggunaan setelah bebas karena hanya setengah dari kemungkinan nilai tag yang tersedia untuk setiap lokasi memori. Harap diingat bahwa MTE tidak dapat mendeteksi luapan dalam butiran tag yang sama (potongan selaras 16-byte), dan dapat melewatkan luapan kecil bahkan dalam mode ini. Luapan seperti itu tidak dapat menyebabkan kerusakan memori, karena memori dalam satu butiran tidak pernah digunakan untuk beberapa alokasi.
  • M_MEMTAG_TUNING_UAF - mengaktifkan tag yang diacak secara independen untuk seragam ~93% kemungkinan mendeteksi bug spasial (buffer overflow) dan temporal (digunakan setelah gratis).

Selain API yang dijelaskan di atas, pengguna berpengalaman mungkin perlu mengetahui hal-hal berikut:

  • Menyetel register perangkat keras PSTATE.TCO dapat menghentikan pemeriksaan tag untuk sementara ( contoh ). Misalnya, saat menyalin rentang memori dengan konten tag yang tidak diketahui, atau mengatasi hambatan kinerja dalam hot loop.
  • Saat menggunakan M_HEAP_TAGGING_LEVEL_SYNC , pengendali kerusakan sistem memberikan informasi tambahan seperti pelacakan tumpukan alokasi dan deallokasi. Fungsionalitas ini memerlukan akses ke bit tag dan diaktifkan dengan meneruskan tanda SA_EXPOSE_TAGBITS saat menyetel pengendali sinyal. Program apa pun yang menetapkan penangan sinyalnya sendiri dan mendelegasikan kerusakan yang tidak diketahui ke sistem, disarankan untuk melakukan hal yang sama.

MTE di kernel

Untuk mengaktifkan KASAN yang dipercepat MTE pada kernel, konfigurasikan kernel dengan CONFIG_KASAN=y , CONFIG_KASAN_HW_TAGS=y . Konfigurasi ini diaktifkan secara default di kernel GKI, dimulai dengan Android 12-5.10 .
Ini dapat dikontrol pada saat boot menggunakan argumen baris perintah berikut:

  • kasan=[on|off] - mengaktifkan atau menonaktifkan KASAN (default: on )
  • kasan.mode=[sync |async ] - pilih antara mode sinkron dan asinkron (default: sync )
  • kasan.stacktrace=[on|off] - apakah akan mengumpulkan jejak tumpukan (default: on )
    • pengumpulan jejak tumpukan juga memerlukan stack_depot_disable=off .
  • kasan.fault=[report|panic] - apakah hanya mencetak laporan saja, atau juga membuat kernel panik (default: report ). Terlepas dari opsi ini, pemeriksaan tag akan dinonaktifkan setelah kesalahan pertama dilaporkan.

Kami sangat menyarankan penggunaan mode SYNC selama pengembangan, pengembangan, dan pengujian. Opsi ini harus diaktifkan secara global untuk semua proses yang menggunakan variabel lingkungan atau dengan sistem build . Dalam mode ini, bug terdeteksi di awal proses pengembangan, basis kode distabilkan lebih cepat, dan biaya pendeteksian bug di kemudian hari dalam produksi dapat dihindari.

Kami sangat menyarankan penggunaan mode ASYNC dalam produksi. Ini memberikan alat overhead rendah untuk mendeteksi keberadaan bug keamanan memori dalam suatu proses serta pertahanan lebih mendalam. Setelah bug terdeteksi, pengembang dapat memanfaatkan API runtime untuk beralih ke mode SYNC dan mendapatkan pelacakan tumpukan yang akurat dari sekelompok pengguna yang dijadikan sampel.

Kami sangat menyarankan untuk mengonfigurasi level MTE pilihan khusus CPU untuk SoC. Mode Asymm biasanya memiliki karakteristik kinerja yang sama dengan ASYNC, dan hampir selalu lebih disukai. Inti kecil yang berurutan sering kali menunjukkan kinerja serupa di ketiga mode, dan dapat dikonfigurasi untuk memilih SYNC.

Pengembang harus memeriksa adanya kerusakan dengan memeriksa /data/tombstones , logcat , atau dengan memantau saluran pipa vendor DropboxManager untuk mencari bug pengguna akhir. Untuk informasi selengkapnya tentang men-debug kode asli Android, lihat informasinya di sini .

Komponen platform yang mendukung MTE

Di Android 12, sejumlah komponen sistem keamanan penting menggunakan MTE ASYNC untuk mendeteksi error pengguna akhir dan bertindak sebagai lapisan pertahanan tambahan yang mendalam. Komponen-komponen tersebut adalah:

  • Daemon dan utilitas jaringan (dengan pengecualian netd )
  • Bluetooth, SecureElement, NFC HAL, dan aplikasi sistem
  • daemon statsd
  • system_server
  • zygote64 (untuk memungkinkan aplikasi ikut serta menggunakan MTE)

Target-target ini dipilih berdasarkan kriteria berikut:

  • Proses yang memiliki hak istimewa (didefinisikan sebagai proses yang memiliki akses ke sesuatu yang tidak dimiliki oleh domain SELinux unprivileged_app)
  • Memproses masukan yang tidak dapat dipercaya ( Aturan dua )
  • Perlambatan kinerja yang dapat diterima (perlambatan tidak menimbulkan latensi yang terlihat oleh pengguna)

Kami mendorong vendor untuk mengaktifkan MTE dalam produksi untuk lebih banyak komponen, dengan mengikuti kriteria yang disebutkan di atas. Selama pengembangan, kami merekomendasikan pengujian komponen ini menggunakan mode SYNC, untuk mendeteksi bug yang mudah diperbaiki, dan menilai dampak ASYNC terhadap kinerjanya.
Di masa depan, Android berencana untuk memperluas daftar komponen sistem yang mengaktifkan MTE, dipandu oleh karakteristik kinerja desain perangkat keras yang akan datang.