>From 9e18e6e7854d17aa1639d6145584df27f4b4f856 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 28 Apr 2018 17:25:41 +0000 Subject: [PATCH 16/16] Add memfd_create, mlock2 and pkey_* apis This patch adds support for the following linux syscalls and related interfaces following glibc: memfd_create (linux v3.17) mlock2 (linux v4.4) pkey_alloc (linux v4.9) pkey_free (linux v4.9) pkey_mprotect (linux v4.9) pkey_get (glibc 2.27) pkey_set (glibc 2.27) pkey_get / pkey_set are glibc apis, not syscalls, only an always failing generic implementation is provided in this patch, for pkey_ apis to be useful these will need target specific implementations. MLOCK_ONFAULT is moved under _GNU_SOURCE following glibc. Similar to glibc, mlock2 and pkey_mprotect have fallbacks to mlock and mprotect respectively in case of special arguments. --- arch/powerpc/bits/mman.h | 4 ++++ arch/powerpc64/bits/mman.h | 4 ++++ include/sys/mman.h | 24 +++++++++++++++++++++--- src/linux/memfd_create.c | 8 ++++++++ src/linux/mlock2.c | 11 +++++++++++ src/linux/pkey_alloc.c | 22 ++++++++++++++++++++++ src/linux/pkey_get.c | 9 +++++++++ src/linux/pkey_mprotect.c | 15 +++++++++++++++ src/linux/pkey_set.c | 9 +++++++++ 9 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/linux/memfd_create.c create mode 100644 src/linux/mlock2.c create mode 100644 src/linux/pkey_alloc.c create mode 100644 src/linux/pkey_get.c create mode 100644 src/linux/pkey_mprotect.c create mode 100644 src/linux/pkey_set.c diff --git a/arch/powerpc/bits/mman.h b/arch/powerpc/bits/mman.h index b3a675a8..23e18eb1 100644 --- a/arch/powerpc/bits/mman.h +++ b/arch/powerpc/bits/mman.h @@ -12,3 +12,7 @@ #define MCL_FUTURE 0x4000 #undef MCL_ONFAULT #define MCL_ONFAULT 0x8000 + +#ifdef _GNU_SOURCE +#define PKEY_DISABLE_EXECUTE 0x4 +#endif diff --git a/arch/powerpc64/bits/mman.h b/arch/powerpc64/bits/mman.h index b3a675a8..23e18eb1 100644 --- a/arch/powerpc64/bits/mman.h +++ b/arch/powerpc64/bits/mman.h @@ -12,3 +12,7 @@ #define MCL_FUTURE 0x4000 #undef MCL_ONFAULT #define MCL_ONFAULT 0x8000 + +#ifdef _GNU_SOURCE +#define PKEY_DISABLE_EXECUTE 0x4 +#endif diff --git a/include/sys/mman.h b/include/sys/mman.h index 19dd844e..643f882d 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -94,6 +94,20 @@ extern "C" { #define MADV_SOFT_OFFLINE 101 #endif +#ifdef _GNU_SOURCE +#define MREMAP_MAYMOVE 1 +#define MREMAP_FIXED 2 + +#define PKEY_DISABLE_ACCESS 0x1 +#define PKEY_DISABLE_WRITE 0x2 + +#define MLOCK_ONFAULT 0x01 + +#define MFD_CLOEXEC 0x0001U +#define MFD_ALLOW_SEALING 0x0002U +#define MFD_HUGETLB 0x0004U +#endif + #include void *mmap (void *, size_t, int, int, int, off_t); @@ -110,14 +124,18 @@ int mlockall (int); int munlockall (void); #ifdef _GNU_SOURCE -#define MREMAP_MAYMOVE 1 -#define MREMAP_FIXED 2 void *mremap (void *, size_t, size_t, int, ...); int remap_file_pages (void *, size_t, int, size_t, int); +int memfd_create (const char *, unsigned); +int mlock2 (const void *, size_t, unsigned); +int pkey_alloc (unsigned, unsigned); +int pkey_free (int); +int pkey_mprotect (void *, size_t, int, int); +int pkey_get (int); +int pkey_set (int, unsigned); #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define MLOCK_ONFAULT 0x01 int madvise (void *, size_t, int); int mincore (void *, size_t, unsigned char *); #endif diff --git a/src/linux/memfd_create.c b/src/linux/memfd_create.c new file mode 100644 index 00000000..1649fe55 --- /dev/null +++ b/src/linux/memfd_create.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE 1 +#include +#include "syscall.h" + +int memfd_create(const char *name, unsigned flags) +{ + return syscall(SYS_memfd_create, name, flags); +} diff --git a/src/linux/mlock2.c b/src/linux/mlock2.c new file mode 100644 index 00000000..e1235c46 --- /dev/null +++ b/src/linux/mlock2.c @@ -0,0 +1,11 @@ +#define _GNU_SOURCE 1 +#include +#include +#include "syscall.h" + +int mlock2(const void *addr, size_t len, unsigned flags) +{ + if (flags == 0) + return mlock(addr, len); + return syscall(SYS_mlock2, addr, len, flags); +} diff --git a/src/linux/pkey_alloc.c b/src/linux/pkey_alloc.c new file mode 100644 index 00000000..8027cd12 --- /dev/null +++ b/src/linux/pkey_alloc.c @@ -0,0 +1,22 @@ +#define _GNU_SOURCE 1 +#include +#include +#include "syscall.h" + +int pkey_alloc(unsigned flags, unsigned access) +{ +#ifdef SYS_pkey_alloc + return syscall(SYS_pkey_alloc, flags, access); +#else + return __syscall_ret(-ENOSYS); +#endif +} + +int pkey_free(int pkey) +{ +#ifdef SYS_pkey_free + return syscall(SYS_pkey_free, pkey); +#else + return __syscall_ret(-ENOSYS); +#endif +} diff --git a/src/linux/pkey_get.c b/src/linux/pkey_get.c new file mode 100644 index 00000000..d583fa9c --- /dev/null +++ b/src/linux/pkey_get.c @@ -0,0 +1,9 @@ +#define _GNU_SOURCE 1 +#include +#include +#include "syscall.h" + +int pkey_get(int pkey) +{ + return __syscall_ret(-ENOSYS); +} diff --git a/src/linux/pkey_mprotect.c b/src/linux/pkey_mprotect.c new file mode 100644 index 00000000..0a1f97ad --- /dev/null +++ b/src/linux/pkey_mprotect.c @@ -0,0 +1,15 @@ +#define _GNU_SOURCE 1 +#include +#include +#include "syscall.h" + +int pkey_mprotect(void *addr, size_t len, int prot, int pkey) +{ + if (pkey == -1) + return mprotect(addr, len, prot); +#ifdef SYS_pkey_mprotect + return syscall(SYS_pkey_mprotect, addr, len, prot, pkey); +#else + return __syscall_ret(-ENOSYS); +#endif +} diff --git a/src/linux/pkey_set.c b/src/linux/pkey_set.c new file mode 100644 index 00000000..addf8da5 --- /dev/null +++ b/src/linux/pkey_set.c @@ -0,0 +1,9 @@ +#define _GNU_SOURCE 1 +#include +#include +#include "syscall.h" + +int pkey_set(int pkey, unsigned access) +{ + return __syscall_ret(-ENOSYS); +} -- 2.16.3