[libc] [llvm] Implement pkey_alloc/free/get/set/mprotect for x86_64 linux (PR #162362)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 7 13:07:11 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jackson Stogel (jtstogel)

<details>
<summary>Changes</summary>

This patch provides definitions for `pkey_*` functions for linux x86_64.

`alloc`, `free`, and `mprotect` are simple syscall wrappers. `pkey_set` and `pkey_get` modify architecture-specific registers. The logic for these live in architecture specific directories:

* `libc/src/sys/mman/linux/x86_64/pkey_common.h` has a real implementation
* `libc/src/sys/mman/linux/generic/pkey_common.h` contains stubs that just return `ENOSYS`.

This is my first addition to LLVM libc. It's likely I've missed something that needs updating -- ample feedback is welcome!

---

Patch is 30.82 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/162362.diff


22 Files Affected:

- (modified) libc/config/linux/x86_64/entrypoints.txt (+5) 
- (modified) libc/src/sys/mman/CMakeLists.txt (+35) 
- (modified) libc/src/sys/mman/linux/CMakeLists.txt (+75) 
- (added) libc/src/sys/mman/linux/generic/CMakeLists.txt (+9) 
- (added) libc/src/sys/mman/linux/generic/pkey_common.h (+25) 
- (added) libc/src/sys/mman/linux/pkey_alloc.cpp (+37) 
- (added) libc/src/sys/mman/linux/pkey_free.cpp (+35) 
- (added) libc/src/sys/mman/linux/pkey_get.cpp (+35) 
- (added) libc/src/sys/mman/linux/pkey_mprotect.cpp (+45) 
- (added) libc/src/sys/mman/linux/pkey_set.cpp (+35) 
- (added) libc/src/sys/mman/linux/x86_64/CMakeLists.txt (+10) 
- (added) libc/src/sys/mman/linux/x86_64/pkey_common.h (+71) 
- (added) libc/src/sys/mman/pkey_alloc.h (+20) 
- (added) libc/src/sys/mman/pkey_free.h (+20) 
- (added) libc/src/sys/mman/pkey_get.h (+20) 
- (added) libc/src/sys/mman/pkey_mprotect.h (+21) 
- (added) libc/src/sys/mman/pkey_set.h (+20) 
- (modified) libc/test/src/sys/mman/linux/CMakeLists.txt (+21) 
- (added) libc/test/src/sys/mman/linux/pkey_test.cpp (+241) 
- (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+75) 
- (modified) utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel (+1) 
- (modified) utils/bazel/llvm-project-overlay/libc/test/src/sys/mman/BUILD.bazel (+18) 


``````````diff
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 87b78a337b875..4c56d23d96877 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -264,6 +264,11 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.munmap
+    libc.src.sys.mman.pkey_alloc
+    libc.src.sys.mman.pkey_free
+    libc.src.sys.mman.pkey_get
+    libc.src.sys.mman.pkey_mprotect
+    libc.src.sys.mman.pkey_set
     libc.src.sys.mman.remap_file_pages
     libc.src.sys.mman.posix_madvise
     libc.src.sys.mman.shm_open
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 4d4c2ad376050..c7be1eddacb5e 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -86,6 +86,41 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.msync
 )
 
+add_entrypoint_object(
+  pkey_alloc
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pkey_alloc
+)
+
+add_entrypoint_object(
+  pkey_free
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pkey_free
+)
+
+add_entrypoint_object(
+  pkey_get
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pkey_get
+)
+
+add_entrypoint_object(
+  pkey_mprotect
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pkey_mprotect
+)
+
+add_entrypoint_object(
+  pkey_set
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pkey_set
+)
+
 add_entrypoint_object(
   remap_file_pages
   ALIAS
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 7181bb98a187f..1c79180cbcabb 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -1,3 +1,10 @@
+add_subdirectory(generic)
+set(ARCH_SUBDIRECTORY generic)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
+  add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
+  set(ARCH_SUBDIRECTORY ${LIBC_TARGET_ARCHITECTURE})
+endif()
+
 add_entrypoint_object(
   madvise
   SRCS
@@ -166,6 +173,74 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  pkey_alloc
+  SRCS
+    pkey_alloc.cpp
+  HDRS
+    ../pkey_alloc.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  pkey_free
+  SRCS
+    pkey_free.cpp
+  HDRS
+    ../pkey_free.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  pkey_get
+  SRCS
+    pkey_get.cpp
+  HDRS
+    ../pkey_get.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+    .${ARCH_SUBDIRECTORY}.pkey_common
+)
+
+add_entrypoint_object(
+  pkey_mprotect
+  SRCS
+    pkey_mprotect.cpp
+  HDRS
+    ../pkey_mprotect.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.sys.mman.mprotect
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  pkey_set
+  SRCS
+    pkey_set.cpp
+  HDRS
+    ../pkey_set.h
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+    .${ARCH_SUBDIRECTORY}.pkey_common
+)
+
 add_entrypoint_object(
   remap_file_pages
   SRCS
diff --git a/libc/src/sys/mman/linux/generic/CMakeLists.txt b/libc/src/sys/mman/linux/generic/CMakeLists.txt
new file mode 100644
index 0000000000000..42b6d96c8387e
--- /dev/null
+++ b/libc/src/sys/mman/linux/generic/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_header_library(
+  pkey_common
+  HDRS
+    pkey_common.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.__support.common
+    libc.src.__support.error_or
+)
diff --git a/libc/src/sys/mman/linux/generic/pkey_common.h b/libc/src/sys/mman/linux/generic/pkey_common.h
new file mode 100644
index 0000000000000..0811cfb77d4b0
--- /dev/null
+++ b/libc/src/sys/mman/linux/generic/pkey_common.h
@@ -0,0 +1,25 @@
+#ifndef LLVM_SYS_MMAN_LINUX_GENERIC_PKEY_COMMON_H_
+#define LLVM_SYS_MMAN_LINUX_GENERIC_PKEY_COMMON_H_
+
+#include "hdr/errno_macros.h" // For ENOSYS
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace pkey_common {
+
+LIBC_INLINE ErrorOr<int> pkey_get(int pkey) {
+  (void)pkey;
+  return Error(ENOSYS);
+}
+
+LIBC_INLINE ErrorOr<int> pkey_set(int pkey, unsigned int access_rights) {
+  (void)pkey;
+  (void)access_rights;
+  return Error(ENOSYS);
+}
+
+} // namespace pkey_common
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_SYS_MMAN_LINUX_GENERIC_PKEY_COMMON_H_
diff --git a/libc/src/sys/mman/linux/pkey_alloc.cpp b/libc/src/sys/mman/linux/pkey_alloc.cpp
new file mode 100644
index 0000000000000..baf32013bc5c7
--- /dev/null
+++ b/libc/src/sys/mman/linux/pkey_alloc.cpp
@@ -0,0 +1,37 @@
+//===---------- Linux implementation of the Linux pkey_alloc function -----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/pkey_alloc.h"
+
+#include "hdr/errno_macros.h"             // For ENOSYS
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pkey_alloc,
+                   (unsigned int flags, unsigned int access_rights)) {
+#if !defined(SYS_pkey_alloc)
+  libc_errno = ENOSYS;
+  return -1;
+#else
+  int ret =
+      LIBC_NAMESPACE::syscall_impl<int>(SYS_pkey_alloc, flags, access_rights);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  return static_cast<int>(ret);
+#endif
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/linux/pkey_free.cpp b/libc/src/sys/mman/linux/pkey_free.cpp
new file mode 100644
index 0000000000000..0228971bd10f6
--- /dev/null
+++ b/libc/src/sys/mman/linux/pkey_free.cpp
@@ -0,0 +1,35 @@
+//===---------- Linux implementation of the Linux pkey_free function ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/pkey_free.h"
+
+#include "hdr/errno_macros.h"             // For ENOSYS
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pkey_free, (int pkey)) {
+#if !defined(SYS_pkey_free)
+  libc_errno = ENOSYS;
+  return -1;
+#else
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pkey_free, pkey);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  return 0;
+#endif
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/linux/pkey_get.cpp b/libc/src/sys/mman/linux/pkey_get.cpp
new file mode 100644
index 0000000000000..623b7930c7a23
--- /dev/null
+++ b/libc/src/sys/mman/linux/pkey_get.cpp
@@ -0,0 +1,35 @@
+//===---------- Linux implementation of the Linux pkey_mprotect function --===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/pkey_get.h"
+
+#include "hdr/errno_macros.h" // For ENOSYS
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#if defined(LIBC_TARGET_ARCH_IS_X86_64)
+#include "src/sys/mman/linux/x86_64/pkey_common.h"
+#else
+#include "src/sys/mman/linux/generic/pkey_common.h"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pkey_get, (int pkey)) {
+  ErrorOr<int> ret = LIBC_NAMESPACE::pkey_common::pkey_get(pkey);
+  if (!ret.has_value()) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return ret.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/linux/pkey_mprotect.cpp b/libc/src/sys/mman/linux/pkey_mprotect.cpp
new file mode 100644
index 0000000000000..15c5d9db39b33
--- /dev/null
+++ b/libc/src/sys/mman/linux/pkey_mprotect.cpp
@@ -0,0 +1,45 @@
+//===---------- Linux implementation of the Linux pkey_mprotect function --===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/pkey_mprotect.h"
+
+#include "hdr/errno_macros.h" // For ENOSYS
+#include "hdr/types/size_t.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/sys/mman/mprotect.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pkey_mprotect,
+                   (void *addr, size_t len, int prot, int pkey)) {
+  // Fall back to mprotect if pkey is -1
+  // to maintain compatibility with kernel versions that don't support pkey.
+  if (pkey == -1) {
+    return LIBC_NAMESPACE::mprotect(addr, len, prot);
+  }
+
+#if !defined(SYS_pkey_mprotect)
+  libc_errno = ENOSYS;
+  return -1;
+#else
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pkey_mprotect, addr, len,
+                                              prot, pkey);
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return 0;
+#endif
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/linux/pkey_set.cpp b/libc/src/sys/mman/linux/pkey_set.cpp
new file mode 100644
index 0000000000000..7921443f688d3
--- /dev/null
+++ b/libc/src/sys/mman/linux/pkey_set.cpp
@@ -0,0 +1,35 @@
+//===---------- Linux implementation of the Linux pkey_mprotect function --===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/mman/pkey_set.h"
+
+#include "hdr/errno_macros.h" // For ENOSYS
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+#if defined(LIBC_TARGET_ARCH_IS_X86_64)
+#include "src/sys/mman/linux/x86_64/pkey_common.h"
+#else
+#include "src/sys/mman/linux/generic/pkey_common.h"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, pkey_set, (int pkey, unsigned int access_rights)) {
+  ErrorOr<int> ret = LIBC_NAMESPACE::pkey_common::pkey_set(pkey, access_rights);
+  if (!ret.has_value()) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return ret.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/linux/x86_64/CMakeLists.txt b/libc/src/sys/mman/linux/x86_64/CMakeLists.txt
new file mode 100644
index 0000000000000..1ce23af6dbd2a
--- /dev/null
+++ b/libc/src/sys/mman/linux/x86_64/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_header_library(
+  pkey_common
+  HDRS
+    pkey_common.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.stdint_proxy
+    libc.src.__support.common
+    libc.src.__support.error_or
+)
diff --git a/libc/src/sys/mman/linux/x86_64/pkey_common.h b/libc/src/sys/mman/linux/x86_64/pkey_common.h
new file mode 100644
index 0000000000000..bffa9feaed06c
--- /dev/null
+++ b/libc/src/sys/mman/linux/x86_64/pkey_common.h
@@ -0,0 +1,71 @@
+#ifndef LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_
+#define LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_
+
+#include "hdr/errno_macros.h" // For ENOSYS
+#include "hdr/stdint_proxy.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+
+#if !defined(LIBC_TARGET_ARCH_IS_X86_64)
+#error "Invalid include"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+namespace pkey_common {
+namespace internal {
+
+constexpr int MAX_KEY = 15;
+constexpr int KEY_MASK = 0x3;
+constexpr int BITS_PER_KEY = 2;
+
+// This will SIGILL on CPUs that don't support PKU / OSPKE,
+// but this case should never be reached as a prior pkey_alloc invocation
+// would have failed more gracefully.
+LIBC_INLINE uint32_t read_prku() {
+  uint32_t pkru = 0;
+  uint32_t edx = 0;
+  LIBC_INLINE_ASM("rdpkru" : "=a"(pkru), "=d"(edx) : "c"(0));
+  return pkru;
+}
+
+// This will SIGILL on CPUs that don't support PKU / OSPKE,
+// but this case should never be reached as a prior pkey_alloc invocation
+// would have failed more gracefully.
+LIBC_INLINE void write_prku(uint32_t pkru) {
+  LIBC_INLINE_ASM("wrpkru" : : "a"(pkru), "d"(0), "c"(0));
+}
+
+} // namespace internal
+
+// x86_64 implementation of pkey_get.
+// Returns the access rights for the given pkey on success, errno otherwise.
+LIBC_INLINE ErrorOr<int> pkey_get(int pkey) {
+  if (pkey < 0 || pkey > internal::MAX_KEY) {
+    return Error(EINVAL);
+  }
+
+  uint32_t pkru = internal::read_prku();
+  return (pkru >> (pkey * internal::BITS_PER_KEY)) & internal::KEY_MASK;
+}
+
+// x86_64 implementation of pkey_set.
+// Returns 0 on success, errno otherwise.
+LIBC_INLINE ErrorOr<int> pkey_set(int pkey, unsigned int access_rights) {
+  if (pkey < 0 || pkey > internal::MAX_KEY ||
+      access_rights > internal::KEY_MASK) {
+    return Error(EINVAL);
+  }
+
+  uint32_t pkru = internal::read_prku();
+  pkru &= ~(internal::KEY_MASK << (pkey * internal::BITS_PER_KEY));
+  pkru |=
+      ((access_rights & internal::KEY_MASK) << (pkey * internal::BITS_PER_KEY));
+  internal::write_prku(pkru);
+
+  return 0;
+}
+
+} // namespace pkey_common
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_
diff --git a/libc/src/sys/mman/pkey_alloc.h b/libc/src/sys/mman/pkey_alloc.h
new file mode 100644
index 0000000000000..c63c6a36c8021
--- /dev/null
+++ b/libc/src/sys/mman/pkey_alloc.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pkey_alloc function -----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_PKEY_ALLOC_H
+#define LLVM_LIBC_SRC_SYS_MMAN_PKEY_ALLOC_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pkey_alloc(unsigned int flags, unsigned int access_rights);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_PKEY_ALLOC_H
diff --git a/libc/src/sys/mman/pkey_free.h b/libc/src/sys/mman/pkey_free.h
new file mode 100644
index 0000000000000..a357e9b8c847b
--- /dev/null
+++ b/libc/src/sys/mman/pkey_free.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pkey_free function ------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_PKEY_FREE_H
+#define LLVM_LIBC_SRC_SYS_MMAN_PKEY_FREE_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pkey_free(int pkey);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_PKEY_FREE_H
diff --git a/libc/src/sys/mman/pkey_get.h b/libc/src/sys/mman/pkey_get.h
new file mode 100644
index 0000000000000..d41afe08ae371
--- /dev/null
+++ b/libc/src/sys/mman/pkey_get.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pkey_get function -------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_PKEY_GET_H
+#define LLVM_LIBC_SRC_SYS_MMAN_PKEY_GET_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pkey_get(int pkey);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_PKEY_GET_H
diff --git a/libc/src/sys/mman/pkey_mprotect.h b/libc/src/sys/mman/pkey_mprotect.h
new file mode 100644
index 0000000000000..4d19348ef09db
--- /dev/null
+++ b/libc/src/sys/mman/pkey_mprotect.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for pkey_mprotect function --------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_PKEY_MPROTECT_H
+#define LLVM_LIBC_SRC_SYS_MMAN_PKEY_MPROTECT_H
+
+#include "src/__support/macros/config.h"
+#include "hdr/types/size_t.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pkey_mprotect(void *addr, size_t len, int prot, int pkey);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_PKEY_MPROTECT_H
diff --git a/libc/src/sys/mman/pkey_set.h b/libc/src/sys/mman/pkey_set.h
new file mode 100644
index 0000000000000..55bafbd11d709
--- /dev/null
+++ b/libc/src/sys/mman/pkey_set.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pkey_set function -------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_MMAN_PKEY_SET_H
+#define LLVM_LIBC_SRC_SYS_MMAN_PKEY_SET_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pkey_set(int pkey, unsigned int access_rights);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_PKEY_SET_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index a362c1cf61cbc..721f89961f7c0 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -67,6 +67,27 @@ add_libc_unittest(
 )
 
 
+add_libc_unittest(
+  pkey_test
+  SUITE
+    libc_sys_mman_unittests
+  SRCS
+    pkey_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.signal_macros
+    libc.hdr.types.size_t
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.munmap
+    libc.src.sys.mman.pkey_alloc
+    libc.src.sys.mman.pkey_free
+    libc.src.sys.mman.pkey_get
+    libc.src.sys.mman.pkey_mprotect
+    libc.src.sys.mman.pkey_set
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 add_libc_unittest(
   posix_madvise_test
   SUITE
diff --git a/libc/test/src/sys/mman/linux/pkey_test.cpp b/libc/test/src/sys/mman/linux/pkey_test.cpp
new file mode 100644
index 0000000000000..9c6feae2d457b
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/pkey_test.cpp
@@ -0,0 +1,241 @@
+//===-- Unit tests for pkey functions -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/162362


More information about the llvm-commits mailing list