{
  "slug": "file-sealing",
  "term": "Linux file sealing",
  "aliases": [
    "file seals",
    "memfd sealing"
  ],
  "definition": "Linux file sealing irreversibly restricts selected operations on a supported file, with restrictions shared by all descriptors referring to its inode.",
  "note": "Scope: F_ADD_SEALS adds restrictions and F_GET_SEALS reads them. F_SEAL_SEAL prevents further additions, rather than freezing content. Restrictions cannot be removed. [seals-api]\n\nWrites: F_SEAL_WRITE cannot be installed while a shared writable mapping exists. F_SEAL_FUTURE_WRITE allows earlier shared writable mappings to keep changing the file while blocking new ones and write calls. A pre-existing shared PROT_READ mapping from a writable descriptor can also block F_SEAL_WRITE: Linux counts potential write capability, not only current store permissions. [seals-capability] Private copy-on-write mappings remain distinct from writes to the backing object. [seals-api] [seals-mapping]\n\nSize: F_SEAL_SHRINK and F_SEAL_GROW control resizing separately from writes. Combining both with F_SEAL_WRITE constrains size and content through these APIs. Seals on volatile memfds do not create persistent storage or authenticate the data's origin. [seals-kernel]\n\nMapping order: changing an earlier shared mapping to PROT_READ does not necessarily remove its potential write capability. In the companion Linux 6.8 controls, it could be upgraded after FUTURE_WRITE and modify the file. A shared read-only mapping created after that seal could not be upgraded; the kernel clears VM_MAYWRITE at mapping creation. [seals-mapping] [mprotect-api]\n\nRead-only descriptors: a shared mapping from a separately reopened O_RDONLY descriptor could not be upgraded, but still saw writes through another descriptor before sealing. That reader did not prevent the writable descriptor from installing WRITE. Adding seals itself requires a writable descriptor. [seals-api] [mprotect-api]",
  "status": "shipping",
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-10-18",
  "advantages": [
    "Kernel enforcement can constrain a peer that holds a writable descriptor."
  ],
  "limitations": [
    "A receiver still needs to inspect the actual seal mask and validate the application's data format."
  ],
  "related": [
    "memfd-create",
    "memory-mapped-file",
    "file-truncation",
    "copy-on-write"
  ],
  "citations": [
    {
      "id": "seals-api",
      "title": "Linux man-pages: F_GET_SEALS / F_ADD_SEALS",
      "url": "https://man7.org/linux/man-pages/man2/F_ADD_SEALS.2const.html",
      "accessed": "2026-10-17"
    },
    {
      "id": "seals-kernel",
      "title": "Linux v6.12: memfd sealing implementation",
      "url": "https://github.com/torvalds/linux/blob/v6.12/mm/memfd.c",
      "accessed": "2026-10-17"
    },
    {
      "id": "seals-mapping",
      "title": "Linux v6.12: seal_check_write mapping checks",
      "url": "https://github.com/torvalds/linux/blob/v6.12/include/linux/mm.h",
      "accessed": "2026-10-17"
    },
    {
      "id": "seals-capability",
      "title": "Linux v6.12: shared mappings with potential write capability",
      "url": "https://github.com/torvalds/linux/blob/v6.12/include/linux/fs.h#L520-L547",
      "accessed": "2026-10-18"
    },
    {
      "id": "mprotect-api",
      "title": "Linux man-pages: mprotect(2), access changes and EACCES",
      "url": "https://man7.org/linux/man-pages/man2/mprotect.2.html",
      "accessed": "2026-10-18"
    }
  ],
  "provenance": [
    "The companion probe tests seven sequential cases on one host, not a concurrent interprocess protocol.",
    "The source review uses Linux v6.12 code to explain mechanisms; the measured kernel is recorded separately.",
    "Three additional mapping-capability controls and raw observations: https://hesela.dev/research/file-seal-capability.json; runnable source: https://hesela.dev/research/file-seal-capability.py."
  ]
}
