Sebuah memfd dapat dimulai sebagai anonymous file yang writable lalu menolak kelas mutasi tertentu melalui seal yang ditegakkan kernel. Transisi ini melekat pada inode, bukan pada satu descriptor, sehingga proses tidak dapat mempertahankan duplicate descriptor tanpa pembatasan untuk melewati seal yang dipasang melalui referensi lain.
Sifat tersebut berbeda dari memberikan descriptor dengan mode akses yang lebih sempit kepada komponen lain. Mode akses descriptor membatasi satu open file description. Seal mengubah operasi yang diizinkan kernel terhadap file itu sendiri, termasuk operasi melalui descriptor lain yang merujuk inode yang sama.
File ada tanpa pathname normal
memfd_create() mengembalikan file descriptor untuk anonymous file. File tersebut memiliki properti seperti file biasa yang relevan untuk IPC: dapat diubah ukurannya, dibaca, ditulis, dipetakan ke memori, diduplikasi, diwariskan, dan dikirim melalui Unix domain socket.
Nama memfd yang diberikan bersifat diagnostik, bukan entry namespace untuk lookup pathname biasa. Lifetime file mengikuti referensinya. Ketika tidak ada descriptor, mapping, atau referensi kernel lain yang mempertahankannya, storage dapat direklamasi.
Kombinasi ini cocok untuk data yang membutuhkan semantik file tanpa publikasi pada direktori filesystem. Producer dapat membangun payload, memetakannya untuk akses, lalu mengirim descriptor alih-alih menyalin payload ke temporary file yang memiliki pathname.
Sealing bersifat opsional. Caller yang ingin menambahkan seal biasa membuat memfd dengan MFD_ALLOW_SEALING. Tanpa izin tersebut, state seal awal mencegah penambahan seal berikutnya.
Seal berada pada inode
Linux menyediakan file seal melalui operasi fcntl(). F_ADD_SEALS menambahkan pembatasan, sedangkan F_GET_SEALS melaporkan set yang aktif.
Batas identitas penting berada pada inode. Jika dua descriptor merujuk inode memfd yang sama, keduanya melihat seal yang sama. Mengirim descriptor ke proses lain tidak membuat salinan file tanpa seal. Menduplikasi descriptor juga tidak membuatnya.
Sifat ini menjadikan sealing sebagai kontrak shared object. Producer dapat mengisi memfd lalu membatasi mutasi berikutnya sebelum mentransfernya. Receiver dapat memeriksa seal set dan menentukan operasi yang akan ditolak kernel untuk file tersebut.
Kontrak ini monotonic. Seal dapat ditambahkan tetapi tidak dapat dihapus. F_SEAL_SEAL menutup seal set itu sendiri; setelah aktif, upaya menambah seal lain akan gagal. Protokol karena itu perlu membedakan file yang baru dibatasi sebagian dari file yang set pembatasannya sudah difinalisasi.
Batas ukuran dan batas byte merupakan hal terpisah
F_SEAL_SHRINK mencegah operasi yang mengurangi ukuran file. F_SEAL_GROW mencegah operasi yang menambah ukurannya. Keduanya tidak membuat byte yang sudah ada menjadi immutable dengan sendirinya.
Pemisahan ini penting untuk shared buffer dengan ukuran tetap. Producer dapat membekukan ukuran sambil tetap mengizinkan write di dalam rentang yang ada, atau menggabungkan size seal dengan write restriction ketika payload harus menjadi immutable.
Ukuran tetap tidak sama dengan isi tetap. Tanpa write seal, operasi yang menimpa byte dalam extent yang ada dapat tetap valid walaupun pertumbuhan dan penyusutan diblokir.
Seal set terdiri dari beberapa constraint yang berbeda, bukan satu bit read-only generik.
F_SEAL_WRITE memiliki prasyarat mapping
F_SEAL_WRITE memblokir write dan mencegah pembuatan shared writable mapping baru. Seal ini juga mencegah operasi perubahan ukuran yang termasuk dalam semantiknya.
Seal tidak dapat begitu saja mencabut shared writable mapping yang sudah ada. Jika mapping seperti itu masih aktif ketika proses mencoba menambahkan F_SEAL_WRITE, operasi gagal dengan EBUSY. Writable shared mapping harus dilepas sebelum seal dapat dipasang.
Batas ini penting pada protokol yang mempublikasikan buffer sebagai immutable. Producer tidak dapat mempertahankan shared writable mapping, memasang F_SEAL_WRITE, lalu menganggap mapping tersebut diam-diam berubah menjadi read-only. Linux menolak transisi itu.
Urutan publikasi ringkas memiliki transisi state yang terlihat:
int fd = memfd_create("payload", MFD_ALLOW_SEALING | MFD_CLOEXEC);
/* size and populate fd */
munmap(shared_writer, length);
fcntl(fd, F_ADD_SEALS,
F_SEAL_WRITE | F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);Kode produksi tetap harus memeriksa setiap return value dan menangani setup parsial. Contoh tersebut hanya menunjukkan batas semantik: shared writable mapping yang masih aktif tidak kompatibel dengan pemasangan full write seal.
Future-write sealing mempertahankan writer yang sudah ada
Linux juga menyediakan F_SEAL_FUTURE_WRITE. Seal ini menolak write() berikutnya dan upaya berikutnya untuk membuat writable mapping, sementara shared writable mapping yang sudah ada tetap dapat memodifikasi file.
Bentuk protokolnya berbeda dari F_SEAL_WRITE. Proses dapat mempertahankan mapping yang sudah writable sebelum seal dan terus memperbaruinya, sementara consumer berikutnya dicegah memperoleh writable mapping baru atau menulis melalui operasi write biasa.
Hasilnya bukan immutability umum. Existing writable shared mapping tetap menjadi jalur mutasi. Menganggap F_SEAL_FUTURE_WRITE setara dengan F_SEAL_WRITE akan melebihkan jaminannya.
Transfer descriptor tidak otomatis mentransfer trust
Sealed memfd dapat dikirim antarproses melalui descriptor passing pada Unix domain socket. Receiver memperoleh descriptor untuk file yang sama, termasuk state seal-nya.
Pemeriksaan seal berguna pada batas IPC, tetapi tidak mengautentikasi sender, memvalidasi struktur payload, atau membuktikan bahwa receiver memperoleh objek yang dimaksud. Properti tersebut berada pada protokol di sekelilingnya.
Receiver perlu memeriksa seal set aktual, bukan menyimpulkannya dari konvensi. Protokol yang mensyaratkan isi immutable dengan ukuran tetap dapat menolak memfd jika seal yang diwajibkan tidak ada. Jika finality juga penting, protokol dapat mensyaratkan F_SEAL_SEAL.
Seal menyatakan batas mutasi. Seal tidak menyatakan validitas schema, provenance, confidentiality, atau authorization.
Memory mapping tetap mengikuti semantik file
Memfd dapat dipetakan karena merupakan file object, dan sealing berinteraksi langsung dengan permission mapping. Jika kernel mengizinkan shared writable mapping, perubahan melalui mapping tersebut memengaruhi isi file.
Private mapping memiliki semantik berbeda. Perubahan MAP_PRIVATE merupakan copy-on-write pada mapping dan tidak menulis perubahan private itu kembali ke file. Consumer karena itu dapat membuat private writable memory dari isi file immutable tanpa memperoleh jalur untuk memutasi shared memfd object.
Perbedaannya terletak antara mutability virtual memory suatu proses dan mutability shared file. Seal membatasi yang kedua.
Sealing mempersempit race tanpa menggantikan state protokol
Protokol userspace dapat mengirim pesan bahwa buffer sudah final lalu mengandalkan semua participant untuk berhenti menulis. Konvensi tersebut memiliki race surface karena writer lama masih dapat memutasi objek setelah proses lain menerima pesan final.
Write seal yang berhasil memindahkan invariant spesifik itu ke kernel. Setelah seal terpasang, operasi yang dilarang akan gagal walaupun sebuah komponen masih menyimpan descriptor yang diterima sebelumnya.
Jaminan tetap dimulai pada titik yang presisi. Sebelum pemasangan seal berhasil, file masih dapat dimutasi melalui jalur yang masih diizinkan. Consumer yang menerima descriptor sebelum producer selesai memasang seal dapat melihat state berbeda dari consumer yang menerimanya sesudahnya.
Ordering karena itu tetap menjadi bagian dari desain IPC. Sealing menyediakan batas mutasi durable untuk file object; protokol menentukan kapan batas tersebut harus ada relatif terhadap transfer descriptor dan konsumsi payload.
Linux memfd seals paling berguna ketika shared file perlu berpindah dari fase konstruksi ke fase terbatas tanpa hanya bergantung pada perilaku kooperatif. Cakupannya spesifik: seal membatasi mutasi file tertentu pada inode, berlaku di seluruh referensi ke inode tersebut, dan irreversible setelah ditambahkan. Seal tidak mengubah arbitrary shared memory menjadi data immutable dan tidak menggantikan aturan identity, validation, atau ordering di sekitar file.