When a page is mapped using mmap
, page protection flags can be specified using the protection flags argument. See Memory-mapped I/O.
The operating system may keep track of these flags separately even if the underlying hardware treats them the same for the purposes of access checking (as happens with PROT_READ
and PROT_EXEC
on some platforms). On GNU systems, PROT_EXEC
always implies PROT_READ
, so that users can view the machine code which is executing on their system.
After allocation, protection flags can be changed using the mprotect
function.
If the mprotect
function is used to make a region of memory inaccessible by specifying the PROT_NONE
protection flag and access is later restored, the memory retains its previous contents.
On some systems, it may not be possible to specify additional flags which were not present when the mapping was first created. For example, an attempt to make a region of memory executable could fail if the initial protection flags were ‘PROT_READ | PROT_WRITE’.
In general, the mprotect
function can be used to change any process memory, no matter how it was allocated. However, portable use of the function requires that it is only used with memory regions returned by mmap
or mmap64
.
On some systems, further restrictions can be added to specific pages using memory protection keys. These restrictions work as follows:
pkey_alloc
function, and applied to pages using pkey_mprotect
.pkey_set
and pkey_get
functions.PROT_
* protection flags set by mprotect
or pkey_mprotect
.New threads and subprocesses inherit the access rights of the current thread. If a protection key is allocated subsequently, existing threads (except the current) will use an unspecified system default for the access rights associated with newly allocated keys.
Upon entering a signal handler, the system resets the access rights of the current thread so that pages with the default key can be accessed, but the access rights for other protection keys are unspecified.
Applications are expected to allocate a key once using pkey_alloc
, and apply the key to memory regions which need special protection with pkey_mprotect
:
int key = pkey_alloc (0, PKEY_DISABLE_ACCESS); if (key < 0) /* Perform error checking, including fallback for lack of support. */ ...; /* Apply the key to a special memory region used to store critical data. */ if (pkey_mprotect (region, region_length, PROT_READ | PROT_WRITE, key) < 0) ...; /* Perform error checking (generally fatal). */
If the key allocation fails due to lack of support for memory protection keys, the pkey_mprotect
call can usually be skipped. In this case, the region will not be protected by default. It is also possible to call pkey_mprotect
with a key value of -1, in which case it will behave in the same way as mprotect
.
After key allocation assignment to memory pages, pkey_set
can be used to temporarily acquire access to the memory region and relinquish it again:
if (key >= 0 && pkey_set (key, 0) < 0) ...; /* Perform error checking (generally fatal). */ /* At this point, the current thread has read-write access to the memory region. */ ... /* Revoke access again. */ if (key >= 0 && pkey_set (key, PKEY_DISABLE_ACCESS) < 0) ...; /* Perform error checking (generally fatal). */
In this example, a negative key value indicates that no key had been allocated, which means that the system lacks support for memory protection keys and it is not necessary to change the the access rights of the current thread (because it always has access).
Compared to using mprotect
to change the page protection flags, this approach has two advantages: It is thread-safe in the sense that the access rights are only changed for the current thread, so another thread which changes its own access rights concurrently to gain access to the mapping will not suddenly see its access rights revoked. And pkey_set
typically does not involve a call into the kernel and a context switch, so it is more efficient.
Preliminary: | MT-Safe | AS-Safe | AC-Unsafe corrupt | See POSIX Safety Concepts.
Allocate a new protection key. The flags argument is reserved and must be zero. The restrictions argument specifies access rights which are applied to the current thread (as if with pkey_set
below). Access rights of other threads are not changed.
The function returns the new protection key, a non-negative number, or -1 on error.
The following errno
error conditions are defined for this function:
ENOSYS
The system does not implement memory protection keys.
EINVAL
The flags argument is not zero.
The restrictions argument is invalid.
The system does not implement memory protection keys or runs in a mode in which memory protection keys are disabled.
ENOSPC
All available protection keys already have been allocated.
The system does not implement memory protection keys or runs in a mode in which memory protection keys are disabled.
Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.
Deallocate the protection key, so that it can be reused by pkey_alloc
.
Calling this function does not change the access rights of the freed protection key. The calling thread and other threads may retain access to it, even if it is subsequently allocated again. For this reason, it is not recommended to call the pkey_free
function.
ENOSYS
The system does not implement memory protection keys.
EINVAL
The key argument is not a valid protection key.
Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.
Similar to mprotect
, but also set the memory protection key for the memory region to key
.
Some systems use memory protection keys to emulate certain combinations of protection flags. Under such circumstances, specifying an explicit protection key may behave as if additional flags have been specified in protection, even though this does not happen with the default protection key. For example, some systems can support PROT_EXEC
-only mappings only with a default protection key, and memory with a key which was allocated using pkey_alloc
will still be readable if PROT_EXEC
is specified without PROT_READ
.
If key is -1, the default protection key is applied to the mapping, just as if mprotect
had been called.
The pkey_mprotect
function returns 0 on success and -1 on failure. The same errno
error conditions as for mprotect
are defined for this function, with the following addition:
EINVAL
The key argument is not -1 or a valid memory protection key allocated using pkey_alloc
.
ENOSYS
The system does not implement memory protection keys, and key is not -1.
Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.
Change the access rights of the current thread for memory pages with the protection key key to rights. If rights is zero, no additional access restrictions on top of the page protection flags are applied. Otherwise, rights is a combination of the following flags:
PKEY_DISABLE_WRITE
¶
Subsequent attempts to write to memory with the specified protection key will fault.
PKEY_DISABLE_ACCESS
¶
Subsequent attempts to write to or read from memory with the specified protection key will fault.
Operations not specified as flags are not restricted. In particular, this means that the memory region will remain executable if it was mapped with the PROT_EXEC
protection flag and PKEY_DISABLE_ACCESS
has been specified.
Calling the pkey_set
function with a protection key which was not allocated by pkey_alloc
results in undefined behavior. This means that calling this function on systems which do not support memory protection keys is undefined.
The pkey_set
function returns 0 on success and -1 on failure.
The following errno
error conditions are defined for this function:
EINVAL
The system does not support the access rights restrictions expressed in the rights argument.
Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.
Return the access rights of the current thread for memory pages with protection key key. The return value is zero or a combination of the PKEY_DISABLE_
* flags; see the pkey_set
function.
Calling the pkey_get
function with a protection key which was not allocated by pkey_alloc
results in undefined behavior. This means that calling this function on systems which do not support memory protection keys is undefined.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4