memfd_secret(2)
πΈ NAME πΈ
okay so bestie, meet memfd_secret(2) β the syscall that makes an anonymous RAM-based file so you can get at secret memory regions π
β¨. Like, it literally creates an anonymous RAM-based file that gives you access to secret memory regions. Iconic behavior only.
π LIBRARY π
Standard C library (libc, -lc) π«Ά
β¨ SYNOPSIS β¨
#include <sys/syscall.h> /* Definition of SYS_* constants */
#include <unistd.h>
int syscall(SYS_memfd_secret, unsigned int flags);
bestie no cap β glibc does not give you a wrapper formemfd_secret(), so you gotta go throughsyscall(2). That's just the way it is π
π¦ DESCRIPTION π¦
So memfd_secret() creates an anonymous RAM-based file and hands you back a file descriptor pointing at it. The whole point of this file is that it lets you make and access memory regions with stronger protection than your usual RAM-based files and anonymous memory mappings. And the second every open reference to the file gets closed, it's automatically released β no cleanup era needed π
The initial size of the file is 0, so right after the call you should set the file size with ftruncate(2).
The memory areas backing the file you made with memfd_secret(2)? Only visible to the processes that hold the file descriptor. The memory region gets yanked out of the kernel page tables, and only the page tables of the processes holding the file descriptor map the corresponding physical memory. Which means β and this is the wild part β the pages in the region can't be accessed by the kernel itself, so like, pointers to the region can't be passed to system calls. The kernel is literally not invited π«π«Ά
These values may be bitwise ORed in flags to control what memfd_secret() does:
FD_CLOEXECβ sets the close-on-exec flag on the new file descriptor, which makes the region get removed from the process onexecve(2). Go read the description of theO_CLOEXECflag inopen(2)if you want the lore π
As its return value, memfd_secret() returns a new file descriptor that refers to an anonymous file. This fd is opened for both reading and writing (O_RDWR), and O_LARGEFILE is set for the file descriptor. Both. At once. Multitasking queen π
About fork(2) and execve(2) β the usual semantics apply to the fd that memfd_secret() made π§ A copy of the file descriptor gets inherited by the child produced by fork(2), and it refers to the same file. The file descriptor is preserved across execve(2), unless the close-on-exec flag has been set.
The memory region is locked into memory the same way it works with mlock(2), so it will never get written into swap, and hibernation is inhibited for as long as any memfd_secret() descriptions exist π΄β However, the implementation of memfd_secret() will not try to populate the whole range during the mmap(2) call that attaches the region into the process's address space β instead, the pages only actually get allocated as they are faulted in. Lazy allocation but make it secure β¨ The amount of memory allowed for memory mappings of the file descriptor obeys the same rules as mlock(2) and cannot exceed RLIMIT_MEMLOCK.
π RETURN VALUE π
On success, memfd_secret() returns a new file descriptor π₯³ On error, -1 is returned and errno is set to indicate the error. Rude but standard.
π ERRORS π
EINVALβflagsincluded unknown bits. Like, who are you even.EMFILEβ the per-process limit on the number of open file descriptors has been reached. Too many fds bestie, close some π«ENFILEβ the system-wide limit on the total number of open files has been reached. Not just you, it's everyone.ENOMEMβ there was insufficient memory to create a new anonymous file. The math wasn't mathing πENOSYSβmemfd_secret()is not implemented on this architecture, or has not been enabled on the kernel command-line withsecretmem_enable=1.
π STANDARDS π
Linux. periodt π
π°οΈ HISTORY π°οΈ
Linux 5.14 β¨
Before Linux 6.5, memfd_secret() was disabled by default and only available if the system administrator turned it on using the "secretmem.enable=y" kernel parameter. So yeah, it used to be invite-only ποΈ
π NOTES π
The memfd_secret() system call is designed to let a user-space process create a range of memory that is inaccessible to anybody else β kernel included. There is no 100% guarantee that the kernel won't be able to access memory ranges backed by memfd_secret() in any circumstances, but nevertheless, it's much harder to exfiltrate data from these regions. Not perfect, but it's giving protection π
memfd_secret() provides the following protections:
- Enhanced protection (in conjunction with all the other in-kernel attack prevention systems) against ROP attacks π‘οΈ The absence of any in-kernel primitive for accessing memory backed by
memfd_secret()means that a one-gadget ROP attack can't work to perform data exfiltration. The attacker would need to find enough ROP gadgets to reconstruct the missing page table entries, which significantly increases the difficulty of the attack, especially when other protections like the kernel stack size limit and address space layout randomization are in place. Good luck with that ig π - Prevent cross-process user-space memory exposures π« Once a region for a
memfd_secret()memory mapping is allocated, the user can't accidentally pass it into the kernel to be transmitted somewhere. The memory pages in this region cannot be accessed via the direct map, and they are disallowed inget_user_pages. Slay. - Harden against exploited kernel flaws πͺ In order to access memory areas backed by
memfd_secret(), a kernel-side attack would need to either walk the page tables and create new ones, or spawn a new privileged user-space process to perform secrets exfiltration usingptrace(2). That's a lot of work, bestie.
To prevent potential data leaks of memory regions backed by memfd_secret() from a hibernation image, hibernation is prevented when there are active memfd_secret() users π΄π«
π SEE ALSO π
fcntl(2), ftruncate(2), mlock(2), memfd_create(2), mmap(2), setrlimit(2)
okay that's the whole page bestie, go forth and be secretive π΅οΈβοΈπ this was brought to you by Linux man-pages 6.20, dated 2026-07-18, and yeah that's memfd_secret(2) β no cap, stay locked (in memory) π
β¨
π¦ 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: GPL-2.0-or-later
- Copyright 2014, Michael Kerrisk <mtk.manpages@gmail.com>
- Copyright 2014, David Herrmann <dh.herrmann@gmail.com>
- Copyright 2021, International Business Machines Corp
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms