---
name: "pkru"
section: "3"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/pkru"
---

# pkru(3)

provide fast user-managed key-based access control for pages

## NAME

**Protection** **Key** **Rights** **for** **User** **pages** – provide fast user-managed key-based access control for pages

## LIBRARY

Standard C Library (libc, -lc)

## SYNOPSIS

**#include \<machine/sysarch.h\>**

*int*\

**x86\_pkru\_get\_perm**(*unsigned int keyidx*, *int \*access*, *int \*modify*);

*int*\

**x86\_pkru\_set\_perm**(*unsigned int keyidx*, *int access*, *int modify*);

*int*\

**x86\_pkru\_protect\_range**(*void \*addr*, *unsigned long len*, *unsigned int keyidx*, *int flag*);

*int*\

**x86\_pkru\_unprotect\_range**(*void \*addr*, *unsigned long len*);

## DESCRIPTION

The protection keys feature provides an additional mechanism, besides the normal page permissions as established by [mmap(2)](/mmap/2.md) and [mprotect(2)](/mprotect/2.md), to control access to user-mode addresses. The mechanism gives safety measures which can be used to avoid incidental read or modification of sensitive memory, or as a debugging feature. It cannot guard against conscious accesses since permissions are user-controllable.

If supported by hardware, each mapped user linear address has an associated 4-bit protection key. A new per-thread PKRU hardware register determines, for each protection key, whether user-mode addresses with that protection key may be read or written.

Only one key may apply to a given range at a time. The default protection key index is zero, it is used even if no key was explicitly assigned to the address, or if the key was removed.

If the user application attempts a memory access which is prohibited by the PKRU register, the offending thread receives a synchronous SIGSEGV signal with *si\_code* set to SEGV\_PKUERR. PKRU protections might prevent the kernel from accessing protected user addresses when handling system calls, but this is not guaranteed and must not be relied upon.

Both 64-bit and 32-bit applications can use protection keys. More information about the hardware feature is provided in the IA32 Software Developer's Manual published by Intel Corp.

The key indexes written into the page table entries are managed by the **sysarch**() syscall. Per-key permissions are managed using the user-mode instructions *RDPKRU* and *WRPKRU*. The system provides convenient library helpers for both the syscall and the instructions, described below.

The **x86\_pkru\_protect\_range**() function assigns key *keyidx* to the range starting at *addr* and having length *len*. Starting address is truncated to the page start, and the end is rounded up to the end of the page. After a successful call, the range has the specified key assigned, even if the key is zero and it did not change the page table entries.

The *flags* argument takes the logical OR of the following values:

- \[*AMD64\_PKRU\_EXCL*\]

  Only assign the key if the range does not have any other keys assigned (including the zero key). You must first remove any existing key with **x86\_pkru\_unprotect\_range**() in order for this request to succeed. If the *AMD64\_PKRU\_EXCL* flag is not specified, **x86\_pkru\_protect\_range**() replaces any existing key.

- \[*AMD64\_PKRU\_PERSIST*\]

  The keys assigned to the range are persistent. They are re-established when the current mapping is destroyed and a new mapping is created in any sub-range of the specified range. You must use a **x86\_pkru\_unprotect\_range**() call to forget the key.

The **x86\_pkru\_unprotect\_range**() function removes any keys assigned to the specified range. Existing mappings are changed to use key index zero in page table entries. Keys are no longer considered installed for all mappings in the range, for the purposes of **x86\_pkru\_protect\_range**() with the *AMD64\_PKRU\_EXCL* flag.

The **x86\_pkru\_get\_perm**() function returns access rights for the key specified by the *keyidx* argument. If the value pointed to by *access* is zero after the call, no read or write permissions is granted for mappings which are assigned the key *keyidx*. If *access* is not zero, read access is permitted. The non-zero value of the variable pointed to by the *modify* argument indicates that write access is permitted.

Conversely, the **x86\_pkru\_set\_perm**() establishes the access and modify permissions for the given key index as specified by its arguments.

## RETURN VALUES

The **Protection()** function returns the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.

## ERRORS

- \[EOPNOTSUPP\]

  The hardware does not support protection keys.

- \[EINVAL\]

  The supplied key index is invalid (greater than 15).

- \[EINVAL\]

  The supplied *flags* argument for **x86\_pkru\_protect\_range**() has reserved bits set.

- \[EINVAL\]

  The range of the request partially covers a mapping of an object created by [shm\_create\_largepage(3)](/shm_create_largepage/3.md).

- \[EFAULT\]

  The supplied address range does not completely fit into the user-managed address range.

- \[ENOMEM\]

  The memory shortage prevents the completion of the operation.

- \[EBUSY\]

  The *AMD64\_PKRU\_EXCL* flag was specified for **x86\_pkru\_protect\_range**() and the range already has defined protection keys.

## SEE ALSO

[mmap(2)](/mmap/2.md), [mprotect(2)](/mprotect/2.md), [munmap(2)](/munmap/2.md), [sysarch(2)](/sysarch/2.md)

## STANDARDS

The **Protection** functions are non-standard and first appeared in FreeBSD 13.0.
