Seal Memfd Mengubah Memori Bersama Menjadi Kebijakan File Monotonik

Sebuah proses menyiapkan objek biner di memori, meneruskan file descriptor ke proses lain, lalu mengharapkan byte tetap stabil setelah validasi. Memori bersama biasa tidak menyediakan sifat tersebut dengan sendirinya: pemegang otoritas tulis lain dapat mengubah objek setelah pemeriksaan, mengubah ukurannya, atau mempertahankan mapping yang dapat ditulis. File seal Linux menyediakan kontrak yang lebih sempit. Seal menghapus operasi mutasi tertentu dari file yang mendukung sealing, dan seal yang berhasil ditambahkan tidak dapat dihapus kemudian.

Sifat monotonik tersebut berguna pada batas kepercayaan yang memakai memori bersama berbasis file. Namun batasannya juga tegas: memfd yang memiliki seal tidak otomatis bersifat immutable. Hasil akhirnya bergantung pada seal yang dipasang, waktu pemasangannya, dan mapping yang sudah ada.

Sealing merupakan properti inode, bukan flag descriptor

memfd_create() membuat file anonim dan mengembalikan descriptor yang dibuka untuk baca dan tulis. Objek ini memiliki semantik regular file tanpa memerlukan pathname persisten. Sealing tersedia saat objek dibuat dengan MFD_ALLOW_SEALING; tanpa flag tersebut, kumpulan seal awal mencakup F_SEAL_SEAL, sehingga seal tambahan tidak dapat dipasang.

Seal melekat pada inode file. Karena itu, descriptor yang merujuk objek yang sama melihat kumpulan seal yang sama. Meneruskan memfd melalui Unix-domain socket tidak membuat salinan tanpa seal, dan menduplikasi descriptor tidak membuat status sealing yang independen.

F_ADD_SEALS menambahkan pembatasan melalui fcntl(). Penambahan yang berhasil berlaku seketika dan tidak dapat dibalik. F_GET_SEALS menampilkan bit mask saat ini sehingga penerima dapat memverifikasi properti pada objek yang benar-benar diterimanya, bukan mempercayai metadata yang dikirim bersama objek tersebut.

Hal ini berbeda dari access mode pada descriptor. Descriptor read-only dapat membatasi operasi melalui descriptor itu, sementara descriptor writable lain mungkin masih ada di tempat lain. File seal mengubah operasi yang diizinkan pada objek dasar untuk semua pemegangnya.

Seal tulis dan seal ukuran menutup jalur mutasi yang berbeda

F_SEAL_WRITE memblokir penulisan isi file dan mencegah pembuatan shared writable mapping baru. Seal ini sendiri tidak melarang semua perubahan ukuran. F_SEAL_SHRINK mencegah pengurangan ukuran file, sedangkan F_SEAL_GROW mencegah penambahannya. Produsen yang memerlukan urutan byte stabil dengan ukuran tetap perlu memperlakukan mutasi isi dan mutasi ukuran sebagai dua dimensi kebijakan yang terpisah.

Pemisahan tersebut penting bagi parser yang memvalidasi offset atau panjang. Byte yang stabil belum cukup jika proses lain dapat melakukan truncate pada file backing setelah pemeriksaan batas. Mapping yang kemudian menjangkau bagian objek yang sudah dihapus dapat memicu fault, bukan mempertahankan asumsi saat validasi.

Sebaliknya, seal ukuran saja tidak membekukan byte yang sudah ada. Objek dengan panjang tetap masih dapat diubah di tempat jika mutasi tulis tidak dibatasi.

F_SEAL_SEAL mengunci kebijakan seal itu sendiri. Setelah terpasang, seal tambahan tidak dapat ditambahkan. Seal ini tepat dipasang setelah kumpulan seal yang diinginkan sudah lengkap. Pemasangan terlalu dini dapat secara permanen menghalangi penambahan pembatasan yang terlewat.

Writable mapping yang sudah ada membentuk batas waktu penting

Seal tulis terkuat tidak dapat langsung ditambahkan selama shared writable mapping untuk file tersebut masih ada. Penambahan F_SEAL_WRITE gagal dengan EBUSY pada kondisi itu. Produsen yang memerlukan write sealing penuh harus menghapus shared writable mapping yang bertentangan sebelum meminta seal.

Linux juga menyediakan F_SEAL_FUTURE_WRITE. Seal ini memblokir penulisan berikutnya melalui write() dan pembuatan writable shared mapping baru, tetapi shared writable mapping yang dibuat sebelum seal tetap dapat mengubah file.

Perbedaan tersebut disengaja dan memiliki konsekuensi keamanan. F_SEAL_FUTURE_WRITE dapat membiarkan produsen mempertahankan writable mapping yang sudah ada sambil membagikan descriptor yang tidak dapat memperoleh jalur tulis baru melalui penulisan biasa atau writable mapping baru. Seal ini tidak membuat byte stabil terhadap produsen yang masih memegang mapping lama.

Konsumen yang memerlukan input immutable tidak dapat menyamakan F_SEAL_FUTURE_WRITE dengan F_SEAL_WRITE. Seal pertama membatasi otoritas tulis yang muncul setelah pemasangan; seal kedua mensyaratkan tidak adanya shared writable mapping sebelum dapat berlaku.

Transfer descriptor mempertahankan pembatasan yang ditegakkan kernel

Arsitektur yang umum membuat dan mengisi memfd dalam satu proses, memasang seal, lalu meneruskan descriptor ke proses lain dengan SCM_RIGHTS. Penerima memperoleh referensi ke objek file yang sama. Status seal mengikuti objek tersebut karena seal bukan metadata aplikasi yang ditempelkan pada pesan IPC.

Pola ini dapat menghapus race antara pemeriksaan dan penggunaan dari protokol memori bersama. Konsumen dapat memeriksa F_GET_SEALS, memvalidasi isi, lalu beroperasi pada objek terseal yang sama tanpa menyalin data hanya untuk melindungi diri dari mutasi file berikutnya. Pernyataan tersebut berlaku jika seal yang diwajibkan benar-benar menutup setiap mutasi yang relevan terhadap asumsi konsumen.

Penerima tetap memerlukan kebijakan penerimaan. Penerima perlu memverifikasi bit seal yang diharapkan pada descriptor dan memvalidasi properti objek lain yang diwajibkan protokol. Klaim dari peer bahwa objek sudah terseal bukan pengganti pemeriksaan langsung terhadap objek melalui kernel.

Sealing juga tidak mengautentikasi pengirim atau menentukan objek mana yang berhak diberikan oleh pengirim. Otorisasi peer Unix socket, pemeriksaan tipe descriptor, framing protokol, dan kebijakan resource tingkat aplikasi tetap merupakan kontrol terpisah.

Seal membatasi mutasi file, bukan seluruh bentuk otoritas

Memfd dapat membawa data sensitif, material executable, state terserialisasi, atau isi lain, tetapi seal tidak mengubahnya menjadi mekanisme isolasi umum. Seal tidak mencabut akses baca yang sudah ada, tidak mencegah pemegang yang sah menyalin byte ke tempat lain, dan tidak menghapus descriptor yang sudah dibagikan.

Kebijakan eksekusi juga terpisah. Linux menyediakan F_SEAL_EXEC pada kernel yang mendukungnya. Semantiknya berkaitan dengan status executable dan mengimplikasikan seal tambahan, tetapi aplikasi perlu mengikat penggunaan tersebut pada antarmuka kernel yang sedang berjalan, bukan menganggapnya tersedia pada semua deployment.

Demikian pula, close-on-exec merupakan properti pewarisan descriptor, bukan seal. MFD_CLOEXEC dapat mencegah descriptor awal bertahan melewati execve(), tetapi pengaturan tersebut tidak membekukan isi file. Sealing dan kebijakan masa hidup descriptor menangani batas yang berbeda.

Sifat anonim memfd juga bukan jaminan kerahasiaan. Tidak adanya pathname persisten normal memang menghilangkan satu jalur namespace menuju objek, tetapi akses masih dapat mengalir melalui descriptor yang diwariskan, transfer descriptor eksplisit, serta mekanisme lain yang diizinkan sistem.

Jaminan yang berguna adalah pengurangan otoritas mutasi yang terverifikasi

Sealing memfd paling kuat saat protokol menyatakan properti yang diperlukan secara tepat. Payload immutable berukuran tetap memerlukan kumpulan seal yang berbeda dari buffer yang sengaja mempertahankan writable mapping pada sisi produsen. Penerima dapat memverifikasi properti tersebut langsung pada objek file sebelum mempercayai data yang berasal darinya.

Batas yang dihasilkan bersifat ringkas: seal secara monotonik menghapus operasi file tertentu, kernel menegakkannya pada semua referensi ke objek yang sama, dan kumpulan seal dapat diperiksa. Batas itu tidak mencakup semuanya. Identitas pengirim, provenance descriptor, kerahasiaan, pewarisan, serta otoritas yang tetap ada melalui mapping sebelumnya merupakan properti arsitektur di sekelilingnya.