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