Arm Memory Tagging Extension

Arm v9 memperkenalkan Arm Memory Tagging Extension (MTE), implementasi hardware memori yang diberi tag.

Pada tingkat tinggi, MTE memberi tag pada setiap alokasi/dealokasi memori dengan metadata tambahan. MTE menetapkan tag ke lokasi memori, yang kemudian dapat dikaitkan dengan pointer yang mereferensikan lokasi memori tersebut. Pada waktu proses, CPU memeriksa apakah pointer dan tag metadata cocok pada setiap pemuatan dan penyimpanan.

Di Android 12, pengalokasi memori heap kernel dan ruang pengguna dapat menambah metadata ke setiap alokasi. Hal ini membantu mendeteksi bug use-after-free dan buffer-overflow, yang merupakan sumber bug keamanan memori paling umum di codebase 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 kebenaran deteksi bug atas performa dan dapat digunakan sebagai alat deteksi bug yang presisi, saat overhead performa yang lebih tinggi dapat diterima. Jika diaktifkan, MTE SYNC berfungsi sebagai mitigasi keamanan. Jika ada ketidakcocokan tag, prosesor akan segera membatalkan eksekusi dan menghentikan proses dengan SIGSEGV (kode SEGV_MTESERR) dan informasi lengkap tentang akses memori dan alamat faulting.

Sebaiknya gunakan mode ini selama pengujian sebagai alternatif untuk HWASan/KASAN atau dalam produksi saat proses target merepresentasikan kerentanan platform terhadap serangan. Selain itu, jika mode ASYNC telah menunjukkan 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 akan merekam stack trace untuk semua alokasi dan dealokasi serta menggunakannya untuk memberikan laporan error yang lebih baik yang menyertakan penjelasan tentang error memori, seperti use-after-free atau buffer-overflow, dan stack trace 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 performa atas akurasi laporan bug dan dapat digunakan sebagai deteksi overhead rendah untuk bug keamanan memori. Jika ada ketidakcocokan tag, pemroses akan melanjutkan eksekusi hingga entri kernel terdekat (misalnya, syscall atau interupsi timer), yang menghentikan proses dengan SIGSEGV (kode SEGV_MTEAERR) tanpa merekam alamat faulting atau akses memori.

Sebaiknya gunakan mode ini dalam produksi pada codebase yang telah diuji dengan baik, dengan kepadatan bug keamanan memori yang diketahui rendah, yang dicapai dengan menggunakan mode SYNC selama pengujian.

Mode asimetris (ASYMM)

Fitur tambahan di Arm v8.7-A, mode MTE asimetris memberikan pemeriksaan sinkron pada pembacaan memori, dan pemeriksaan asinkron penulisan memori, dengan performa yang mirip dengan mode ASYNC. Dalam sebagian besar situasi, mode ini merupakan peningkatan dari mode ASYNC, dan sebaiknya gunakan mode ini, bukan ASYNC, jika tersedia.

Oleh karena itu, tidak ada API yang dijelaskan di bawah yang menyebutkan mode asimetris. Sebagai gantinya, OS dapat dikonfigurasi untuk selalu menggunakan mode asimetris saat asinkron diminta. Untuk mengetahui informasi selengkapnya, lihat Mengonfigurasi tingkat MTE pilihan khusus CPU.

MTE di ruang pengguna

Bagian berikut menjelaskan cara MTE dapat diaktifkan untuk proses sistem dan aplikasi. MTE dinonaktifkan secara default, kecuali jika salah satu opsi di bawah ditetapkan untuk proses tertentu (lihat komponen yang mengaktifkan MTE di bawah).

Mengaktifkan MTE menggunakan sistem build

Sebagai properti di seluruh proses, MTE dikontrol oleh setelan waktu build dari executable utama. Opsi berikut memungkinkan perubahan setelan ini untuk executable individual, atau untuk seluruh subdirektori di pohon sumber. Setelan ini diabaikan pada library, atau target apa pun yang bukan executable maupun pengujian.

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

Mode MTE Setelan
MTE Asinkron
  sanitize: {
  memtag_heap: true,
  }
MTE Sinkron
  sanitize: {
  memtag_heap: true,
  diag: {
  memtag_heap: true,
  },
  }

atau di Android.mk:

Mode MTE Setelan
Asynchronous MTE LOCAL_SANITIZE := memtag_heap
Synchronous MTE LOCAL_SANITIZE := memtag_heap
LOCAL_SANITIZE_DIAG := memtag_heap

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

Mode MTE Daftar sertakan Daftar kecualikan
asinkron PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS MEMTAG_HEAP_ASYNC_INCLUDE_PATHS PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
sinkron PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS MEMTAG_HEAP_SYNC_INCLUDE_PATHS

atau

Mode MTE Setelan
MTE Asinkron MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
MTE Sinkron MEMTAG_HEAP_SYNC_INCLUDE_PATHS

atau dengan menentukan jalur pengecualian executable:

Mode MTE Setelan
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

Setelan build di atas dapat diganti saat runtime dengan menetapkan properti sistem berikut:

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

Dengan basename adalah nama dasar executable.

Misalnya, untuk menetapkan /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

Cara lain untuk mengganti setelan build untuk proses native (non-aplikasi) adalah dengan menentukan variabel lingkungan: MEMTAG_OPTIONS=(off|sync|async) Jika variabel lingkungan dan properti sistem ditentukan, variabel akan diprioritaskan.

Mengaktifkan MTE untuk aplikasi

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

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

Jika ditetapkan pada tag <application>, atribut akan memengaruhi semua proses yang digunakan oleh aplikasi, dan dapat diganti untuk setiap proses dengan menetapkan tag <process>.

Untuk eksperimen, kompatibilitas perubahan dapat digunakan untuk menetapkan nilai default atribut memtagMode untuk aplikasi yang tidak menentukan nilai apa pun dalam manifes (atau menentukan default).

Fitur ini berada di bagian Sistem > Lanjutan > Opsi developer > Perubahan Kompatibilitas Aplikasi di menu setelan global. Menetapkan NATIVE_MEMTAG_ASYNC atau NATIVE_MEMTAG_SYNC akan mengaktifkan MTE untuk aplikasi tertentu. Anda juga dapat menyetelnya menggunakan perintah am sebagai berikut:

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

Membangun image sistem MTE

Sebaiknya aktifkan MTE pada semua biner native selama pengembangan dan pengaktifan. Hal ini membantu mendeteksi bug keamanan memori lebih awal dan memberikan cakupan pengguna yang realistis jika diaktifkan dalam build pengujian.

Sebaiknya aktifkan MTE dalam mode sinkron pada semua biner native selama pengembangan

SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m

Seperti variabel apa pun dalam sistem build, SANITIZE_TARGET dapat digunakan sebagai variabel lingkungan atau setelan make (misalnya, dalam file product.mk).

Hal ini mengaktifkan MTE untuk semua proses native, tetapi tidak untuk aplikasi (yang di-fork dari zygote64) yang MTE-nya dapat diaktifkan dengan mengikuti petunjuk di Mengaktifkan MTE untuk aplikasi.

Mengonfigurasi tingkat MTE pilihan khusus CPU

Di beberapa CPU, performa MTE dalam mode ASYMM atau bahkan SYNC mungkin mirip dengan performa ASYNC. Hal ini membuat pengaktifan pemeriksaan yang lebih ketat pada CPU tersebut menjadi bermanfaat saat mode pemeriksaan yang kurang ketat diminta, untuk mendapatkan manfaat deteksi error dari pemeriksaan yang lebih ketat tanpa kekurangan performa.

Secara default, proses yang dikonfigurasi untuk berjalan dalam mode ASYNC berjalan dalam mode ASYNC di semua CPU. Untuk mengonfigurasi kernel agar menjalankan proses ini dalam mode SYNC di CPU tertentu, nilai sinkronisasi harus ditulis ke sysfs entri /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred saat waktu booting. Hal ini dapat dilakukan dengan skrip init. Misalnya, untuk mengonfigurasi CPU 0-1 agar menjalankan proses mode ASYNC dalam mode SYNC, dan CPU 2-3 agar menggunakan mode ASYMM, hal berikut dapat ditambahkan ke klausa init 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

Tombstone dari proses mode ASYNC yang berjalan dalam mode SYNC berisi stack trace yang tepat dari lokasi error memori. Namun, tombstone tersebut tidak menyertakan stack trace alokasi atau dealokasi. Stack trace ini hanya tersedia jika proses dikonfigurasi untuk berjalan dalam mode SYNC.

int mallopt(M_THREAD_DISABLE_MEM_INIT, level)

dengan level adalah 0 atau 1.

Menonaktifkan inisialisasi memori di malloc, dan menghindari perubahan tag memori kecuali jika diperlukan untuk kebenaran.

int mallopt(M_MEMTAG_TUNING, level)

dengan level adalah:

  • M_MEMTAG_TUNING_BUFFER_OVERFLOW
  • M_MEMTAG_TUNING_UAF

Memilih strategi alokasi tag.

  • Setelan default adalah M_MEMTAG_TUNING_BUFFER_OVERFLOW.
  • M_MEMTAG_TUNING_BUFFER_OVERFLOW memungkinkan deteksi deterministik deteksi bug buffer overflow dan underflow linear dengan menetapkan nilai tag yang berbeda ke alokasi yang berdekatan. Mode ini memiliki peluang yang sedikit lebih rendah untuk mendeteksi bug use-after-free karena hanya setengah dari nilai tag yang mungkin tersedia untuk setiap lokasi memori. MTE tidak dapat mendeteksi overflow dalam butiran tag yang sama (chunk yang selaras 16 byte), dan dapat melewatkan overflow kecil meskipun dalam mode ini. Overflow tersebut tidak dapat menjadi penyebab kerusakan memori, karena memori dalam satu butiran tidak pernah digunakan untuk beberapa alokasi.
  • M_MEMTAG_TUNING_UAF memungkinkan tag yang diacak secara independen untuk probabilitas seragam ~93% dalam mendeteksi bug spasial (buffer overflow) dan temporal (use after free).

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

  • Menetapkan register hardwarePSTATE.TCO dapat menekan pemeriksaan tag untuk sementara (contoh). Misalnya, saat menyalin rentang memori dengan konten tag yang tidak diketahui, atau mengatasi bottleneck performa dalam loop aktif.
  • Saat menggunakan M_HEAP_TAGGING_LEVEL_SYNC, pengendali error sistem memberikan informasi tambahan seperti stack trace alokasi dan dealokasi. Fungsi ini memerlukan akses ke bit tag dan diaktifkan dengan meneruskan flag SA_EXPOSE_TAGBITS saat menetapkan pengendali sinyal. Sebaiknya program apa pun yang menetapkan pengendali sinyalnya sendiri dan mendelegasikan error yang tidak diketahui ke sistem melakukan hal yang sama.

MTE di kernel

Untuk mengaktifkan KASAN yang dipercepat MTE untuk kernel, konfigurasi kernel dengan CONFIG_KASAN=y, CONFIG_KASAN_HW_TAGS=y. Konfigurasi ini diaktifkan secara default pada kernel GKI, mulai dari Android 12-5.10.

Anda dapat mengontrolnya saat waktu booting menggunakan argumen command line berikut:

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

Sebaiknya gunakan mode SYNC selama pengaktifan, pengembangan, dan pengujian. Opsi ini harus diaktifkan secara global untuk semua proses menggunakan variabel lingkungan atau dengan sistem build. Dalam mode ini, bug terdeteksi lebih awal dalam proses pengembangan, codebase distabilkan lebih cepat, dan biaya untuk mendeteksi bug nanti dalam produksi dihindari.

Sebaiknya gunakan mode ASYNC dalam produksi. Mode ini menyediakan alat overhead rendah untuk mendeteksi keberadaan bug keamanan memori dalam suatu proses serta pertahanan mendalam lebih lanjut. Setelah bug terdeteksi, developer dapat memanfaatkan API runtime untuk beralih ke mode SYNC dan mendapatkan stack trace yang akurat dari kumpulan pengguna yang diambil sampelnya.

Sebaiknya konfigurasi tingkat MTE pilihan khusus CPU untuk SoC. Mode Asymm biasanya memiliki karakteristik performa yang sama dengan ASYNC, dan hampir selalu lebih disukai. Core kecil yang berurutan sering kali menunjukkan performa yang serupa dalam ketiga mode, dan dapat dikonfigurasi untuk lebih memilih SYNC.

Developer harus memeriksa keberadaan error dengan memeriksa /data/tombstones, logcat atau dengan memantau pipeline DropboxManager vendor untuk bug pengguna akhir. Untuk mengetahui info selengkapnya tentang proses debug kode native Android, lihat informasi di sini.

Komponen platform yang mengaktifkan MTE

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

  • Daemon dan utilitas jaringan (kecuali netd)
  • Bluetooth, SecureElement, NFC HAL, dan aplikasi sistem
  • Daemon statsd
  • system_server
  • zygote64 (untuk memungkinkan aplikasi memilih menggunakan MTE)

Target ini dipilih berdasarkan kriteria berikut:

  • Proses yang memiliki hak istimewa (didefinisikan sebagai proses yang memiliki akses ke sesuatu yang tidak dimiliki domain SELinux unprivileged_app)
  • Proses input yang tidak tepercaya (Aturan dua)
  • Perlambatan performa yang dapat diterima (perlambatan tidak membuat latensi yang terlihat oleh pengguna )

Sebaiknya vendor mengaktifkan MTE dalam produksi untuk lebih banyak komponen, dengan mengikuti kriteria yang disebutkan di atas. Selama pengembangan, sebaiknya uji komponen ini menggunakan mode SYNC, untuk mendeteksi bug yang mudah diperbaiki, dan menilai dampak ASYNC terhadap performanya.

Kami berencana untuk memperluas daftar komponen sistem yang mengaktifkan MTE, yang dipandu oleh karakteristik performa desain hardware mendatang.