$RodHat_
Syscall reference · Memory

memfd_create(2)

Create an anonymous RAM-backed file with no path, optionally sealable.

Since
Linux 3.17check your kernel →
glibc
glibc 2.27
System
Linux
Man page
memfd_create(2)

Synopsis

#define _GNU_SOURCE
#include <sys/mman.h>

int memfd_create(const char *name, unsigned int flags);

Rod's take

Every older way to hand a blob to another process has a name somebody can race: a temp file, a /dev/shm object you hoped you unlinked in time. memfd_create has no name. It's an fd backed by anonymous memory, and the only way in is the fd. Create it with MFD_ALLOW_SEALING, fill it, slap on SHRINK, GROW, WRITE and SEAL, and nobody holding a copy can change a byte, you included. Forget the flag at creation and you can't retrofit it. In the kernel since 3.17 and still mostly a Wayland secret.

Flags and arguments that matter

NameWhat it does
MFD_CLOEXECSet close-on-exec on the new descriptor.
MFD_ALLOW_SEALINGAllow fcntl(F_ADD_SEALS). Without it the file starts with F_SEAL_SEAL and can never be sealed.
MFD_HUGETLBLinux 4.14Back the file with hugetlbfs huge pages; pick size with MFD_HUGE_2MB, MFD_HUGE_1GB, etc.
F_SEAL_SHRINK / F_SEAL_GROWfcntl(2) seals that lock the file size against shrinking or growing.
F_SEAL_WRITEfcntl(2) seal blocking writes; can't be added while writable shared mappings exist.
F_SEAL_FUTURE_WRITEfcntl(2) seal blocking future writes while allowing existing writable mappings to remain.
F_SEAL_SEALfcntl(2) seal preventing any further seals from being added.

Errors you will actually hit

errnoMeaning
EINVALflags contained unknown bits, or name exceeded 249 bytes.
EFAULTname points to invalid memory.
EMFILEPer-process open file descriptor limit reached.
ENOMEMInsufficient memory to create the anonymous file.
EPERMMFD_HUGETLB requested without CAP_IPC_LOCK or hugetlb_shm_group membership.

Example

int fd = memfd_create("config", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0)
    err(1, "memfd_create");
if (ftruncate(fd, len) < 0 || write(fd, data, len) != (ssize_t)len)
    err(1, "fill memfd");

if (fcntl(fd, F_ADD_SEALS,
          F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0)
    err(1, "F_ADD_SEALS");
/* immutable now: hand it over with SCM_RIGHTS */

Trimmed from the full walkthrough in memfd_create and file sealing: an anonymous file nobody can modify (including you).

BSD equivalent

FreeBSD: memfd_create(2) (FreeBSD 13.0), an SHM_ANON shared memory object that supports MFD_ALLOW_SEALING. OpenBSD: none.

The long version, from the console

Sources

  1. memfd_create(2), man7.org
  2. shm_open(2), FreeBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.