]> git.ipfire.org Git - thirdparty/man-pages.git/blame - man7/pkeys.7
Changes: Ready for 5.02
[thirdparty/man-pages.git] / man7 / pkeys.7
CommitLineData
452f5494
DH
1.\" Copyright (C) 2016 Intel Corporation
2.\"
3.\" %%%LICENSE_START(VERBATIM)
4.\" Permission is granted to make and distribute verbatim copies of this
5.\" manual provided the copyright notice and this permission notice are
6.\" preserved on all copies.
7.\"
8.\" Permission is granted to copy and distribute modified versions of this
9.\" manual under the conditions for verbatim copying, provided that the
10.\" entire resulting derived work is distributed under the terms of a
11.\" permission notice identical to this one.
12.\"
13.\" Since the Linux kernel and libraries are constantly changing, this
14.\" manual page may be incorrect or out-of-date. The author(s) assume no
15.\" responsibility for errors or omissions, or for damages resulting from
16.\" the use of the information contained herein. The author(s) may not
17.\" have taken the same level of care in the production of this manual,
18.\" which is licensed free of charge, as they might when working
19.\" professionally.
20.\"
21.\" Formatted or processed versions of this manual, if unaccompanied by
22.\" the source, must acknowledge the copyright and authors of this work.
23.\" %%%LICENSE_END
24.\"
9ba01802 25.TH PKEYS 7 2019-03-06 "Linux" "Linux Programmer's Manual"
452f5494
DH
26.SH NAME
27pkeys \- overview of Memory Protection Keys
28.SH DESCRIPTION
29Memory Protection Keys (pkeys) are an extension to existing
30page-based memory permissions.
31Normal page permissions using
32page tables require expensive system calls and TLB invalidations
33when changing permissions.
34Memory Protection Keys provide a mechanism for changing
35protections without requiring modification of the page tables on
36every permission change.
a721e8b2 37.PP
435f231a 38To use pkeys, software must first "tag" a page in the page tables
452f5494
DH
39with a pkey.
40After this tag is in place, an application only has
41to change the contents of a register in order to remove write
42access, or all access to a tagged page.
a721e8b2 43.PP
435f231a 44Protection keys work in conjunction with the existing
1b9d5819 45.BR PROT_READ /
435f231a
MK
46.BR PROT_WRITE /
47.BR PROT_EXEC
48permissions passed to system calls such as
452f5494
DH
49.BR mprotect (2)
50and
51.BR mmap (2),
52but always act to further restrict these traditional permission
53mechanisms.
a721e8b2 54.PP
79a2a437
MK
55If a process performs an access that violates pkey
56restrictions, it receives a
57.BR SIGSEGV
58signal.
59See
60.BR sigaction (2)
61for details of the information available with that signal.
a721e8b2 62.PP
435f231a 63To use the pkeys feature, the processor must support it, and the kernel
452f5494
DH
64must contain support for the feature on a given processor.
65As of early 2016 only future Intel x86 processors are supported,
66and this hardware supports 16 protection keys in each process.
67However, pkey 0 is used as the default key, so a maximum of 15
68are available for actual application use.
69The default key is assigned to any memory region for which a
70pkey has not been explicitly assigned via
435f231a 71.BR pkey_mprotect (2).
a721e8b2 72.PP
435f231a 73Protection keys have the potential to add a layer of security and
452f5494 74reliability to applications.
435f231a 75But they have not been primarily designed as
452f5494
DH
76a security feature.
77For instance, WRPKRU is a completely unprivileged
78instruction, so pkeys are useless in any case that an attacker controls
79the PKRU register or can execute arbitrary instructions.
a721e8b2 80.PP
452f5494
DH
81Applications should be very careful to ensure that they do not "leak"
82protection keys.
435f231a
MK
83For instance, before calling
84.BR pkey_free (2),
452f5494
DH
85the application should be sure that no memory has that pkey assigned.
86If the application left the freed pkey assigned, a future user of
87that pkey might inadvertently change the permissions of an unrelated
435f231a 88data structure, which could impact security or stability.
452f5494 89The kernel currently allows in-use pkeys to have
435f231a 90.BR pkey_free (2)
452f5494
DH
91called on them because it would have processor or memory performance
92implications to perform the additional checks needed to disallow it.
435f231a
MK
93Implementation of the necessary checks is left up to applications.
94Applications may implement these checks by searching the
95.IR /proc/[pid]/smaps
96file for memory regions with the pkey assigned.
97Further details can be found in
98.BR proc (5).
a721e8b2 99.PP
452f5494
DH
100Any application wanting to use protection keys needs to be able
101to function without them.
102They might be unavailable because the hardware that the
103application runs on does not support them, the kernel code does
104not contain support, the kernel support has been disabled, or
105because the keys have all been allocated, perhaps by a library
106the application is using.
107It is recommended that applications wanting to use protection
108keys should simply call
435f231a
MK
109.BR pkey_alloc (2)
110and test whether the call succeeds,
452f5494 111instead of attempting to detect support for the
435f231a 112feature in any other way.
a721e8b2 113.PP
452f5494 114Although unnecessary, hardware support for protection keys may be
435f231a
MK
115enumerated with the
116.I cpuid
117instruction.
118Details of how to do this can be found in the Intel Software
452f5494 119Developers Manual.
435f231a
MK
120The kernel performs this enumeration and exposes the information in
121.IR /proc/cpuinfo
122under the "flags" field.
123The string "pku" in this field indicates hardware support for protection
124keys and the string "ospke" indicates that the kernel contains and has
452f5494 125enabled protection keys support.
a721e8b2 126.PP
452f5494
DH
127Applications using threads and protection keys should be especially
128careful.
129Threads inherit the protection key rights of the parent at the time
130of the
131.BR clone (2),
132system call.
133Applications should either ensure that their own permissions are
435f231a 134appropriate for child threads at the time when
452f5494 135.BR clone (2)
435f231a 136is called, or ensure that each child thread can perform its
452f5494 137own initialization of protection key rights.
3b3d46e7 138.\"
c92965c2
DH
139.SS Signal Handler Behavior
140Each time a signal handler is invoked (including nested signals), the
141thread is temporarily given a new, default set of protection key rights
142that override the rights from the interrupted context.
143This means that applications must re-establish their desired protection
144key rights upon entering a signal handler if the desired rights differ
145from the defaults.
146The rights of any interrupted context are restored when the signal
147handler returns.
a721e8b2 148.PP
c92965c2
DH
149This signal behavior is unusual and is due to the fact that the x86 PKRU
150register (which stores protection key access rights) is managed with the
151same hardware mechanism (XSAVE) that manages floating-point registers.
fc635dd8 152The signal behavior is the same as that of floating-point registers.
3b3d46e7 153.\"
452f5494
DH
154.SS Protection Keys system calls
155The Linux kernel implements the following pkey-related system calls:
156.BR pkey_mprotect (2),
157.BR pkey_alloc (2),
158and
435f231a 159.BR pkey_free (2).
a721e8b2 160.PP
452f5494 161The Linux pkey system calls are available only if the kernel was
435f231a 162configured and built with the
452f5494
DH
163.BR CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
164option.
165.SH EXAMPLE
166.PP
435f231a 167The program below allocates a page of memory with read and write permissions.
452f5494
DH
168It then writes some data to the memory and successfully reads it
169back.
170After that, it attempts to allocate a protection key and
435f231a
MK
171disallows access to the page by using the WRPKRU instruction.
172It then tries to access the page,
452f5494 173which we now expect to cause a fatal signal to the application.
a721e8b2 174.PP
452f5494 175.in +4n
b8302363 176.EX
452f5494
DH
177.RB "$" " ./a.out"
178buffer contains: 73
179about to read buffer again...
180Segmentation fault (core dumped)
b8302363 181.EE
452f5494
DH
182.in
183.SS Program source
184\&
e7d0bb47 185.EX
452f5494
DH
186#define _GNU_SOURCE
187#include <unistd.h>
188#include <sys/syscall.h>
189#include <stdio.h>
190#include <sys/mman.h>
191
8bb4e767
MK
192static inline void
193wrpkru(unsigned int pkru)
452f5494 194{
8bb4e767
MK
195 unsigned int eax = pkru;
196 unsigned int ecx = 0;
197 unsigned int edx = 0;
452f5494 198
d1a71985 199 asm volatile(".byte 0x0f,0x01,0xef\en\et"
8bb4e767 200 : : "a" (eax), "c" (ecx), "d" (edx));
452f5494
DH
201}
202
8bb4e767
MK
203int
204pkey_set(int pkey, unsigned long rights, unsigned long flags)
452f5494 205{
8bb4e767 206 unsigned int pkru = (rights << (2 * pkey));
452f5494
DH
207 return wrpkru(pkru);
208}
209
8bb4e767
MK
210int
211pkey_mprotect(void *ptr, size_t size, unsigned long orig_prot,
212 unsigned long pkey)
452f5494
DH
213{
214 return syscall(SYS_pkey_mprotect, ptr, size, orig_prot, pkey);
215}
216
8bb4e767
MK
217int
218pkey_alloc(void)
452f5494
DH
219{
220 return syscall(SYS_pkey_alloc, 0, 0);
221}
222
8bb4e767
MK
223int
224pkey_free(unsigned long pkey)
452f5494
DH
225{
226 return syscall(SYS_pkey_free, pkey);
227}
228
d1a71985 229#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
8bb4e767
MK
230 } while (0)
231
232int
233main(void)
452f5494
DH
234{
235 int status;
236 int pkey;
237 int *buffer;
238
8bb4e767
MK
239 /*
240 *Allocate one page of memory
241 */
242 buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
243 MAP_ANONYMOUS | MAP_PRIVATE, \-1, 0);
452f5494 244 if (buffer == MAP_FAILED)
8bb4e767 245 errExit("mmap");
452f5494 246
8bb4e767
MK
247 /*
248 * Put some random data into the page (still OK to touch)
249 */
250 *buffer = __LINE__;
d1a71985 251 printf("buffer contains: %d\en", *buffer);
452f5494 252
8bb4e767
MK
253 /*
254 * Allocate a protection key:
255 */
452f5494 256 pkey = pkey_alloc();
8bb4e767
MK
257 if (pkey == \-1)
258 errExit("pkey_alloc");
452f5494 259
8bb4e767
MK
260 /*
261 * Disable access to any memory with "pkey" set,
262 * even though there is none right now
263 */
452f5494
DH
264 status = pkey_set(pkey, PKEY_DISABLE_ACCESS, 0);
265 if (status)
8bb4e767 266 errExit("pkey_set");
452f5494
DH
267
268 /*
8bb4e767
MK
269 * Set the protection key on "buffer".
270 * Note that it is still read/write as far as mprotect() is
452f5494
DH
271 * concerned and the previous pkey_set() overrides it.
272 */
8bb4e767
MK
273 status = pkey_mprotect(buffer, getpagesize(),
274 PROT_READ | PROT_WRITE, pkey);
275 if (status == -1)
276 errExit("pkey_mprotect");
452f5494 277
d1a71985 278 printf("about to read buffer again...\en");
8bb4e767
MK
279
280 /*
281 * This will crash, because we have disallowed access
282 */
d1a71985 283 printf("buffer contains: %d\en", *buffer);
452f5494
DH
284
285 status = pkey_free(pkey);
8bb4e767
MK
286 if (status == -1)
287 errExit("pkey_free");
452f5494 288
8bb4e767 289 exit(EXIT_SUCCESS);
452f5494 290}
b9c93deb 291.EE
452f5494
DH
292.SH SEE ALSO
293.BR pkey_alloc (2),
294.BR pkey_free (2),
295.BR pkey_mprotect (2),
435f231a 296.BR sigaction (2)