Arm memory tagging extension

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

Secara umum, MTE memberi tag pada setiap alokasi/dealokasi memori dengan metadata tambahan. Hal ini menetapkan tag ke lokasi memori, yang kemudian dapat dikaitkan dengan pointer yang mereferensikan lokasi memori tersebut. Saat runtime, 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 setiap alokasi dengan metadata. Hal ini membantu mendeteksi bug penggunaan setelah pelepasan dan buffer overflow, yang merupakan sumber paling umum dari bug keamanan memori dalam 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 mencatat rekaman jejak stack untuk semua alokasi dan dealokasi serta menggunakannya untuk memberikan laporan error yang lebih baik yang mencakup penjelasan tentang error memori, seperti use-after-free, atau buffer overflow, dan rekaman jejak stack dari 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, prosesor akan melanjutkan eksekusi hingga entri kernel terdekat (misalnya, syscall atau interupsi timer), yang menghentikan proses dengan SIGSEGV (kode SEGV_MTEAERR) tanpa mencatat 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 menyediakan pemeriksaan sinkron pada pembacaan memori, dan pemeriksaan asinkron pada penulisan memori, dengan performa yang mirip dengan mode ASYNC. Dalam sebagian besar situasi, mode ini lebih baik daripada mode ASYNC, dan sebaiknya gunakan mode ini daripada 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. Lihat bagian "Mengonfigurasi tingkat MTE pilihan khusus CPU" untuk mengetahui informasi selengkapnya.

MTE di ruang pengguna

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

Mengaktifkan MTE menggunakan sistem build

Sebagai properti seluruh proses, MTE dikontrol oleh setelan waktu build dapat dieksekusi utama. Opsi berikut memungkinkan perubahan setelan ini untuk file yang dapat dieksekusi satu per satu, atau untuk seluruh subdirektori dalam struktur sumber. Setelan 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 Sertakan daftar Daftar pengecualian
asinkron PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS MEMTAG_HEAP_ASYNC_INCLUDE_PATHS PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
sinkronkan 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 file yang dapat dieksekusi:

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 menyetel properti sistem berikut:

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

Dengan basename adalah nama dasar 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

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 dinonaktifkan secara default, tetapi aplikasi yang ingin menggunakan MTE dapat melakukannya dengan menyetel android:memtagMode pada tag <application> atau <process> di AndroidManifest.xml.

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

Jika ditetapkan pada tag <application>, atribut tersebut akan memengaruhi semua proses yang digunakan oleh aplikasi, dan dapat diganti untuk setiap proses dengan menetapkan 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).
Perubahan ini dapat ditemukan di bagian System > Advanced > Developer options > App Compatibility Changes dalam menu setelan global. Menetapkan NATIVE_MEMTAG_ASYNC atau NATIVE_MEMTAG_SYNC akan mengaktifkan MTE untuk aplikasi tertentu.
Atau, setelan ini dapat ditetapkan menggunakan perintah am sebagai berikut:

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

Membangun image sistem MTE

Sebaiknya aktifkan MTE di semua biner native selama pengembangan dan penyiapan. Hal ini membantu mendeteksi bug keamanan memori sejak 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 lainnya dalam sistem build, SANITIZE_TARGET dapat digunakan sebagai variabel lingkungan atau setelan make (misalnya, dalam file product.mk).
Perhatikan bahwa tindakan 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 atas.

Mengonfigurasi level MTE pilihan khusus CPU

Pada beberapa CPU, performa MTE dalam mode ASYMM atau bahkan SYNC mungkin serupa dengan performa ASYNC. Hal ini membuat pengaktifan pemeriksaan yang lebih ketat pada CPU tersebut menjadi berharga saat mode pemeriksaan yang kurang ketat diminta, untuk mendapatkan manfaat deteksi error dari pemeriksaan yang lebih ketat tanpa kerugian performa.
Secara default, proses yang dikonfigurasi untuk berjalan dalam mode ASYNC akan berjalan dalam mode ASYNC di semua CPU. Untuk mengonfigurasi kernel agar menjalankan proses ini dalam mode SYNC di CPU tertentu, sinkronisasi nilai harus ditulis ke entri sysfs /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 ASYNCH di mode SYNC, dan CPU 2-3 agar berjalan di mode ASYMM, 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

Penanda dari proses mode ASYNC yang berjalan dalam mode SYNC akan berisi stack trace yang tepat dari lokasi error memori. Namun, tidak akan 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-nya adalah M_MEMTAG_TUNING_BUFFER_OVERFLOW.
  • M_MEMTAG_TUNING_BUFFER_OVERFLOW - memungkinkan deteksi deterministik bug overflow dan underflow buffer linear dengan menetapkan nilai tag yang berbeda ke alokasi yang berdekatan. Mode ini memiliki peluang yang sedikit lebih kecil untuk mendeteksi bug use-after-free karena hanya setengah dari kemungkinan nilai tag yang tersedia untuk setiap lokasi memori. Perlu diingat bahwa MTE tidak dapat mendeteksi overflow dalam butiran tag yang sama (chunk yang diselaraskan 16 byte), dan dapat melewatkan overflow kecil bahkan 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 - mengaktifkan tag yang diacak secara independen untuk probabilitas ~93% yang seragam dalam mendeteksi bug spasial (buffer overflow) dan temporal (use after free).

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

  • Menyetel register hardwarePSTATE.TCO dapat menonaktifkan pemeriksaan tag untuk sementara (contoh). Misalnya, saat menyalin rentang memori dengan konten tag yang tidak diketahui, atau mengatasi hambatan performa dalam loop panas.
  • Saat menggunakan M_HEAP_TAGGING_LEVEL_SYNC, handler error sistem memberikan informasi tambahan seperti rekaman aktivitas alokasi dan dealokasi. Fungsi ini memerlukan akses ke bit tag dan diaktifkan dengan meneruskan flag SA_EXPOSE_TAGBITS saat menyetel handler sinyal. Program apa pun yang menyetel handler sinyalnya sendiri dan mendelegasikan error yang tidak diketahui ke sistem direkomendasikan untuk 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.
Hal ini dapat dikontrol pada waktu booting menggunakan argumen command line 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 stack trace (default: on)
    • pengumpulan rekaman aktivitas stack juga memerlukan stack_depot_disable=off.
  • kasan.fault=[report|panic] - apakah hanya mencetak laporan, atau juga menyebabkan 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 pendeteksian bug di kemudian hari dalam produksi dapat dihindari.

Sebaiknya gunakan mode ASYNC dalam produksi. Hal ini memberikan 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 sekumpulan pengguna yang disampel.

Sebaiknya konfigurasi tingkat MTE pilihan khusus CPU untuk SoC. Mode asimetris biasanya memiliki karakteristik performa yang sama dengan ASYNC, dan hampir selalu lebih disukai. Inti dalam urutan kecil sering 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 mengetahui bug pengguna akhir. Untuk mengetahui info selengkapnya tentang proses debug kode native Android, lihat informasi di sini.

Komponen platform yang mendukung MTE

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

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

Target ini dipilih berdasarkan kriteria berikut:

  • Proses istimewa (didefinisikan sebagai proses yang memiliki akses ke sesuatu yang tidak dimiliki oleh domain SELinux unprivileged_app)
  • Memproses input yang tidak tepercaya (Aturan dua)
  • Perlambatan performa yang dapat diterima (perlambatan tidak menyebabkan 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, sebaiknya uji komponen ini menggunakan mode SYNC, untuk mendeteksi bug yang mudah diperbaiki, dan menilai dampak ASYNC terhadap performanya.
Pada masa mendatang, Android berencana memperluas daftar komponen sistem yang mengaktifkan MTE, yang dipandu oleh karakteristik performa desain hardware mendatang.