Added
Link Here
|
1 |
/*- |
2 |
* Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com> |
3 |
* All rights reserved. |
4 |
* |
5 |
* Redistribution and use in source and binary forms, with or without |
6 |
* modification, are permitted provided that the following conditions |
7 |
* are met: |
8 |
* 1. Redistributions of source code must retain the above copyright |
9 |
* notice, this list of conditions and the following disclaimer. |
10 |
* 2. The name of the developer may NOT be used to endorse or promote products |
11 |
* derived from this software without specific prior written permission. |
12 |
* |
13 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
14 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
16 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
17 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
18 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
19 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
20 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
21 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
22 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
23 |
* SUCH DAMAGE. |
24 |
* |
25 |
* $FreeBSD$ |
26 |
* |
27 |
* Enhancements made by Shawn "lattera" Webb under the direction of SoldierX. |
28 |
*/ |
29 |
|
30 |
#include <sys/cdefs.h> |
31 |
__FBSDID("$FreeBSD$"); |
32 |
|
33 |
#include "opt_pax.h" |
34 |
#include "opt_compat.h" |
35 |
|
36 |
#include <sys/param.h> |
37 |
#include <sys/systm.h> |
38 |
#include <sys/kernel.h> |
39 |
#include <sys/imgact.h> |
40 |
#include <sys/sysent.h> |
41 |
#include <sys/proc.h> |
42 |
#include <sys/elf_common.h> |
43 |
#include <sys/pax.h> |
44 |
#include <sys/sysctl.h> |
45 |
#include <sys/vnode.h> |
46 |
#include <sys/queue.h> |
47 |
#include <sys/libkern.h> |
48 |
#include <sys/jail.h> |
49 |
|
50 |
#include <sys/mman.h> |
51 |
#include <sys/libkern.h> |
52 |
#include <sys/exec.h> |
53 |
|
54 |
#include <vm/pmap.h> |
55 |
#include <vm/vm_map.h> |
56 |
|
57 |
static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS); |
58 |
static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS); |
59 |
static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS); |
60 |
static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS); |
61 |
|
62 |
/* |
63 |
* sysctls and tunables |
64 |
*/ |
65 |
int pax_aslr_status = PAX_ASLR_ENABLED; |
66 |
int pax_aslr_debug = 0; |
67 |
|
68 |
#ifdef PAX_ASLR_MAX_SEC |
69 |
int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MAX_LEN; |
70 |
int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MAX_LEN; |
71 |
int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MAX_LEN; |
72 |
#else |
73 |
int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MIN_LEN; |
74 |
int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MIN_LEN; |
75 |
int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MIN_LEN; |
76 |
#endif /* PAX_ASLR_MAX_SEC */ |
77 |
|
78 |
|
79 |
SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0, |
80 |
"PaX (exploit mitigation) features."); |
81 |
SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0, |
82 |
"Address Space Layout Randomization."); |
83 |
|
84 |
SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status, |
85 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
86 |
NULL, 0, sysctl_pax_aslr_status, "I", |
87 |
"Restrictions status. " |
88 |
"0 - disabled, " |
89 |
"1 - enabled, " |
90 |
"2 - global enabled, " |
91 |
"3 - force global enabled"); |
92 |
TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status); |
93 |
|
94 |
SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode"); |
95 |
TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug); |
96 |
|
97 |
SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len, |
98 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
99 |
NULL, 0, sysctl_pax_aslr_mmap, "I", |
100 |
"Number of bits randomized for mmap(2) calls. " |
101 |
"32 bit: [8,16] 64 bit: [16,32]"); |
102 |
TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len); |
103 |
|
104 |
SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len, |
105 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
106 |
NULL, 0, sysctl_pax_aslr_stack, "I", |
107 |
"Number of bits randomized for the stack. " |
108 |
"32 bit: [6,12] 64 bit: [12,21]"); |
109 |
TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len); |
110 |
|
111 |
SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len, |
112 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
113 |
NULL, 0, sysctl_pax_aslr_exec, "I", |
114 |
"Number of bits randomized for the PIE exec base. " |
115 |
"32 bit: [6,12] 64 bit: [12,21]"); |
116 |
TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len); |
117 |
|
118 |
static int |
119 |
sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS) |
120 |
{ |
121 |
int err; |
122 |
int val; |
123 |
struct prison *pr=NULL; |
124 |
|
125 |
pr = pax_aslr_get_prison(req->td, NULL); |
126 |
|
127 |
if ((pr) && !(pr->pr_pax_set)) |
128 |
pax_aslr_init_prison(pr); |
129 |
|
130 |
val = (pr != NULL) ? pr->pr_pax_aslr_status : pax_aslr_status; |
131 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
132 |
if (err || !req->newptr) |
133 |
return (err); |
134 |
|
135 |
switch (val) { |
136 |
case PAX_ASLR_DISABLED: |
137 |
case PAX_ASLR_ENABLED: |
138 |
case PAX_ASLR_GLOBAL_ENABLED: |
139 |
case PAX_ASLR_FORCE_GLOBAL_ENABLED: |
140 |
pax_aslr_status = val; |
141 |
if (pr) |
142 |
pr->pr_pax_aslr_status = val; |
143 |
break; |
144 |
default: |
145 |
return (EINVAL); |
146 |
} |
147 |
|
148 |
return (0); |
149 |
} |
150 |
|
151 |
static int |
152 |
sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS) |
153 |
{ |
154 |
int err; |
155 |
int val; |
156 |
struct prison *pr=NULL; |
157 |
|
158 |
pr = pax_aslr_get_prison(req->td, NULL); |
159 |
|
160 |
if ((pr) && !(pr->pr_pax_set)) |
161 |
pax_aslr_init_prison(pr); |
162 |
|
163 |
val = (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len; |
164 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
165 |
if (err || !req->newptr) |
166 |
return (err); |
167 |
|
168 |
if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN |
169 |
|| val > PAX_ASLR_DELTA_MMAP_MAX_LEN) |
170 |
return (EINVAL); |
171 |
|
172 |
pax_aslr_mmap_len = val; |
173 |
if (pr) |
174 |
pr->pr_pax_aslr_mmap_len = val; |
175 |
|
176 |
return (0); |
177 |
} |
178 |
|
179 |
static int |
180 |
sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS) |
181 |
{ |
182 |
int err; |
183 |
int val; |
184 |
struct prison *pr=NULL; |
185 |
|
186 |
pr = pax_aslr_get_prison(req->td, NULL); |
187 |
|
188 |
if ((pr) && !(pr->pr_pax_set)) |
189 |
pax_aslr_init_prison(pr); |
190 |
|
191 |
val = (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len; |
192 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
193 |
if (err || !req->newptr) |
194 |
return (err); |
195 |
|
196 |
if (val < PAX_ASLR_DELTA_STACK_MIN_LEN |
197 |
|| val > PAX_ASLR_DELTA_STACK_MAX_LEN) |
198 |
return (EINVAL); |
199 |
|
200 |
pax_aslr_stack_len = val; |
201 |
if (pr) |
202 |
pr->pr_pax_aslr_stack_len = val; |
203 |
|
204 |
return (0); |
205 |
} |
206 |
|
207 |
static int |
208 |
sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS) |
209 |
{ |
210 |
int err; |
211 |
int val; |
212 |
struct prison *pr=NULL; |
213 |
|
214 |
pr = pax_aslr_get_prison(req->td, NULL); |
215 |
|
216 |
if ((pr) && !(pr->pr_pax_set)) |
217 |
pax_aslr_init_prison(pr); |
218 |
|
219 |
val = (pr != NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len; |
220 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
221 |
if (err || !req->newptr) |
222 |
return (err); |
223 |
|
224 |
if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN |
225 |
|| val > PAX_ASLR_DELTA_EXEC_MAX_LEN) |
226 |
return (EINVAL); |
227 |
|
228 |
pax_aslr_exec_len = val; |
229 |
if (pr) |
230 |
pr->pr_pax_aslr_exec_len = val; |
231 |
|
232 |
return (0); |
233 |
} |
234 |
|
235 |
/* |
236 |
* COMPAT_FREEBSD32 and linuxulator.. |
237 |
*/ |
238 |
#ifdef COMPAT_FREEBSD32 |
239 |
int pax_aslr_compat_status = PAX_ASLR_ENABLED; |
240 |
|
241 |
static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS); |
242 |
static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS); |
243 |
static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS); |
244 |
static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS); |
245 |
|
246 |
#ifdef PAX_ASLR_MAX_SEC |
247 |
int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN; |
248 |
int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN; |
249 |
int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN; |
250 |
#else |
251 |
int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN; |
252 |
int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN; |
253 |
int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN; |
254 |
#endif /* PAX_ASLR_MAX_SEC */ |
255 |
|
256 |
SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0, |
257 |
"Setting for COMPAT_FREEBSD32 and linuxulator."); |
258 |
|
259 |
SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status, |
260 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
261 |
NULL, 0, sysctl_pax_aslr_compat_status, "I", |
262 |
"Restrictions status. " |
263 |
"0 - disabled, " |
264 |
"1 - enabled, " |
265 |
"2 - global enabled, " |
266 |
"3 - force global enabled"); |
267 |
TUNABLE_INT("security.pax.aslr.compat.status", &pax_aslr_compat_status); |
268 |
|
269 |
SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len, |
270 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
271 |
NULL, 0, sysctl_pax_aslr_compat_mmap, "I", |
272 |
"Number of bits randomized for mmap(2) calls. " |
273 |
"32 bit: [8,16]"); |
274 |
TUNABLE_INT("security.pax.aslr.compat.mmap", &pax_aslr_compat_mmap_len); |
275 |
|
276 |
SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len, |
277 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
278 |
NULL, 0, sysctl_pax_aslr_compat_stack, "I", |
279 |
"Number of bits randomized for the stack. " |
280 |
"32 bit: [6,12]"); |
281 |
TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_stack_len); |
282 |
|
283 |
SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len, |
284 |
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON, |
285 |
NULL, 0, sysctl_pax_aslr_compat_exec, "I", |
286 |
"Number of bits randomized for the PIE exec base. " |
287 |
"32 bit: [6,12]"); |
288 |
TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_exec_len); |
289 |
|
290 |
|
291 |
static int |
292 |
sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS) |
293 |
{ |
294 |
int err; |
295 |
int val, *ptr; |
296 |
struct prison *pr=NULL; |
297 |
|
298 |
pr = pax_aslr_get_prison(req->td, NULL); |
299 |
ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_status) : &pax_aslr_compat_status; |
300 |
|
301 |
if ((pr) && !(pr->pr_pax_set)) |
302 |
pax_aslr_init_prison(pr); |
303 |
|
304 |
val = *ptr; |
305 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
306 |
if (err || !req->newptr) |
307 |
return (err); |
308 |
|
309 |
switch (val) { |
310 |
case PAX_ASLR_DISABLED: |
311 |
case PAX_ASLR_ENABLED: |
312 |
case PAX_ASLR_GLOBAL_ENABLED: |
313 |
case PAX_ASLR_FORCE_GLOBAL_ENABLED: |
314 |
pax_aslr_compat_status = val; |
315 |
*ptr = val; |
316 |
break; |
317 |
default: |
318 |
return (EINVAL); |
319 |
} |
320 |
|
321 |
return (0); |
322 |
} |
323 |
|
324 |
static int |
325 |
sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS) |
326 |
{ |
327 |
int err; |
328 |
int val, *ptr; |
329 |
struct prison *pr=NULL; |
330 |
|
331 |
pr = pax_aslr_get_prison(req->td, NULL); |
332 |
ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : &pax_aslr_compat_mmap_len; |
333 |
|
334 |
if ((pr) && !(pr->pr_pax_set)) |
335 |
pax_aslr_init_prison(pr); |
336 |
|
337 |
val = *ptr; |
338 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
339 |
if (err || !req->newptr) |
340 |
return (err); |
341 |
|
342 |
if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN |
343 |
|| val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN) |
344 |
return (EINVAL); |
345 |
|
346 |
pax_aslr_compat_mmap_len = val; |
347 |
*ptr = val; |
348 |
|
349 |
return (0); |
350 |
} |
351 |
|
352 |
static int |
353 |
sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS) |
354 |
{ |
355 |
int err; |
356 |
int val, *ptr; |
357 |
struct prison *pr=NULL; |
358 |
|
359 |
pr = pax_aslr_get_prison(req->td, NULL); |
360 |
ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : &pax_aslr_compat_stack_len; |
361 |
|
362 |
if ((pr) && !(pr->pr_pax_set)) |
363 |
pax_aslr_init_prison(pr); |
364 |
|
365 |
val = (pr != NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len; |
366 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
367 |
if (err || !req->newptr) |
368 |
return (err); |
369 |
|
370 |
if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN |
371 |
|| val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN) |
372 |
return (EINVAL); |
373 |
|
374 |
pax_aslr_compat_stack_len = val; |
375 |
*ptr = val; |
376 |
|
377 |
return (0); |
378 |
} |
379 |
|
380 |
static int |
381 |
sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS) |
382 |
{ |
383 |
int err; |
384 |
int val, *ptr; |
385 |
struct prison *pr=NULL; |
386 |
|
387 |
pr = pax_aslr_get_prison(req->td, NULL); |
388 |
ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : &pax_aslr_compat_exec_len; |
389 |
|
390 |
if ((pr) && !(pr->pr_pax_set)) |
391 |
pax_aslr_init_prison(pr); |
392 |
|
393 |
val = *ptr; |
394 |
err = sysctl_handle_int(oidp, &val, sizeof(int), req); |
395 |
if (err || !req->newptr) |
396 |
return (err); |
397 |
|
398 |
if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN |
399 |
|| val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN) |
400 |
return (EINVAL); |
401 |
|
402 |
pax_aslr_compat_exec_len = val; |
403 |
*ptr = val; |
404 |
|
405 |
return (0); |
406 |
} |
407 |
#endif /* COMPAT_FREEBSD32 */ |
408 |
|
409 |
|
410 |
/* |
411 |
* ASLR functions |
412 |
*/ |
413 |
bool |
414 |
pax_aslr_active(struct thread *td, struct proc *proc) |
415 |
{ |
416 |
int status; |
417 |
struct prison *pr=NULL; |
418 |
#ifdef notyet |
419 |
uint32_t flags; |
420 |
#endif /* notyet */ |
421 |
|
422 |
if (!(td) && !(proc)) |
423 |
return (true); |
424 |
|
425 |
#ifdef notyet |
426 |
flags = (td != NULL) ? td->td_proc->p_pax : proc->p_pax; |
427 |
#endif /* notyet */ |
428 |
pr = pax_aslr_get_prison(td, proc); |
429 |
|
430 |
if ((pr) && !(pr->pr_pax_set)) |
431 |
pax_aslr_init_prison(pr); |
432 |
|
433 |
status = (pr != NULL) ? pr->pr_pax_aslr_status : pax_aslr_status; |
434 |
|
435 |
switch (status) { |
436 |
case PAX_ASLR_DISABLED: |
437 |
return (false); |
438 |
case PAX_ASLR_FORCE_GLOBAL_ENABLED: |
439 |
return (true); |
440 |
case PAX_ASLR_ENABLED: |
441 |
#ifdef notyet |
442 |
if ((flags & ELF_NOTE_PAX_ASLR) == 0) |
443 |
return (false); |
444 |
#endif /* notyet */ |
445 |
break; |
446 |
case PAX_ASLR_GLOBAL_ENABLED: |
447 |
#ifdef notyet |
448 |
if ((flags & ELF_NOTE_PAX_NOASLR) != 0) |
449 |
return (false); |
450 |
#endif /* notyet */ |
451 |
break; |
452 |
default: |
453 |
return (true); |
454 |
} |
455 |
|
456 |
return (true); |
457 |
} |
458 |
|
459 |
struct prison * |
460 |
pax_aslr_get_prison(struct thread *td, struct proc *proc) |
461 |
{ |
462 |
if ((td)) { |
463 |
if ((td->td_proc) && (td->td_proc->p_ucred)) |
464 |
return td->td_proc->p_ucred->cr_prison; |
465 |
|
466 |
return NULL; |
467 |
} |
468 |
|
469 |
if (!(proc)) |
470 |
return NULL; |
471 |
|
472 |
return proc->p_ucred->cr_prison; |
473 |
} |
474 |
|
475 |
void |
476 |
pax_aslr_init_prison(struct prison *pr) |
477 |
{ |
478 |
if (!(pr)) |
479 |
return; |
480 |
|
481 |
if (pr->pr_pax_set) |
482 |
return; |
483 |
|
484 |
if (pax_aslr_debug) |
485 |
uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s ASLR variables\n", pr->pr_name); |
486 |
|
487 |
pr->pr_pax_aslr_status = pax_aslr_status; |
488 |
pr->pr_pax_aslr_debug = pax_aslr_debug; |
489 |
pr->pr_pax_aslr_mmap_len = pax_aslr_mmap_len; |
490 |
pr->pr_pax_aslr_stack_len = pax_aslr_stack_len; |
491 |
pr->pr_pax_aslr_exec_len = pax_aslr_exec_len; |
492 |
|
493 |
#ifdef COMPAT_FREEBSD32 |
494 |
pr->pr_pax_aslr_compat_status = pax_aslr_compat_status; |
495 |
pr->pr_pax_aslr_compat_mmap_len = pax_aslr_compat_mmap_len; |
496 |
pr->pr_pax_aslr_compat_stack_len = pax_aslr_compat_stack_len; |
497 |
pr->pr_pax_aslr_compat_exec_len = pax_aslr_compat_exec_len; |
498 |
#endif /* COMPAT_FREEBSD32 */ |
499 |
|
500 |
pr->pr_pax_set = 1; |
501 |
} |
502 |
|
503 |
void |
504 |
pax_aslr_init(struct thread *td, struct image_params *imgp) |
505 |
{ |
506 |
struct vmspace *vm; |
507 |
u_int sv_flags; |
508 |
struct prison *pr=NULL; |
509 |
|
510 |
pr = pax_aslr_get_prison(td, NULL); |
511 |
|
512 |
if ((pr) && !(pr->pr_pax_set)) |
513 |
pax_aslr_init_prison(pr); |
514 |
|
515 |
if (imgp == NULL) { |
516 |
panic("[PaX ASLR] pax_aslr_init - imgp == NULL"); |
517 |
} |
518 |
|
519 |
if (!pax_aslr_active(td, NULL)) |
520 |
return; |
521 |
|
522 |
vm = imgp->proc->p_vmspace; |
523 |
sv_flags = imgp->proc->p_sysent->sv_flags; |
524 |
|
525 |
#ifndef COMPAT_FREEBSD32 |
526 |
vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(), |
527 |
PAX_ASLR_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len); |
528 |
vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(), |
529 |
PAX_ASLR_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len); |
530 |
vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack); |
531 |
vm->vm_aslr_delta_exec = round_page(PAX_ASLR_DELTA(arc4random(), PAX_ASLR_DELTA_EXEC_LSB, (pr != NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len)); |
532 |
#else /* COMPAT_FREEBSD32 */ |
533 |
if ((sv_flags & SV_LP64) != 0) { |
534 |
vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(), |
535 |
PAX_ASLR_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len); |
536 |
vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(), |
537 |
PAX_ASLR_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len); |
538 |
vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack); |
539 |
} else { |
540 |
vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(), |
541 |
PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len); |
542 |
vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(), |
543 |
PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len); |
544 |
vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack); |
545 |
} |
546 |
#endif /* !COMPAT_FREEBSD32 */ |
547 |
} |
548 |
|
549 |
void |
550 |
pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t orig_addr, int flags) |
551 |
{ |
552 |
struct prison *pr=NULL; |
553 |
|
554 |
pr = pax_aslr_get_prison(td, NULL); |
555 |
|
556 |
if (!pax_aslr_active(td, NULL)) |
557 |
return; |
558 |
|
559 |
if (!(flags & MAP_FIXED) && ((orig_addr == 0) || !(flags & MAP_ANON))) { |
560 |
if (pax_aslr_debug) |
561 |
uprintf("[PaX ASLR] applying to %p orig_addr=%p f=%x\n", |
562 |
(void *)*addr, (void *)orig_addr, flags); |
563 |
if (!(td->td_proc->p_vmspace->vm_map.flags & MAP_ENTRY_GROWS_DOWN)) |
564 |
*addr += td->td_proc->p_vmspace->vm_aslr_delta_mmap; |
565 |
else |
566 |
*addr -= td->td_proc->p_vmspace->vm_aslr_delta_mmap; |
567 |
if (pax_aslr_debug) |
568 |
uprintf("[PaX ASLR] result %p\n", (void *)*addr); |
569 |
} |
570 |
else if (pax_aslr_debug) |
571 |
uprintf("[PaX ASLR] not applying to %p orig_addr=%p f=%x\n", |
572 |
(void *)*addr, (void *)orig_addr, flags); |
573 |
} |
574 |
|
575 |
void |
576 |
pax_aslr_stack(struct thread *td, char **addr, char *orig_addr) |
577 |
{ |
578 |
struct prison *pr=NULL; |
579 |
|
580 |
pr = pax_aslr_get_prison(td, NULL); |
581 |
|
582 |
if (!pax_aslr_active(td, NULL)) |
583 |
return; |
584 |
|
585 |
*addr -= td->td_proc->p_vmspace->vm_aslr_delta_stack; |
586 |
if ((pr) && pr->pr_pax_aslr_debug) |
587 |
uprintf("[PaX ASLR] orig_addr=%p, addr=%p\n", |
588 |
(void *)orig_addr, (void *)*addr); |
589 |
} |