[libc-commits] [libc] [libc] Implement the linux-specific memfd_create syscall wrapper (PR #197439)
Pavel Labath via libc-commits
libc-commits at lists.llvm.org
Wed May 13 06:24:33 PDT 2026
https://github.com/labath created https://github.com/llvm/llvm-project/pull/197439
I'm using the MFD constants from the kernel header as that's what was done for mmap, though it would be relatively simple to declare these ourselves, as they are not architecture-dependent.
>From a5eea9a5cb19f9757bab718ece6f2d1d48589fff Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Wed, 13 May 2026 12:44:40 +0000
Subject: [PATCH] [libc] Implement the linux-specific memfd_create syscall
wrapper
I'm using the MFD constants from the kernel header as that's what was done
for mmap, though it would be simple enough declare these ourselves, as
they are not architecture-dependent.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/arm/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
.../llvm-libc-macros/sys-mman-macros.h | 4 ++
libc/include/sys/mman.yaml | 7 +++
.../linux/syscall_wrappers/CMakeLists.txt | 12 +++++
.../linux/syscall_wrappers/memfd_create.h | 36 ++++++++++++++
libc/src/sys/mman/CMakeLists.txt | 7 +++
libc/src/sys/mman/linux/CMakeLists.txt | 11 +++++
libc/src/sys/mman/linux/memfd_create.cpp | 31 ++++++++++++
libc/src/sys/mman/memfd_create.h | 25 ++++++++++
libc/test/src/sys/mman/linux/CMakeLists.txt | 21 ++++++++
.../src/sys/mman/linux/memfd_create_test.cpp | 48 +++++++++++++++++++
14 files changed, 206 insertions(+)
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/memfd_create.h
create mode 100644 libc/src/sys/mman/linux/memfd_create.cpp
create mode 100644 libc/src/sys/mman/memfd_create.h
create mode 100644 libc/test/src/sys/mman/linux/memfd_create_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index e62bc67e2d5ca..f7e40c1a142fe 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -256,6 +256,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/mman.h entrypoints
libc.src.sys.mman.madvise
+ libc.src.sys.mman.memfd_create
libc.src.sys.mman.mincore
libc.src.sys.mman.mlock
libc.src.sys.mman.mlock2
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 1c4dd1a4cb879..906f36d45e337 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -177,6 +177,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.ioctl.ioctl
# sys/mman.h entrypoints
+ libc.src.sys.mman.memfd_create
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index d1c52dffdb6e7..bf2fb014f4f77 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -256,6 +256,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/mman.h entrypoints
libc.src.sys.mman.madvise
+ libc.src.sys.mman.memfd_create
libc.src.sys.mman.mincore
libc.src.sys.mman.mlock
libc.src.sys.mman.mlock2
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 73b4b3fcd191f..2a6a79cfa77de 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -262,6 +262,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/mman.h entrypoints
libc.src.sys.mman.madvise
+ libc.src.sys.mman.memfd_create
libc.src.sys.mman.mincore
libc.src.sys.mman.mlock
libc.src.sys.mman.mlock2
diff --git a/libc/include/llvm-libc-macros/sys-mman-macros.h b/libc/include/llvm-libc-macros/sys-mman-macros.h
index a6dc6d96b5b79..bc9f783d84a40 100644
--- a/libc/include/llvm-libc-macros/sys-mman-macros.h
+++ b/libc/include/llvm-libc-macros/sys-mman-macros.h
@@ -18,6 +18,10 @@
#error "cannot use <sys/mman.h> without proper system headers."
#endif
+#if __has_include(<linux/memfd.h>)
+#include <linux/memfd.h>
+#endif
+
// Some posix standard flags may not be defined in system headers.
// Posix mmap flags.
#ifndef MAP_FAILED
diff --git a/libc/include/sys/mman.yaml b/libc/include/sys/mman.yaml
index 6adc2c2d5bfa6..f14a90436b791 100644
--- a/libc/include/sys/mman.yaml
+++ b/libc/include/sys/mman.yaml
@@ -19,6 +19,13 @@ functions:
- type: void *
- type: size_t
- type: int
+ - name: memfd_create
+ standards:
+ - Linux
+ return_type: int
+ arguments:
+ - type: const char *
+ - type: unsigned int
- name: mincore
standards:
- Linux
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index bbe76fece3bdd..8d0acca011bec 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -198,6 +198,18 @@ add_header_library(
libc.include.sys_syscall
)
+add_header_library(
+ memfd_create
+ HDRS
+ memfd_create.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.include.sys_syscall
+)
+
add_header_library(
mmap
HDRS
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/memfd_create.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/memfd_create.h
new file mode 100644
index 0000000000000..e748c3c6fb80d
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/memfd_create.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// ErrorOr-returning syscall wrapper for memfd_create.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MEMFD_CREATE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MEMFD_CREATE_H
+
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> memfd_create(const char *name, unsigned int flags) {
+ int ret = syscall_impl<int>(SYS_memfd_create, name, flags);
+ if (ret < 0)
+ return Error(-ret);
+ return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MEMFD_CREATE_H
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index c7be1eddacb5e..ca18fe36449da 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -9,6 +9,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.madvise
)
+add_entrypoint_object(
+ memfd_create
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.memfd_create
+)
+
add_entrypoint_object(
mmap
ALIAS
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 6cafa9ba45c1a..e8d9ed384c9b0 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -18,6 +18,17 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ memfd_create
+ SRCS
+ memfd_create.cpp
+ HDRS
+ ../memfd_create.h
+ DEPENDS
+ libc.src.__support.OSUtil.linux.syscall_wrappers.memfd_create
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
mmap
SRCS
diff --git a/libc/src/sys/mman/linux/memfd_create.cpp b/libc/src/sys/mman/linux/memfd_create.cpp
new file mode 100644
index 0000000000000..e3e1e00034e1a
--- /dev/null
+++ b/libc/src/sys/mman/linux/memfd_create.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of the memfd_create function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/memfd_create.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/memfd_create.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, memfd_create, (const char *name, unsigned int flags)) {
+ ErrorOr<int> result = linux_syscalls::memfd_create(name, flags);
+ if (!result) {
+ libc_errno = result.error();
+ return -1;
+ }
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/memfd_create.h b/libc/src/sys/mman/memfd_create.h
new file mode 100644
index 0000000000000..eefdae3e29d7e
--- /dev/null
+++ b/libc/src/sys/mman/memfd_create.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for memfd_create function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_MEMFD_CREATE_H
+#define LLVM_LIBC_SRC_SYS_MMAN_MEMFD_CREATE_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int memfd_create(const char *name, unsigned int flags);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_MEMFD_CREATE_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index b73212d0c322f..29d97cbfe7018 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -229,3 +229,24 @@ add_libc_unittest(
libc.test.UnitTest.ErrnoCheckingTest
libc.test.UnitTest.ErrnoSetterMatcher
)
+
+add_libc_unittest(
+ memfd_create_test
+ SUITE
+ libc_sys_mman_unittests
+ SRCS
+ memfd_create_test.cpp
+ DEPENDS
+ libc.hdr.fcntl_macros
+ libc.hdr.sys_mman_macros
+ libc.include.llvm-libc-macros.file_seek_macros
+ libc.include.sys_mman
+ libc.src.__support.CPP.scope
+ libc.src.errno.errno
+ libc.src.fcntl.fcntl
+ libc.src.sys.mman.memfd_create
+ libc.src.unistd.close
+ libc.src.unistd.lseek
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/mman/linux/memfd_create_test.cpp b/libc/test/src/sys/mman/linux/memfd_create_test.cpp
new file mode 100644
index 0000000000000..13c1c920e4009
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/memfd_create_test.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for memfd_create.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_mman_macros.h"
+#include "include/llvm-libc-macros/file-seek-macros.h"
+#include "src/__support/CPP/scope.h"
+#include "src/fcntl/fcntl.h"
+#include "src/sys/mman/memfd_create.h"
+#include "src/unistd/close.h"
+#include "src/unistd/lseek.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcMemfdCreateTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcMemfdCreateTest, Basic) {
+ int fd;
+ ASSERT_THAT(fd = LIBC_NAMESPACE::memfd_create("test_memfd", MFD_CLOEXEC),
+ returns(GE(0)).with_errno(EQ(0)));
+ LIBC_NAMESPACE::cpp::scope_exit close_fd(
+ [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
+
+ int flag;
+ ASSERT_THAT(flag = LIBC_NAMESPACE::fcntl(fd, F_GETFD),
+ returns(GE(0)).with_errno(EQ(0)));
+ EXPECT_NE(flag & FD_CLOEXEC, 0);
+
+ ASSERT_THAT(LIBC_NAMESPACE::lseek(fd, 0, SEEK_END), Succeeds(off_t(0)));
+}
+
+TEST_F(LlvmLibcMemfdCreateTest, ErrorHandling) {
+ // Passing invalid flags should cause EINVAL
+ ASSERT_THAT(LIBC_NAMESPACE::memfd_create("test_memfd", 0x80000000),
+ Fails(EINVAL));
+}
More information about the libc-commits
mailing list