Sebuah thread dapat memiliki virtual memory mapping yang writable tetapi tetap terhenti saat mencoba memodifikasi page tertentu. Mode write-protect userfaultfd Linux memungkinkan user space mendaftarkan range memori, menerapkan write protection pada page di range tersebut, lalu menerima event page fault ketika page yang diproteksi ditulis. VMA dapat tetap writable secara logis sementara state page table membentuk batas intersepsi yang lebih sempit.

Mekanisme ini bukan sistem otorisasi umum. userfaultfd adalah interface pengendalian memory fault. Relevansi keamanannya berasal dari posisi titik keputusan: write dapat ditangguhkan sebelum protected page berubah, sehingga handler terpisah dapat mencatat state, mengoordinasikan migrasi, mempertahankan batas snapshot, atau menahan progres dengan membiarkan fault belum terselesaikan.

Registrasi dan proteksi merupakan operasi terpisah

Objek userfaultfd lebih dulu menjalani handshake UFFDIO_API. User space meminta feature yang akan dipakai dan menerima capability feature serta ioctl yang disediakan kernel yang sedang berjalan. Range memori kemudian dapat didaftarkan dengan UFFDIO_REGISTER_MODE_WP.

Registrasi saja tidak selalu menerapkan write protection pada setiap page. Proteksi diterapkan melalui UFFDIO_WRITEPROTECT dan UFFDIO_WRITEPROTECT_MODE_WP terhadap range di dalam region yang telah terdaftar.

Secara konseptual, transisi state-nya adalah:

writable mapping
      |
UFFDIO_REGISTER_MODE_WP
      |
registered range
      |
UFFDIO_WRITEPROTECT + MODE_WP
      |
write-protected page-table state

Write berikutnya ke protected page menghasilkan pesan page fault dengan UFFD_PAGEFAULT_FLAG_WP; write fault juga membawa UFFD_PAGEFAULT_FLAG_WRITE. Pada mode sinkron, thread yang mengalami fault tetap terblokir sampai user space menyelesaikan kondisi tersebut.

Menghapus proteksi melepaskan writer yang terblokir

Handler menyelesaikan synchronous write-protect fault dengan menjalankan UFFDIO_WRITEPROTECT pada range terkait sementara UFFDIO_WRITEPROTECT_MODE_WP dinonaktifkan. Kernel memulihkan akses write untuk state yang diproteksi dan operasi yang terblokir dapat berlanjut.

Urutan tersebut membentuk titik koordinasi sebelum mutasi:

writer             kernel               handler
  |                   |                    |
  |---- write -------> |                    |
  |                 WP fault                |
  |                   |---- event --------> |
  |                   |                    |
  |                blocked          inspect / record
  |                   |                    |
  |                   |<--- unprotect -----|
  |<---- resume -------|                    |

Handler tidak menerima salinan write yang sudah selesai. Notifikasi muncul karena write menemui proteksi. Properti ini cocok untuk pelacakan state yang harus berjalan sebelum writer melanjutkan eksekusi.

Properti yang sama juga menciptakan ketergantungan liveness. Jika handler gagal menangani synchronous fault, writer dapat tetap terblokir. Desain yang menempatkan memori kritis di balik batas ini perlu memperlakukan ketersediaan handler, pengurasan event, dan urutan shutdown sebagai bagian dari model operasional.

Missing page memiliki semantik tersendiri

Write protection terhadap present page dan penanganan missing page merupakan dua hal berbeda. Sebuah range dapat didaftarkan sekaligus dengan UFFDIO_REGISTER_MODE_WP dan UFFDIO_REGISTER_MODE_MISSING, tetapi jalur fault yang dihasilkan tidak dapat dipertukarkan.

Pada anonymous memory, perilaku write-protect historis tidak menerapkan proteksi pada page-table entry yang belum ada. Write ke alamat yang belum populated karena itu dapat mengikuti missing-page path alih-alih menghasilkan write-protect event yang diharapkan. Kernel yang menyediakan UFFD_FEATURE_WP_UNPOPULATED dapat memperluas write protection ke unpopulated anonymous entry ketika feature tersebut diminta.

Perbedaan ini penting bagi policy yang mengasumsikan setiap write pertama akan melewati titik intersepsi yang sama. Asumsi tersebut hanya valid ketika memory type, registration mode, page population state, dan kernel feature yang dinegosiasikan mendukung perilaku itu.

Untuk missing-mode fault, user space dapat menyediakan isi page melalui operasi seperti UFFDIO_COPY atau memetakan zero page jika didukung. Saat missing mode dan write-protect mode digabungkan, aplikasi perlu mengatur secara eksplisit urutan populasi page serta apakah write protection dipertahankan atau dihapus.

Memory type dan capability kernel menentukan batas yang tersedia

Dukungan write-protect berkembang pada berbagai versi kernel dan memory type. Anonymous memory, shmem, dan hugetlbfs tidak memiliki dukungan historis yang identik. Software tidak aman jika hanya menyimpulkan capability dari string versi kernel; negosiasi feature UFFDIO_API tersedia untuk menyatakan interface aktual yang dapat digunakan proses.

Feature bit juga membedakan perilaku seperti write protection untuk shmem dan hugetlbfs, proteksi terhadap unpopulated anonymous entry, serta asynchronous write-protect tracking. Permintaan feature bit yang tidak didukung membuat negosiasi API gagal, bukan diam-diam mengganti perilaku dengan pendekatan yang lebih lemah.

Ini merupakan properti enforcement yang penting. Program yang memerlukan fault boundary tertentu sebaiknya gagal saat inisialisasi jika feature wajib tidak tersedia, bukan terus berjalan dengan asumsi memory tracking yang lebih lemah.

Akses ke userfaultfd juga dikendalikan policy

Pembuatan userfaultfd yang hanya menangani user-mode page fault dapat diminta dengan UFFD_USER_MODE_ONLY. Penanganan fault yang lebih luas melalui system call userfaultfd() tunduk pada policy kernel yang melibatkan CAP_SYS_PTRACE atau setting vm.unprivileged_userfaultfd.

Linux juga menyediakan /dev/userfaultfd pada sistem yang dikonfigurasi untuk itu. Akses ke device tersebut dapat dikendalikan melalui permission filesystem biasa, dan descriptor yang dibuat melalui interface itu tidak diatur oleh vm.unprivileged_userfaultfd dengan cara yang sama seperti jalur system call.

Aturan pembuatan ini terpisah dari registrasi write-protect. Kepemilikan writable mapping tidak otomatis berarti sebuah proses dapat membuat setiap kelas konteks userfaultfd. Deployment policy menentukan proses mana yang boleh membentuk mekanisme intersepsi tersebut.

Mode asynchronous mengubah arti enforcement

UFFD_FEATURE_WP_ASYNC mengubah write-protect mode dari mekanisme notifikasi blocking menjadi asynchronous dirty tracking. Pada mode ini, sebuah write menghapus state pelacakan write-protect dan kernel mengizinkan progres tanpa mengirim normal blocking event kepada handler.

Perbedaannya mendasar. Mode sinkron dapat menempatkan pekerjaan handler sebelum progres writer. Mode asynchronous mencatat bahwa write terjadi tanpa menempatkan keputusan user space pada critical path.

Sistem yang memakai asynchronous mode karena itu tidak dapat menyatakan bahwa monitor menyetujui setiap mutasi. State pelacakan page table dapat dipakai untuk mengidentifikasi page yang ditulis sejak proteksi diaktifkan, tetapi properti tersebut merupakan observasi, bukan mediasi per write.

Mediasi per page bukan transaction boundary aplikasi

Write-protect fault dihasilkan oleh akses memori pada granularitas page table. Mekanisme ini tidak mengetahui apakah instruction merupakan bagian dari transaksi database, operasi kriptografi, update objek pada tingkat bahasa, atau invariant yang melibatkan banyak page.

Satu operasi logis dapat menyentuh beberapa page dan menghasilkan beberapa fault. Beberapa thread juga dapat berkontensi pada protected range yang sama. Setelah proteksi dihapus, write berikutnya dapat berjalan tanpa event lain sampai range diproteksi kembali.

Karena itu, userfaultfd write protection paling kuat ketika protected unit dan policy re-arming dinyatakan secara eksplisit. Mekanisme ini dapat membentuk pre-write page boundary yang presisi, tetapi atomicity pada tingkat lebih tinggi tetap menjadi tanggung jawab aplikasi atau runtime yang mengoordinasikan page tersebut.

Properti keamanan bergantung pada pihak yang mengendalikan re-arming

Kernel menegakkan transisi page table dan fault delivery, tetapi user space menentukan kapan proteksi diterapkan dan kapan proteksi dihapus. Handler yang membuka proteksi pada range luas dapat mengizinkan lebih banyak mutasi berikutnya dibanding handler yang hanya melepas faulting page lalu segera mengaktifkan proteksi kembali.

Hal ini memisahkan mekanisme dari policy. userfaultfd menyediakan penghentian yang ditegakkan kernel terhadap write terpilih selama proteksi aktif. Interface ini tidak menentukan write mana yang sah, berapa lama proteksi tetap dilepas, atau state apa yang wajib dicatat sebelum progres dilanjutkan.

Batas yang dihasilkan bersifat kondisional tetapi berguna: selama synchronous write protection aktif pada page yang didukung, write yang cocok tidak dapat melewati state page table tersebut tanpa fault. Setelah user space menghapus proteksi, semantik writable mapping biasa kembali berlaku sampai proteksi diterapkan lagi.