1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

Linux: Implement interfaces for memory protection keys

This adds system call wrappers for pkey_alloc, pkey_free, pkey_mprotect,
and x86-64 implementations of pkey_get and pkey_set, which abstract over
the PKRU CPU register and hide the actual number of memory protection
keys supported by the CPU.  pkey_mprotect with a -1 key is implemented
using mprotect, so it will work even if the kernel does not support the
pkey_mprotect system call.

The system call wrapers use unsigned int instead of unsigned long for
parameters, so that no special treatment for x32 is needed.  The flags
argument is currently unused, and the access rights bit mask is limited
to two bits by the current PKRU register layout anyway.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer
2017-12-05 15:20:30 +01:00
parent da616c1496
commit 446d22e91d
50 changed files with 1179 additions and 4 deletions

View File

@ -33,6 +33,12 @@
# define MLOCK_ONFAULT 1U
# endif
/* Access rights for pkey_alloc. */
# ifndef PKEY_DISABLE_ACCESS
# define PKEY_DISABLE_ACCESS 0x1
# define PKEY_DISABLE_WRITE 0x2
# endif
__BEGIN_DECLS
/* Create a new memory file descriptor. NAME is a name for debugging.
@ -43,6 +49,28 @@ int memfd_create (const char *__name, unsigned int __flags) __THROW;
memory. FLAGS is a combination of the MLOCK_* flags above. */
int mlock2 (const void *__addr, size_t __length, unsigned int __flags) __THROW;
/* Allocate a new protection key, with the PKEY_DISABLE_* bits
specified in ACCESS_RIGHTS. The protection key mask for the
current thread is updated to match the access privilege for the new
key. */
int pkey_alloc (unsigned int __flags, unsigned int __access_rights) __THROW;
/* Update the access rights for the current thread for KEY, which must
have been allocated using pkey_alloc. */
int pkey_set (int __key, unsigned int __access_rights) __THROW;
/* Return the access rights for the current thread for KEY, which must
have been allocated using pkey_alloc. */
int pkey_get (int _key) __THROW;
/* Free an allocated protection key, which must have been allocated
using pkey_alloc. */
int pkey_free (int __key) __THROW;
/* Apply memory protection flags for KEY to the specified address
range. */
int pkey_mprotect (void *__addr, size_t __len, int __prot, int __pkey) __THROW;
__END_DECLS
#endif /* __USE_GNU */

View File

@ -111,8 +111,12 @@ enum
{
SEGV_MAPERR = 1, /* Address not mapped to object. */
# define SEGV_MAPERR SEGV_MAPERR
SEGV_ACCERR /* Invalid permissions for mapped object. */
SEGV_ACCERR, /* Invalid permissions for mapped object. */
# define SEGV_ACCERR SEGV_ACCERR
SEGV_BNDERR, /* Bounds checking failure. */
# define SEGV_BNDERR SEGV_BNDERR
SEGV_PKUERR /* Protection key checking failure. */
# define SEGV_PKUERR SEGV_PKUERR
};
/* `si_code' values for SIGBUS signal. */