F_GET_SEALS(2const)

πŸ’… F_GET_SEALS(2const) πŸ’…

okay so bestie. F_GET_SEALS, F_ADD_SEALS β€” get/add file seals. this is a 2const page, meaning it's one of those little constellation pages that hangs off a bigger syscall page. this one belongs to fcntl(2). no cap.


✨ LIBRARY ✨

Standard C library (libc, -lc). the classic. icon behavior.


πŸŽ€ SYNOPSIS πŸŽ€

#include <fcntl.h>

int fcntl(int fd, F_ADD_SEALS, int arg);
int fcntl(int fd, F_GET_SEALS);

see how it's all just fcntl() with different ops? yeah. that's the whole vibe. πŸ’–


πŸ¦‹ DESCRIPTION πŸ¦‹

file seals limit the set of allowed operations on a given file. for each seal you set on a file, a specific set of operations will fail with EPERM on that file from now on. the file is said to be sealed. like, locked in, permanently, no takebacks. the default set of seals depends on the type of the underlying file and filesystem. for an overview of file sealing, a discussion of its purpose, and some code examples, go read memfd_create(2) β€” she explains it all, fr fr.

currently, file seals can be applied only to a file descriptor returned by memfd_create(2) (and only if MFD_ALLOW_SEALING was employed). on other filesystems, all fcntl() operations that operate on seals will return EINVAL. so if you're not on a memfd, don't even try it, it's giving nothing. πŸ™ˆ

seals are a property of an inode. so all open file descriptors referring to the same inode share the same set of seals. and β€” big one β€” seals can never be removed, only added. that's the whole point. periodt. πŸ‘‘

F_ADD_SEALS

add the seals given in the bit-mask argument arg to the set of seals of the inode referred to by the file descriptor fd.

seals cannot be removed again. once this call succeeds, the seals are enforced by the kernel immediately. if the current set of seals includes F_SEAL_SEAL (see below), then this call will be rejected with EPERM. adding a seal that is already set is a no-op, in case F_SEAL_SEAL is not set already. in order to place a seal, the file descriptor fd must be writable. πŸ”₯

F_GET_SEALS

return (as the function result) the current set of seals of the inode referred to by fd. if no seals are set, 0 is returned. if the file does not support sealing, -1 is returned and errno is set to EINVAL.

🌸 the seals themselves 🌸

the following seals are available:

🌟 F_SEAL_SEAL

if this seal is set, any further call to fcntl() with F_ADD_SEALS fails with the error EPERM. therefore, this seal prevents any modifications to the set of seals itself. if the initial set of seals of a file includes F_SEAL_SEAL, then this effectively causes the set of seals to be constant and locked. it's the seal that seals the seals. main character energy honestly. πŸ’…

🌟 F_SEAL_SHRINK

if this seal is set, the file in question cannot be reduced in size. this affects open(2) with the O_TRUNC flag as well as truncate(2) and ftruncate(2). those calls fail with EPERM if you try to shrink the file in question. increasing the file size is still possible. so: no shrinking, only growing. we love a growth mindset. πŸ¦‹

🌟 F_SEAL_GROW

if this seal is set, the size of the file in question cannot be increased. this affects write(2) beyond the end of the file, truncate(2), ftruncate(2), and fallocate(2). these calls fail with EPERM if you use them to increase the file size. if you keep the size or shrink it, those calls still work as expected.

🌟 F_SEAL_WRITE

if this seal is set, you cannot modify the contents of the file. note that shrinking or growing the size of the file is still possible and allowed β€” so yeah, this seal is normally used in combination with one of the other seals. this seal affects write(2) and fallocate(2) (only in combination with the FALLOC_FL_PUNCH_HOLE flag). those calls fail with EPERM if this seal is set. furthermore, trying to create new shared, writable memory-mappings via mmap(2) will also fail with EPERM.

🚨 bestie listen. using the F_ADD_SEALS operation to set the F_SEAL_WRITE seal fails with EBUSY if any writable, shared mapping exists. such mappings must be unmapped before you can add this seal. furthermore, if there are any asynchronous I/O operations (io_submit(2)) pending on the file, all outstanding writes will be discarded. like, gone. ✨

🌟 F_SEAL_FUTURE_WRITE (since Linux 5.1)

the effect of this seal is similar to F_SEAL_WRITE, but the contents of the file can still be modified via shared writable mappings that were created prior to the seal being set. any attempt to create a new writable mapping on the file via mmap(2) will fail with EPERM. likewise, an attempt to write to the file via write(2) will fail with EPERM.

using this seal, one process can create a memory buffer that it can continue to modify while sharing that buffer on a "read-only" basis with other processes. it's giving generous tbh. 🫢

🌟 F_SEAL_EXEC (since Linux 6.3)

if this seal is set, the execute mode bits of the file cannot be modified. attempting to change the execute mode bits via fchmod(2) or similar will fail with EPERM. this results in a memfd that is either permanently executable or permanently not executable. binary. iconic.

adding this seal implicitly adds F_SEAL_GROW, F_SEAL_SHRINK, F_SEAL_WRITE, and F_SEAL_FUTURE_WRITE. this ensures that the executable code is not writeable. all the pre-requisites to add the implied seals must be met to successfully add F_SEAL_EXEC. πŸ‘‘


⭐ RETURN VALUE ⭐

F_GET_SEALS a bit mask identifying the seals that have been set for the inode referred to by fd.

F_ADD_SEALS zero.

on error, -1 is returned, and errno is set to indicate the error.


πŸ’€ ERRORS πŸ’€

see fcntl(2).

  • EBUSY β€” op is F_ADD_SEALS, arg includes F_SEAL_WRITE, and there exists a writable, shared mapping on the file referred to by fd.
  • EINVAL β€” op is F_ADD_SEALS and arg includes an unrecognized sealing bit.
  • EINVAL β€” the filesystem containing the inode referred to by fd does not support sealing.
  • EPERM β€” op was F_ADD_SEALS, but fd was not open for writing or the current set of seals on the file already includes F_SEAL_SEAL.

🌈 STANDARDS 🌈

Linux. that's it. that's the standard. 😌


πŸŽ€ HISTORY πŸŽ€

Linux 3.17.


πŸ‘‘ SEE ALSO πŸ‘‘

fcntl(2)


and that's the whole page bestie!! you now know more about file seals than like 97% of people at your school, iykyk. go seal something. πŸ¦‹βœ¨πŸ’–

this was Linux man-pages 6.20, dated 2026-06-04 β€” from the F_GET_SEALS(2const) page. mwah. πŸ’…

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms