]>
Commit | Line | Data |
---|---|---|
c11b1abf | 1 | .\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com> |
2a5e0dcd | 2 | .\" and Copyright (C) 1995 Michael Shields <shields@tembel.org>. |
fea681da | 3 | .\" |
93015253 | 4 | .\" %%%LICENSE_START(VERBATIM) |
fea681da MK |
5 | .\" Permission is granted to make and distribute verbatim copies of this |
6 | .\" manual provided the copyright notice and this permission notice are | |
7 | .\" preserved on all copies. | |
8 | .\" | |
9 | .\" Permission is granted to copy and distribute modified versions of this | |
10 | .\" manual under the conditions for verbatim copying, provided that the | |
11 | .\" entire resulting derived work is distributed under the terms of a | |
12 | .\" permission notice identical to this one. | |
c13182ef | 13 | .\" |
fea681da MK |
14 | .\" Since the Linux kernel and libraries are constantly changing, this |
15 | .\" manual page may be incorrect or out-of-date. The author(s) assume no | |
16 | .\" responsibility for errors or omissions, or for damages resulting from | |
17 | .\" the use of the information contained herein. The author(s) may not | |
18 | .\" have taken the same level of care in the production of this manual, | |
19 | .\" which is licensed free of charge, as they might when working | |
20 | .\" professionally. | |
c13182ef | 21 | .\" |
fea681da MK |
22 | .\" Formatted or processed versions of this manual, if unaccompanied by |
23 | .\" the source, must acknowledge the copyright and author of this work. | |
4b72fb64 | 24 | .\" %%%LICENSE_END |
fea681da MK |
25 | .\" |
26 | .\" Modified 1996-10-22 by Eric S. Raymond <esr@thyrsus.com> | |
27 | .\" Modified 1997-05-31 by Andries Brouwer <aeb@cwi.nl> | |
28 | .\" Modified 2003-08-24 by Andries Brouwer <aeb@cwi.nl> | |
29 | .\" Modified 2004-08-16 by Andi Kleen <ak@muc.de> | |
2a5e0dcd MK |
30 | .\" 2007-06-02, mtk: Fairly substantial rewrites and additions, and |
31 | .\" a much improved example program. | |
bea08fec | 32 | .\" |
63121bd4 | 33 | .TH MPROTECT 2 2019-08-02 "Linux" "Linux Programmer's Manual" |
fea681da | 34 | .SH NAME |
d800ae65 | 35 | mprotect, pkey_mprotect \- set protection on a region of memory |
fea681da MK |
36 | .SH SYNOPSIS |
37 | .nf | |
38 | .B #include <sys/mman.h> | |
68e4db0a | 39 | .PP |
a2f11be3 | 40 | .BI "int mprotect(void *" addr ", size_t " len ", int " prot ); |
f92ea96b MW |
41 | |
42 | .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" | |
43 | .B #include <sys/mman.h> | |
44 | .PP | |
d800ae65 | 45 | .BI "int pkey_mprotect(void *" addr ", size_t " len ", int " prot ", int " pkey "); |
fea681da MK |
46 | .fi |
47 | .SH DESCRIPTION | |
e511ffb6 | 48 | .BR mprotect () |
93d210fd | 49 | changes the access protections for the calling process's memory pages |
988db661 | 50 | containing any part of the address range in the |
657e762d | 51 | interval [\fIaddr\fP,\ \fIaddr\fP+\fIlen\fP\-1]. |
2a5e0dcd MK |
52 | .I addr |
53 | must be aligned to a page boundary. | |
efeece04 | 54 | .PP |
2a5e0dcd | 55 | If the calling process tries to access memory in a manner |
93d210fd | 56 | that violates the protections, then the kernel generates a |
2a5e0dcd MK |
57 | .B SIGSEGV |
58 | signal for the process. | |
fea681da MK |
59 | .PP |
60 | .I prot | |
a9799e8a | 61 | is a combination of the following access flags: |
2a5e0dcd MK |
62 | .B PROT_NONE |
63 | or a bitwise-or of the other values in the following list: | |
fea681da MK |
64 | .TP 1.1i |
65 | .B PROT_NONE | |
66 | The memory cannot be accessed at all. | |
67 | .TP | |
68 | .B PROT_READ | |
69 | The memory can be read. | |
70 | .TP | |
71 | .B PROT_WRITE | |
2a5e0dcd | 72 | The memory can be modified. |
fea681da MK |
73 | .TP |
74 | .B PROT_EXEC | |
fc15ae54 | 75 | The memory can be executed. |
a9799e8a ES |
76 | .TP |
77 | .BR PROT_SEM " (since Linux 2.5.7)" | |
be232513 | 78 | The memory can be used for atomic operations. |
d88d01c6 | 79 | This flag was introduced as part of the |
a9799e8a | 80 | .BR futex (2) |
d88d01c6 MK |
81 | implementation (in order to guarantee the ability to perform atomic |
82 | operations required by commands such as | |
a9799e8a | 83 | .BR FUTEX_WAIT ), |
d88d01c6 | 84 | but is not currently used in on any architecture. |
a9799e8a ES |
85 | .TP |
86 | .BR PROT_SAO " (since Linux 2.6.26)" | |
d88d01c6 MK |
87 | .\" commit aba46c5027cb59d98052231b36efcbbde9c77a1d |
88 | .\" commit ef3d3246a0d06be622867d21af25f997aeeb105f | |
be232513 MK |
89 | The memory should have strong access ordering. |
90 | This feature is specific to | |
d88d01c6 MK |
91 | the PowerPC architecture |
92 | (version 2.06 of the architecture specification adds the SAO CPU feature, | |
be232513 | 93 | and it is available on POWER 7 or PowerPC A2, for example). |
a9799e8a ES |
94 | .PP |
95 | Additionally (since Linux 2.6.0), | |
96 | .I prot | |
97 | can have one of the following flags set: | |
98 | .TP 1.1i | |
99 | .\" mm/mmap.c: | |
100 | .\" vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | | |
101 | .\" mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; | |
102 | .\" And calc_vm_flag_bits converts only GROWSDOWN/DENYWRITE/LOCKED. | |
103 | .B PROT_GROWSUP | |
d88d01c6 MK |
104 | Apply the protection mode up to the end of a mapping |
105 | that grows upwards. | |
106 | (Such mappings are created for the stack area on | |
107 | architectures\(emfor example, HP-PARISC\(emthat | |
108 | have an upwardly growing stack.) | |
109 | .\" The VMA is one that was marked with VM_GROWSUP by the kernel | |
110 | .\" when the stack was created. Note that (unlike VM_GROWSDOWN), | |
111 | .\" there is no mmap() flag (analogous to MAP_GROWSDOWN) for | |
112 | .\" creating a VMA that is marked VM_GROWSUP. | |
a9799e8a ES |
113 | .TP |
114 | .B PROT_GROWSDOWN | |
d88d01c6 MK |
115 | Apply the protection mode down to the beginning of a mapping |
116 | that grows downward | |
117 | (which should be a stack segment or a segment mapped with the | |
a9799e8a | 118 | .B MAP_GROWSDOWN |
d88d01c6 | 119 | flag set). |
d800ae65 | 120 | .PP |
9e7d6be1 MK |
121 | Like |
122 | .BR mprotect (), | |
123 | .BR pkey_mprotect () | |
124 | changes the protection on the pages specified by | |
125 | .IR addr | |
126 | and | |
127 | .IR len . | |
128 | The | |
d800ae65 | 129 | .I pkey |
9e7d6be1 | 130 | argument specifies the protection key (see |
31e0cc44 | 131 | .BR pkeys (7)) |
9e7d6be1 MK |
132 | to assign to the memory. |
133 | The protection key must be allocated with | |
d800ae65 DH |
134 | .BR pkey_alloc (2) |
135 | before it is passed to | |
136 | .BR pkey_mprotect (). | |
9e7d6be1 | 137 | For an example of the use of this system call, see |
31e0cc44 | 138 | .BR pkeys (7). |
47297adb | 139 | .SH RETURN VALUE |
fea681da | 140 | On success, |
e511ffb6 | 141 | .BR mprotect () |
d800ae65 DH |
142 | and |
143 | .BR pkey_mprotect () | |
144 | return zero. | |
9e7d6be1 | 145 | On error, these system calls return \-1, and |
fea681da MK |
146 | .I errno |
147 | is set appropriately. | |
148 | .SH ERRORS | |
149 | .TP | |
150 | .B EACCES | |
c13182ef MK |
151 | The memory cannot be given the specified access. |
152 | This can happen, for example, if you | |
fea681da MK |
153 | .BR mmap (2) |
154 | a file to which you have read-only access, then ask | |
e511ffb6 | 155 | .BR mprotect () |
fea681da MK |
156 | to mark it |
157 | .BR PROT_WRITE . | |
158 | .TP | |
fea681da | 159 | .B EINVAL |
a8d55537 | 160 | \fIaddr\fP is not a valid pointer, |
2a5e0dcd | 161 | or not a multiple of the system page size. |
9e7d6be1 MK |
162 | .TP |
163 | .BR EINVAL | |
164 | .RB ( pkey_mprotect ()) | |
165 | \fIpkey\fP has not been allocated with | |
d800ae65 | 166 | .BR pkey_alloc (2) |
a9799e8a ES |
167 | .TP |
168 | .BR EINVAL | |
169 | Both | |
be232513 MK |
170 | .BR PROT_GROWSUP |
171 | and | |
172 | .BR PROT_GROWSDOWN | |
a9799e8a ES |
173 | were specified in |
174 | .IR prot . | |
175 | .TP | |
176 | .BR EINVAL | |
d88d01c6 | 177 | Invalid flags specified in |
a9799e8a ES |
178 | .IR prot . |
179 | .TP | |
180 | .BR EINVAL | |
181 | (PowerPC architecture) | |
182 | .B PROT_SAO | |
d88d01c6 | 183 | was specified in |
a9799e8a ES |
184 | .IR prot , |
185 | but SAO hardware feature is not available. | |
fea681da MK |
186 | .TP |
187 | .B ENOMEM | |
c13182ef | 188 | Internal kernel structures could not be allocated. |
22b22831 MK |
189 | .TP |
190 | .B ENOMEM | |
191 | Addresses in the range | |
f8ad0aeb | 192 | .RI [ addr , |
da2336b3 | 193 | .IR addr + len \-1] |
f8ad0aeb MK |
194 | are invalid for the address space of the process, |
195 | or specify one or more pages that are not mapped. | |
22b22831 MK |
196 | (Before kernel 2.4.19, the error |
197 | .BR EFAULT | |
198 | was incorrectly produced for these cases.) | |
4607213d MK |
199 | .TP |
200 | .B ENOMEM | |
201 | Changing the protection of a memory region would result in the total number of | |
202 | mappings with distinct attributes (e.g., read versus read/write protection) | |
203 | exceeding the allowed maximum. | |
ee8655b5 | 204 | .\" I.e., the number of VMAs would exceed the 64 kB maximum |
4607213d MK |
205 | (For example, making the protection of a range |
206 | .BR PROT_READ | |
207 | in the middle of a region currently protected as | |
208 | .BR PROT_READ|PROT_WRITE | |
209 | would result in three mappings: | |
210 | two read/write mappings at each end and a read-only mapping in the middle.) | |
f74aed0e MK |
211 | .SH VERSIONS |
212 | .BR pkey_mprotect () | |
fe110bff MK |
213 | first appeared in Linux 4.9; |
214 | library support was added in glibc 2.27. | |
47297adb | 215 | .SH CONFORMING TO |
8f5484f8 | 216 | .BR mprotect (): |
c22f5880 | 217 | POSIX.1-2001, POSIX.1-2008, SVr4. |
2b2581ee MK |
218 | .\" SVr4 defines an additional error |
219 | .\" code EAGAIN. The SVr4 error conditions don't map neatly onto Linux's. | |
d9bfdb9c | 220 | POSIX says that the behavior of |
2b2581ee | 221 | .BR mprotect () |
2a5e0dcd MK |
222 | is unspecified if it is applied to a region of memory that |
223 | was not obtained via | |
2b2581ee | 224 | .BR mmap (2). |
efeece04 | 225 | .PP |
8f5484f8 MK |
226 | .BR pkey_mprotect () |
227 | is a nonportable Linux extension. | |
2b2581ee | 228 | .SH NOTES |
329ad271 | 229 | On Linux, it is always permissible to call |
2b2581ee | 230 | .BR mprotect () |
fc7ba057 | 231 | on any address in a process's address space (except for the |
2b2581ee | 232 | kernel vsyscall area). |
3a06e3f7 | 233 | In particular, it can be used |
2b2581ee | 234 | to change existing code mappings to be writable. |
efeece04 | 235 | .PP |
2b2581ee MK |
236 | Whether |
237 | .B PROT_EXEC | |
238 | has any effect different from | |
239 | .B PROT_READ | |
28d01ac4 MK |
240 | depends on processor architecture, kernel version, and process state. |
241 | If | |
b22b377b MS |
242 | .B READ_IMPLIES_EXEC |
243 | is set in the process's personality flags (see | |
244 | .BR personality (2)), | |
245 | specifying | |
246 | .B PROT_READ | |
247 | will implicitly add | |
d8012462 | 248 | .BR PROT_EXEC . |
efeece04 | 249 | .PP |
34ccb744 | 250 | On some hardware architectures (e.g., i386), |
0daa9e92 | 251 | .B PROT_WRITE |
f3edaabb MK |
252 | implies |
253 | .BR PROT_READ . | |
efeece04 | 254 | .PP |
c22f5880 | 255 | POSIX.1 says that an implementation may permit access |
2a5e0dcd MK |
256 | other than that specified in |
257 | .IR prot , | |
33a0ccb2 | 258 | but at a minimum can allow write access only if |
2a5e0dcd MK |
259 | .B PROT_WRITE |
260 | has been set, and must not allow any access if | |
261 | .B PROT_NONE | |
262 | has been set. | |
efeece04 | 263 | .PP |
d800ae65 DH |
264 | Applications should be careful when mixing use of |
265 | .BR mprotect () | |
266 | and | |
9e7d6be1 | 267 | .BR pkey_mprotect (). |
d800ae65 DH |
268 | On x86, when |
269 | .BR mprotect () | |
270 | is used with | |
271 | .IR prot | |
272 | set to | |
273 | .B PROT_EXEC | |
274 | a pkey is may be allocated and set on the memory implicitly | |
275 | by the kernel, but only when the pkey was 0 previously. | |
efeece04 | 276 | .PP |
d800ae65 DH |
277 | On systems that do not support protection keys in hardware, |
278 | .BR pkey_mprotect () | |
279 | may still be used, but | |
280 | .IR pkey | |
a4a0b742 | 281 | must be set to -1. |
d800ae65 DH |
282 | When called this way, the operation of |
283 | .BR pkey_mprotect () | |
284 | is equivalent to | |
285 | .BR mprotect (). | |
fea681da | 286 | .SH EXAMPLE |
2720c2ed | 287 | .\" sigaction.2 refers to this example |
f20d7d8e | 288 | .PP |
9e7d6be1 | 289 | The program below demonstrates the use of |
9871c08c | 290 | .BR mprotect (). |
9e7d6be1 | 291 | The program allocates four pages of memory, makes the third |
5fab2e7c | 292 | of these pages read-only, and then executes a loop that walks upward |
f20d7d8e | 293 | through the allocated region modifying bytes. |
efeece04 | 294 | .PP |
f20d7d8e MK |
295 | An example of what we might see when running the program is the |
296 | following: | |
efeece04 | 297 | .PP |
088a639b | 298 | .in +4n |
b8302363 | 299 | .EX |
b43a3b30 | 300 | .RB "$" " ./a.out" |
f20d7d8e MK |
301 | Start of region: 0x804c000 |
302 | Got SIGSEGV at address: 0x804e000 | |
b8302363 | 303 | .EE |
1c32ee47 | 304 | .in |
9c330504 | 305 | .SS Program source |
d84d0300 | 306 | \& |
e7d0bb47 | 307 | .EX |
f20d7d8e MK |
308 | #include <unistd.h> |
309 | #include <signal.h> | |
fea681da | 310 | #include <stdio.h> |
f20d7d8e | 311 | #include <malloc.h> |
fea681da MK |
312 | #include <stdlib.h> |
313 | #include <errno.h> | |
314 | #include <sys/mman.h> | |
315 | ||
d1a71985 | 316 | #define handle_error(msg) \e |
6a578b88 | 317 | do { perror(msg); exit(EXIT_FAILURE); } while (0) |
d3b5ab82 | 318 | |
22617a74 | 319 | static char *buffer; |
f20d7d8e MK |
320 | |
321 | static void | |
322 | handler(int sig, siginfo_t *si, void *unused) | |
323 | { | |
e931e035 MK |
324 | /* Note: calling printf() from a signal handler is not safe |
325 | (and should not be done in production programs), since | |
326 | printf() is not async\-signal\-safe; see signal-safety(7). | |
327 | Nevertheless, we use printf() here as a simple way of | |
328 | showing that the handler was called. */ | |
329 | ||
d1a71985 | 330 | printf("Got SIGSEGV at address: 0x%lx\en", |
29059a65 | 331 | (long) si\->si_addr); |
f20d7d8e MK |
332 | exit(EXIT_FAILURE); |
333 | } | |
fea681da MK |
334 | |
335 | int | |
f20d7d8e | 336 | main(int argc, char *argv[]) |
fea681da MK |
337 | { |
338 | char *p; | |
f20d7d8e MK |
339 | int pagesize; |
340 | struct sigaction sa; | |
341 | ||
342 | sa.sa_flags = SA_SIGINFO; | |
343 | sigemptyset(&sa.sa_mask); | |
344 | sa.sa_sigaction = handler; | |
29059a65 | 345 | if (sigaction(SIGSEGV, &sa, NULL) == \-1) |
6a578b88 | 346 | handle_error("sigaction"); |
fea681da | 347 | |
f20d7d8e | 348 | pagesize = sysconf(_SC_PAGE_SIZE); |
29059a65 | 349 | if (pagesize == \-1) |
6a578b88 | 350 | handle_error("sysconf"); |
fea681da | 351 | |
988db661 | 352 | /* Allocate a buffer aligned on a page boundary; |
f20d7d8e MK |
353 | initial protection is PROT_READ | PROT_WRITE */ |
354 | ||
355 | buffer = memalign(pagesize, 4 * pagesize); | |
d3b5ab82 | 356 | if (buffer == NULL) |
6a578b88 | 357 | handle_error("memalign"); |
fea681da | 358 | |
d1a71985 | 359 | printf("Start of region: 0x%lx\en", (long) buffer); |
fea681da | 360 | |
988db661 | 361 | if (mprotect(buffer + pagesize * 2, pagesize, |
7d9da03f | 362 | PROT_READ) == \-1) |
6a578b88 | 363 | handle_error("mprotect"); |
fea681da | 364 | |
f20d7d8e | 365 | for (p = buffer ; ; ) |
f81fb444 | 366 | *(p++) = \(aqa\(aq; |
fea681da | 367 | |
d1a71985 | 368 | printf("Loop completed\en"); /* Should never happen */ |
646f46f0 | 369 | exit(EXIT_SUCCESS); |
fea681da | 370 | } |
e7d0bb47 | 371 | .EE |
47297adb | 372 | .SH SEE ALSO |
2a5e0dcd | 373 | .BR mmap (2), |
9e7d6be1 | 374 | .BR sysconf (3), |
31e0cc44 | 375 | .BR pkeys (7) |