1mprotect(2) System Calls Manual mprotect(2)
2
3
4
6 mprotect, pkey_mprotect - set protection on a region of memory
7
9 Standard C library (libc, -lc)
10
12 #include <sys/mman.h>
13
14 int mprotect(void addr[.len], size_t len, int prot);
15
16 #define _GNU_SOURCE /* See feature_test_macros(7) */
17 #include <sys/mman.h>
18
19 int pkey_mprotect(void addr[.len], size_t len, int prot, int pkey);
20
22 mprotect() changes the access protections for the calling process's
23 memory pages containing any part of the address range in the interval
24 [addr, addr+len-1]. addr must be aligned to a page boundary.
25
26 If the calling process tries to access memory in a manner that violates
27 the protections, then the kernel generates a SIGSEGV signal for the
28 process.
29
30 prot is a combination of the following access flags: PROT_NONE or a
31 bitwise-or of the other values in the following list:
32
33 PROT_NONE
34 The memory cannot be accessed at all.
35
36 PROT_READ
37 The memory can be read.
38
39 PROT_WRITE
40 The memory can be modified.
41
42 PROT_EXEC
43 The memory can be executed.
44
45 PROT_SEM (since Linux 2.5.7)
46 The memory can be used for atomic operations. This flag was in‐
47 troduced as part of the futex(2) implementation (in order to
48 guarantee the ability to perform atomic operations required by
49 commands such as FUTEX_WAIT), but is not currently used in on
50 any architecture.
51
52 PROT_SAO (since Linux 2.6.26)
53 The memory should have strong access ordering. This feature is
54 specific to the PowerPC architecture (version 2.06 of the archi‐
55 tecture specification adds the SAO CPU feature, and it is avail‐
56 able on POWER 7 or PowerPC A2, for example).
57
58 Additionally (since Linux 2.6.0), prot can have one of the following
59 flags set:
60
61 PROT_GROWSUP
62 Apply the protection mode up to the end of a mapping that grows
63 upwards. (Such mappings are created for the stack area on ar‐
64 chitectures—for example, HP-PARISC—that have an upwardly growing
65 stack.)
66
67 PROT_GROWSDOWN
68 Apply the protection mode down to the beginning of a mapping
69 that grows downward (which should be a stack segment or a seg‐
70 ment mapped with the MAP_GROWSDOWN flag set).
71
72 Like mprotect(), pkey_mprotect() changes the protection on the pages
73 specified by addr and len. The pkey argument specifies the protection
74 key (see pkeys(7)) to assign to the memory. The protection key must be
75 allocated with pkey_alloc(2) before it is passed to pkey_mprotect().
76 For an example of the use of this system call, see pkeys(7).
77
79 On success, mprotect() and pkey_mprotect() return zero. On error,
80 these system calls return -1, and errno is set to indicate the error.
81
83 EACCES The memory cannot be given the specified access. This can hap‐
84 pen, for example, if you mmap(2) a file to which you have read-
85 only access, then ask mprotect() to mark it PROT_WRITE.
86
87 EINVAL addr is not a valid pointer, or not a multiple of the system
88 page size.
89
90 EINVAL (pkey_mprotect()) pkey has not been allocated with pkey_alloc(2)
91
92 EINVAL Both PROT_GROWSUP and PROT_GROWSDOWN were specified in prot.
93
94 EINVAL Invalid flags specified in prot.
95
96 EINVAL (PowerPC architecture) PROT_SAO was specified in prot, but SAO
97 hardware feature is not available.
98
99 ENOMEM Internal kernel structures could not be allocated.
100
101 ENOMEM Addresses in the range [addr, addr+len-1] are invalid for the
102 address space of the process, or specify one or more pages that
103 are not mapped. (Before Linux 2.4.19, the error EFAULT was in‐
104 correctly produced for these cases.)
105
106 ENOMEM Changing the protection of a memory region would result in the
107 total number of mappings with distinct attributes (e.g., read
108 versus read/write protection) exceeding the allowed maximum.
109 (For example, making the protection of a range PROT_READ in the
110 middle of a region currently protected as PROT_READ|PROT_WRITE
111 would result in three mappings: two read/write mappings at each
112 end and a read-only mapping in the middle.)
113
115 POSIX says that the behavior of mprotect() is unspecified if it is ap‐
116 plied to a region of memory that was not obtained via mmap(2).
117
118 On Linux, it is always permissible to call mprotect() on any address in
119 a process's address space (except for the kernel vsyscall area). In
120 particular, it can be used to change existing code mappings to be
121 writable.
122
123 Whether PROT_EXEC has any effect different from PROT_READ depends on
124 processor architecture, kernel version, and process state. If READ_IM‐
125 PLIES_EXEC is set in the process's personality flags (see personal‐
126 ity(2)), specifying PROT_READ will implicitly add PROT_EXEC.
127
128 On some hardware architectures (e.g., i386), PROT_WRITE implies
129 PROT_READ.
130
131 POSIX.1 says that an implementation may permit access other than that
132 specified in prot, but at a minimum can allow write access only if
133 PROT_WRITE has been set, and must not allow any access if PROT_NONE has
134 been set.
135
136 Applications should be careful when mixing use of mprotect() and
137 pkey_mprotect(). On x86, when mprotect() is used with prot set to
138 PROT_EXEC a pkey may be allocated and set on the memory implicitly by
139 the kernel, but only when the pkey was 0 previously.
140
141 On systems that do not support protection keys in hardware, pkey_mpro‐
142 tect() may still be used, but pkey must be set to -1. When called this
143 way, the operation of pkey_mprotect() is equivalent to mprotect().
144
146 mprotect()
147 POSIX.1-2008.
148
149 pkey_mprotect()
150 Linux.
151
153 mprotect()
154 POSIX.1-2001, SVr4.
155
156 pkey_mprotect()
157 Linux 4.9, glibc 2.27.
158
161 The program below demonstrates the use of mprotect(). The program al‐
162 locates four pages of memory, makes the third of these pages read-only,
163 and then executes a loop that walks upward through the allocated region
164 modifying bytes.
165
166 An example of what we might see when running the program is the follow‐
167 ing:
168
169 $ ./a.out
170 Start of region: 0x804c000
171 Got SIGSEGV at address: 0x804e000
172
173 Program source
174
175 #include <malloc.h>
176 #include <signal.h>
177 #include <stdio.h>
178 #include <stdlib.h>
179 #include <sys/mman.h>
180 #include <unistd.h>
181
182 #define handle_error(msg) \
183 do { perror(msg); exit(EXIT_FAILURE); } while (0)
184
185 static char *buffer;
186
187 static void
188 handler(int sig, siginfo_t *si, void *unused)
189 {
190 /* Note: calling printf() from a signal handler is not safe
191 (and should not be done in production programs), since
192 printf() is not async-signal-safe; see signal-safety(7).
193 Nevertheless, we use printf() here as a simple way of
194 showing that the handler was called. */
195
196 printf("Got SIGSEGV at address: %p\n", si->si_addr);
197 exit(EXIT_FAILURE);
198 }
199
200 int
201 main(void)
202 {
203 int pagesize;
204 struct sigaction sa;
205
206 sa.sa_flags = SA_SIGINFO;
207 sigemptyset(&sa.sa_mask);
208 sa.sa_sigaction = handler;
209 if (sigaction(SIGSEGV, &sa, NULL) == -1)
210 handle_error("sigaction");
211
212 pagesize = sysconf(_SC_PAGE_SIZE);
213 if (pagesize == -1)
214 handle_error("sysconf");
215
216 /* Allocate a buffer aligned on a page boundary;
217 initial protection is PROT_READ | PROT_WRITE. */
218
219 buffer = memalign(pagesize, 4 * pagesize);
220 if (buffer == NULL)
221 handle_error("memalign");
222
223 printf("Start of region: %p\n", buffer);
224
225 if (mprotect(buffer + pagesize * 2, pagesize,
226 PROT_READ) == -1)
227 handle_error("mprotect");
228
229 for (char *p = buffer ; ; )
230 *(p++) = 'a';
231
232 printf("Loop completed\n"); /* Should never happen */
233 exit(EXIT_SUCCESS);
234 }
235
237 mmap(2), sysconf(3), pkeys(7)
238
239
240
241Linux man-pages 6.04 2023-03-30 mprotect(2)