kern_pax.c revision 1.56
1/* $NetBSD: kern_pax.c,v 1.56 2016/09/03 12:20:58 christos Exp $ */ 2 3/* 4 * Copyright (c) 2015 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Maxime Villard. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. The name of the author may not be used to endorse or promote products 45 * derived from this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59#include <sys/cdefs.h> 60__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.56 2016/09/03 12:20:58 christos Exp $"); 61 62#include "opt_pax.h" 63 64#include <sys/param.h> 65#include <sys/proc.h> 66#include <sys/exec.h> 67#include <sys/exec_elf.h> 68#include <sys/pax.h> 69#include <sys/sysctl.h> 70#include <sys/kmem.h> 71#include <sys/mman.h> 72#include <sys/fileassoc.h> 73#include <sys/syslog.h> 74#include <sys/vnode.h> 75#include <sys/queue.h> 76#include <sys/bitops.h> 77#include <sys/kauth.h> 78#include <sys/cprng.h> 79 80#ifdef PAX_ASLR_DEBUG 81#define PAX_DPRINTF(_fmt, args...) \ 82 do if (pax_aslr_debug) uprintf("%s: " _fmt "\n", __func__, ##args); \ 83 while (/*CONSTCOND*/0) 84#else 85#define PAX_DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0) 86#endif 87 88#ifdef PAX_ASLR 89#include <sys/mman.h> 90 91int pax_aslr_enabled = 1; 92int pax_aslr_global = PAX_ASLR; 93 94#ifndef PAX_ASLR_DELTA_MMAP_LSB 95#define PAX_ASLR_DELTA_MMAP_LSB PGSHIFT 96#endif 97#ifndef PAX_ASLR_DELTA_MMAP_LEN 98#define PAX_ASLR_DELTA_MMAP_LEN ((sizeof(void *) * NBBY) / 2) 99#endif 100#ifndef PAX_ASLR_DELTA_MMAP_LEN32 101#define PAX_ASLR_DELTA_MMAP_LEN32 ((sizeof(uint32_t) * NBBY) / 2) 102#endif 103#ifndef PAX_ASLR_DELTA_STACK_LSB 104#define PAX_ASLR_DELTA_STACK_LSB PGSHIFT 105#endif 106#ifndef PAX_ASLR_DELTA_STACK_LEN 107#define PAX_ASLR_DELTA_STACK_LEN ((sizeof(void *) * NBBY) / 4) 108#endif 109#ifndef PAX_ASLR_DELTA_STACK_LEN32 110#define PAX_ASLR_DELTA_STACK_LEN32 ((sizeof(uint32_t) * NBBY) / 4) 111#endif 112#define PAX_ASLR_MAX_STACK_WASTE 8 113 114static bool pax_aslr_elf_flags_active(uint32_t); 115#endif /* PAX_ASLR */ 116 117#ifdef PAX_MPROTECT 118static int pax_mprotect_enabled = 1; 119static int pax_mprotect_global = PAX_MPROTECT; 120static int pax_mprotect_ptrace = 1; 121static bool pax_mprotect_elf_flags_active(uint32_t); 122#endif /* PAX_MPROTECT */ 123#ifdef PAX_MPROTECT_DEBUG 124int pax_mprotect_debug; 125#endif 126 127#ifdef PAX_SEGVGUARD 128#ifndef PAX_SEGVGUARD_EXPIRY 129#define PAX_SEGVGUARD_EXPIRY (2 * 60) 130#endif 131#ifndef PAX_SEGVGUARD_SUSPENSION 132#define PAX_SEGVGUARD_SUSPENSION (10 * 60) 133#endif 134#ifndef PAX_SEGVGUARD_MAXCRASHES 135#define PAX_SEGVGUARD_MAXCRASHES 5 136#endif 137 138#ifdef PAX_ASLR_DEBUG 139int pax_aslr_debug; 140/* flag set means disable */ 141int pax_aslr_flags; 142uint32_t pax_aslr_rand; 143#define PAX_ASLR_STACK 0x01 144#define PAX_ASLR_STACK_GAP 0x02 145#define PAX_ASLR_MMAP 0x04 146#define PAX_ASLR_EXEC_OFFSET 0x08 147#define PAX_ASLR_RTLD_OFFSET 0x10 148#define PAX_ASLR_FIXED 0x20 149#endif 150 151static int pax_segvguard_enabled = 1; 152static int pax_segvguard_global = PAX_SEGVGUARD; 153static int pax_segvguard_expiry = PAX_SEGVGUARD_EXPIRY; 154static int pax_segvguard_suspension = PAX_SEGVGUARD_SUSPENSION; 155static int pax_segvguard_maxcrashes = PAX_SEGVGUARD_MAXCRASHES; 156 157static fileassoc_t segvguard_id; 158 159struct pax_segvguard_uid_entry { 160 uid_t sue_uid; 161 size_t sue_ncrashes; 162 time_t sue_expiry; 163 time_t sue_suspended; 164 LIST_ENTRY(pax_segvguard_uid_entry) sue_list; 165}; 166 167struct pax_segvguard_entry { 168 LIST_HEAD(, pax_segvguard_uid_entry) segv_uids; 169}; 170 171static bool pax_segvguard_elf_flags_active(uint32_t); 172static void pax_segvguard_cleanup_cb(void *); 173#endif /* PAX_SEGVGUARD */ 174 175SYSCTL_SETUP(sysctl_security_pax_setup, "sysctl security.pax setup") 176{ 177 const struct sysctlnode *rnode = NULL, *cnode; 178 179 sysctl_createv(clog, 0, NULL, &rnode, 180 CTLFLAG_PERMANENT, 181 CTLTYPE_NODE, "pax", 182 SYSCTL_DESCR("PaX (exploit mitigation) features."), 183 NULL, 0, NULL, 0, 184 CTL_SECURITY, CTL_CREATE, CTL_EOL); 185 186 cnode = rnode; 187 188#ifdef PAX_MPROTECT 189 rnode = cnode; 190 sysctl_createv(clog, 0, &rnode, &rnode, 191 CTLFLAG_PERMANENT, 192 CTLTYPE_NODE, "mprotect", 193 SYSCTL_DESCR("mprotect(2) W^X restrictions."), 194 NULL, 0, NULL, 0, 195 CTL_CREATE, CTL_EOL); 196 sysctl_createv(clog, 0, &rnode, NULL, 197 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 198 CTLTYPE_INT, "enabled", 199 SYSCTL_DESCR("Restrictions enabled."), 200 NULL, 0, &pax_mprotect_enabled, 0, 201 CTL_CREATE, CTL_EOL); 202 sysctl_createv(clog, 0, &rnode, NULL, 203 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 204 CTLTYPE_INT, "global", 205 SYSCTL_DESCR("When enabled, unless explicitly " 206 "specified, apply restrictions to " 207 "all processes."), 208 NULL, 0, &pax_mprotect_global, 0, 209 CTL_CREATE, CTL_EOL); 210 sysctl_createv(clog, 0, &rnode, NULL, 211 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 212 CTLTYPE_INT, "ptrace", 213 SYSCTL_DESCR("When enabled, allow ptrace(2) to " 214 "override mprotect permissions on traced " 215 "processes"), 216 NULL, 0, &pax_mprotect_ptrace, 0, 217 CTL_CREATE, CTL_EOL); 218#ifdef PAX_MPROTECT_DEBUG 219 sysctl_createv(clog, 0, &rnode, NULL, 220 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 221 CTLTYPE_INT, "debug", 222 SYSCTL_DESCR("print mprotect changes."), 223 NULL, 0, &pax_mprotect_debug, 0, 224 CTL_CREATE, CTL_EOL); 225#endif 226#endif /* PAX_MPROTECT */ 227 228#ifdef PAX_SEGVGUARD 229 rnode = cnode; 230 sysctl_createv(clog, 0, &rnode, &rnode, 231 CTLFLAG_PERMANENT, 232 CTLTYPE_NODE, "segvguard", 233 SYSCTL_DESCR("PaX segvguard."), 234 NULL, 0, NULL, 0, 235 CTL_CREATE, CTL_EOL); 236 sysctl_createv(clog, 0, &rnode, NULL, 237 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 238 CTLTYPE_INT, "enabled", 239 SYSCTL_DESCR("segvguard enabled."), 240 NULL, 0, &pax_segvguard_enabled, 0, 241 CTL_CREATE, CTL_EOL); 242 sysctl_createv(clog, 0, &rnode, NULL, 243 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 244 CTLTYPE_INT, "global", 245 SYSCTL_DESCR("segvguard all programs."), 246 NULL, 0, &pax_segvguard_global, 0, 247 CTL_CREATE, CTL_EOL); 248 sysctl_createv(clog, 0, &rnode, NULL, 249 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 250 CTLTYPE_INT, "expiry_timeout", 251 SYSCTL_DESCR("Entry expiry timeout (in seconds)."), 252 NULL, 0, &pax_segvguard_expiry, 0, 253 CTL_CREATE, CTL_EOL); 254 sysctl_createv(clog, 0, &rnode, NULL, 255 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 256 CTLTYPE_INT, "suspend_timeout", 257 SYSCTL_DESCR("Entry suspension timeout (in seconds)."), 258 NULL, 0, &pax_segvguard_suspension, 0, 259 CTL_CREATE, CTL_EOL); 260 sysctl_createv(clog, 0, &rnode, NULL, 261 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 262 CTLTYPE_INT, "max_crashes", 263 SYSCTL_DESCR("Max number of crashes before expiry."), 264 NULL, 0, &pax_segvguard_maxcrashes, 0, 265 CTL_CREATE, CTL_EOL); 266#endif /* PAX_SEGVGUARD */ 267 268#ifdef PAX_ASLR 269 rnode = cnode; 270 sysctl_createv(clog, 0, &rnode, &rnode, 271 CTLFLAG_PERMANENT, 272 CTLTYPE_NODE, "aslr", 273 SYSCTL_DESCR("Address Space Layout Randomization."), 274 NULL, 0, NULL, 0, 275 CTL_CREATE, CTL_EOL); 276 sysctl_createv(clog, 0, &rnode, NULL, 277 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 278 CTLTYPE_INT, "enabled", 279 SYSCTL_DESCR("Restrictions enabled."), 280 NULL, 0, &pax_aslr_enabled, 0, 281 CTL_CREATE, CTL_EOL); 282 sysctl_createv(clog, 0, &rnode, NULL, 283 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 284 CTLTYPE_INT, "global", 285 SYSCTL_DESCR("When enabled, unless explicitly " 286 "specified, apply to all processes."), 287 NULL, 0, &pax_aslr_global, 0, 288 CTL_CREATE, CTL_EOL); 289#ifdef PAX_ASLR_DEBUG 290 sysctl_createv(clog, 0, &rnode, NULL, 291 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 292 CTLTYPE_INT, "debug", 293 SYSCTL_DESCR("Pring ASLR selected addresses."), 294 NULL, 0, &pax_aslr_debug, 0, 295 CTL_CREATE, CTL_EOL); 296 sysctl_createv(clog, 0, &rnode, NULL, 297 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 298 CTLTYPE_INT, "flags", 299 SYSCTL_DESCR("Disable/Enable select ASLR features."), 300 NULL, 0, &pax_aslr_flags, 0, 301 CTL_CREATE, CTL_EOL); 302 sysctl_createv(clog, 0, &rnode, NULL, 303 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 304 CTLTYPE_INT, "rand", 305 SYSCTL_DESCR("Use the given fixed random value"), 306 NULL, 0, &pax_aslr_rand, 0, 307 CTL_CREATE, CTL_EOL); 308#endif 309 sysctl_createv(clog, 0, &rnode, NULL, 310 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 311 CTLTYPE_INT, "mmap_len", 312 SYSCTL_DESCR("Number of bits randomized for " 313 "mmap(2) calls."), 314 NULL, PAX_ASLR_DELTA_MMAP_LEN, NULL, 0, 315 CTL_CREATE, CTL_EOL); 316 sysctl_createv(clog, 0, &rnode, NULL, 317 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 318 CTLTYPE_INT, "stack_len", 319 SYSCTL_DESCR("Number of bits randomized for " 320 "the stack."), 321 NULL, PAX_ASLR_DELTA_STACK_LEN, NULL, 0, 322 CTL_CREATE, CTL_EOL); 323 sysctl_createv(clog, 0, &rnode, NULL, 324 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 325 CTLTYPE_INT, "exec_len", 326 SYSCTL_DESCR("Number of bits randomized for " 327 "the PIE exec base."), 328 NULL, PAX_ASLR_DELTA_EXEC_LEN, NULL, 0, 329 CTL_CREATE, CTL_EOL); 330 331#endif /* PAX_ASLR */ 332} 333 334/* 335 * Initialize PaX. 336 */ 337void 338pax_init(void) 339{ 340#ifdef PAX_SEGVGUARD 341 int error; 342 343 error = fileassoc_register("segvguard", pax_segvguard_cleanup_cb, 344 &segvguard_id); 345 if (error) { 346 panic("pax_init: segvguard_id: error=%d\n", error); 347 } 348#endif /* PAX_SEGVGUARD */ 349#ifdef PAX_ASLR 350 /* Adjust maximum stack by the size we can consume for ASLR */ 351 extern rlim_t maxsmap; 352 maxsmap = MAXSSIZ - (MAXSSIZ / PAX_ASLR_MAX_STACK_WASTE); 353 // XXX: compat32 is not handled. 354#endif 355} 356 357void 358pax_set_flags(struct exec_package *epp, struct proc *p) 359{ 360 p->p_pax = epp->ep_pax_flags; 361 362#ifdef PAX_MPROTECT 363 if (pax_mprotect_ptrace == 0) 364 return; 365 /* 366 * If we are running under the debugger, turn off MPROTECT so 367 * the debugger can insert/delete breakpoints 368 */ 369 if (p->p_slflag & PSL_TRACED) 370 p->p_pax &= ~P_PAX_MPROTECT; 371#endif 372} 373 374void 375pax_setup_elf_flags(struct exec_package *epp, uint32_t elf_flags) 376{ 377 uint32_t flags = 0; 378 379#ifdef PAX_ASLR 380 if (pax_aslr_elf_flags_active(elf_flags)) { 381 flags |= P_PAX_ASLR; 382 } 383#endif 384#ifdef PAX_MPROTECT 385 if (pax_mprotect_elf_flags_active(elf_flags)) { 386 flags |= P_PAX_MPROTECT; 387 } 388#endif 389#ifdef PAX_SEGVGUARD 390 if (pax_segvguard_elf_flags_active(elf_flags)) { 391 flags |= P_PAX_GUARD; 392 } 393#endif 394 395 epp->ep_pax_flags = flags; 396} 397 398#if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) || defined(PAX_ASLR) 399static inline bool 400pax_flags_active(uint32_t flags, uint32_t opt) 401{ 402 if (!(flags & opt)) 403 return false; 404 return true; 405} 406#endif /* PAX_MPROTECT || PAX_SEGVGUARD || PAX_ASLR */ 407 408#ifdef PAX_MPROTECT 409static bool 410pax_mprotect_elf_flags_active(uint32_t flags) 411{ 412 if (!pax_mprotect_enabled) 413 return false; 414 if (pax_mprotect_global && (flags & ELF_NOTE_PAX_NOMPROTECT) != 0) { 415 /* Mprotect explicitly disabled */ 416 return false; 417 } 418 if (!pax_mprotect_global && (flags & ELF_NOTE_PAX_MPROTECT) == 0) { 419 /* Mprotect not requested */ 420 return false; 421 } 422 return true; 423} 424 425void 426pax_mprotect_adjust( 427#ifdef PAX_MPROTECT_DEBUG 428 const char *file, size_t line, 429#endif 430 struct lwp *l, vm_prot_t *prot, vm_prot_t *maxprot) 431{ 432 uint32_t flags; 433 434 flags = l->l_proc->p_pax; 435 if (!pax_flags_active(flags, P_PAX_MPROTECT)) 436 return; 437 438 if ((*prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) != VM_PROT_EXECUTE) { 439#ifdef PAX_MPROTECT_DEBUG 440 struct proc *p = l->l_proc; 441 if ((*prot & VM_PROT_EXECUTE) && pax_mprotect_debug) { 442 printf("%s: %s,%zu: %d.%d (%s): -x\n", 443 __func__, file, line, 444 p->p_pid, l->l_lid, p->p_comm); 445 } 446#endif 447 *prot &= ~VM_PROT_EXECUTE; 448 *maxprot &= ~VM_PROT_EXECUTE; 449 } else { 450#ifdef PAX_MPROTECT_DEBUG 451 struct proc *p = l->l_proc; 452 if ((*prot & VM_PROT_WRITE) && pax_mprotect_debug) { 453 printf("%s: %s,%zu: %d.%d (%s): -w\n", 454 __func__, file, line, 455 p->p_pid, l->l_lid, p->p_comm); 456 } 457#endif 458 *prot &= ~VM_PROT_WRITE; 459 *maxprot &= ~VM_PROT_WRITE; 460 } 461} 462 463/* 464 * Bypass MPROTECT for traced processes 465 */ 466int 467pax_mprotect_prot(struct lwp *l) 468{ 469 uint32_t flags; 470 471 flags = l->l_proc->p_pax; 472 if (!pax_flags_active(flags, P_PAX_MPROTECT)) 473 return 0; 474 if (pax_mprotect_ptrace < 2) 475 return 0; 476 return UVM_EXTRACT_PROT_ALL; 477} 478 479 480#endif /* PAX_MPROTECT */ 481 482#ifdef PAX_ASLR 483static bool 484pax_aslr_elf_flags_active(uint32_t flags) 485{ 486 if (!pax_aslr_enabled) 487 return false; 488 if (pax_aslr_global && (flags & ELF_NOTE_PAX_NOASLR) != 0) { 489 /* ASLR explicitly disabled */ 490 return false; 491 } 492 if (!pax_aslr_global && (flags & ELF_NOTE_PAX_ASLR) == 0) { 493 /* ASLR not requested */ 494 return false; 495 } 496 return true; 497} 498 499static bool 500pax_aslr_epp_active(struct exec_package *epp) 501{ 502 if (__predict_false((epp->ep_flags & (EXEC_32|EXEC_TOPDOWN_VM)) == 0)) 503 return false; 504 return pax_flags_active(epp->ep_pax_flags, P_PAX_ASLR); 505} 506 507static bool 508pax_aslr_active(struct lwp *l) 509{ 510 return pax_flags_active(l->l_proc->p_pax, P_PAX_ASLR); 511} 512 513void 514pax_aslr_init_vm(struct lwp *l, struct vmspace *vm, struct exec_package *ep) 515{ 516 if (!pax_aslr_active(l)) 517 return; 518 519 if (__predict_false((ep->ep_flags & (EXEC_32|EXEC_TOPDOWN_VM)) == 0)) 520 return; 521 522#ifdef PAX_ASLR_DEBUG 523 if (pax_aslr_flags & PAX_ASLR_MMAP) 524 return; 525#endif 526 527 uint32_t len = (ep->ep_flags & EXEC_32) ? 528 PAX_ASLR_DELTA_MMAP_LEN32 : PAX_ASLR_DELTA_MMAP_LEN; 529 530 uint32_t rand = cprng_fast32(); 531#ifdef PAX_ASLR_DEBUG 532 if (pax_aslr_flags & PAX_ASLR_FIXED) 533 rand = pax_aslr_rand; 534#endif 535 vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand, 536 PAX_ASLR_DELTA_MMAP_LSB, len); 537 538 PAX_DPRINTF("delta_mmap=%#jx/%u", 539 (uintmax_t)vm->vm_aslr_delta_mmap, len); 540} 541 542void 543pax_aslr_mmap(struct lwp *l, vaddr_t *addr, vaddr_t orig_addr, int f) 544{ 545 if (!pax_aslr_active(l)) 546 return; 547#ifdef PAX_ASLR_DEBUG 548 char buf[256]; 549 550 if (pax_aslr_flags & PAX_ASLR_MMAP) 551 return; 552 553 if (pax_aslr_debug) 554 snprintb(buf, sizeof(buf), MAP_FMT, f); 555 else 556 buf[0] = '\0'; 557#endif 558 559 if (!(f & MAP_FIXED) && ((orig_addr == 0) || !(f & MAP_ANON))) { 560 PAX_DPRINTF("applying to %#jx orig_addr=%#jx f=%s", 561 (uintmax_t)*addr, (uintmax_t)orig_addr, buf); 562 if (!(l->l_proc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)) 563 *addr += l->l_proc->p_vmspace->vm_aslr_delta_mmap; 564 else 565 *addr -= l->l_proc->p_vmspace->vm_aslr_delta_mmap; 566 PAX_DPRINTF("result %#jx", (uintmax_t)*addr); 567 } else { 568 PAX_DPRINTF("not applying to %#jx orig_addr=%#jx f=%s", 569 (uintmax_t)*addr, (uintmax_t)orig_addr, buf); 570 } 571} 572 573static vaddr_t 574pax_aslr_offset(vaddr_t align) 575{ 576 size_t pax_align, l2, delta; 577 uint32_t rand; 578 vaddr_t offset; 579 580 pax_align = align == 0 ? PGSHIFT : align; 581 l2 = ilog2(pax_align); 582 583 rand = cprng_fast32(); 584#ifdef PAX_ASLR_DEBUG 585 if (pax_aslr_flags & PAX_ASLR_FIXED) 586 rand = pax_aslr_rand; 587#endif 588 589#define PAX_TRUNC(a, b) ((a) & ~((b) - 1)) 590 591 delta = PAX_ASLR_DELTA(rand, l2, PAX_ASLR_DELTA_EXEC_LEN); 592 offset = PAX_TRUNC(delta, pax_align) + PAGE_SIZE; 593 594 PAX_DPRINTF("rand=%#x l2=%#zx pax_align=%#zx delta=%#zx offset=%#jx", 595 rand, l2, pax_align, delta, (uintmax_t)offset); 596 597 return offset; 598} 599 600vaddr_t 601pax_aslr_exec_offset(struct exec_package *epp, vaddr_t align) 602{ 603 if (!pax_aslr_epp_active(epp)) 604 goto out; 605 606#ifdef PAX_ASLR_DEBUG 607 if (pax_aslr_flags & PAX_ASLR_EXEC_OFFSET) 608 goto out; 609#endif 610 return pax_aslr_offset(align) + PAGE_SIZE; 611out: 612 return MAX(align, PAGE_SIZE); 613} 614 615voff_t 616pax_aslr_rtld_offset(struct exec_package *epp, vaddr_t align, int use_topdown) 617{ 618 voff_t offset; 619 620 if (!pax_aslr_epp_active(epp)) 621 return 0; 622 623#ifdef PAX_ASLR_DEBUG 624 if (pax_aslr_flags & PAX_ASLR_RTLD_OFFSET) 625 return 0; 626#endif 627 offset = pax_aslr_offset(align); 628 if (use_topdown) 629 offset = -offset; 630 631 return offset; 632} 633 634void 635pax_aslr_stack(struct exec_package *epp, vsize_t *max_stack_size) 636{ 637 if (!pax_aslr_epp_active(epp)) 638 return; 639#ifdef PAX_ASLR_DEBUG 640 if (pax_aslr_flags & PAX_ASLR_STACK) 641 return; 642#endif 643 644 uint32_t len = (epp->ep_flags & EXEC_32) ? 645 PAX_ASLR_DELTA_STACK_LEN32 : PAX_ASLR_DELTA_STACK_LEN; 646 uint32_t rand = cprng_fast32(); 647#ifdef PAX_ASLR_DEBUG 648 if (pax_aslr_flags & PAX_ASLR_FIXED) 649 rand = pax_aslr_rand; 650#endif 651 u_long d = PAX_ASLR_DELTA(rand, PAX_ASLR_DELTA_STACK_LSB, len); 652 d &= (*max_stack_size / PAX_ASLR_MAX_STACK_WASTE) - 1; 653 u_long newminsaddr = (u_long)STACK_GROW(epp->ep_minsaddr, d); 654 PAX_DPRINTF("old minsaddr=%#jx delta=%#lx new minsaddr=%#lx", 655 (uintmax_t)epp->ep_minsaddr, d, newminsaddr); 656 epp->ep_minsaddr = (vaddr_t)newminsaddr; 657 *max_stack_size -= d; 658} 659 660uint32_t 661pax_aslr_stack_gap(struct exec_package *epp) 662{ 663 if (!pax_aslr_epp_active(epp)) 664 return 0; 665 666#ifdef PAX_ASLR_DEBUG 667 if (pax_aslr_flags & PAX_ASLR_STACK_GAP) 668 return 0; 669#endif 670 671 uint32_t rand = cprng_fast32(); 672#ifdef PAX_ASLR_DEBUG 673 if (pax_aslr_flags & PAX_ASLR_FIXED) 674 rand = pax_aslr_rand; 675#endif 676 rand %= PAGE_SIZE; 677 PAX_DPRINTF("stack gap=%#x\n", rand); 678 return rand; 679} 680#endif /* PAX_ASLR */ 681 682#ifdef PAX_SEGVGUARD 683static bool 684pax_segvguard_elf_flags_active(uint32_t flags) 685{ 686 if (!pax_segvguard_enabled) 687 return false; 688 if (pax_segvguard_global && (flags & ELF_NOTE_PAX_NOGUARD) != 0) { 689 /* Segvguard explicitly disabled */ 690 return false; 691 } 692 if (!pax_segvguard_global && (flags & ELF_NOTE_PAX_GUARD) == 0) { 693 /* Segvguard not requested */ 694 return false; 695 } 696 return true; 697} 698 699static void 700pax_segvguard_cleanup_cb(void *v) 701{ 702 struct pax_segvguard_entry *p = v; 703 struct pax_segvguard_uid_entry *up; 704 705 if (p == NULL) { 706 return; 707 } 708 while ((up = LIST_FIRST(&p->segv_uids)) != NULL) { 709 LIST_REMOVE(up, sue_list); 710 kmem_free(up, sizeof(*up)); 711 } 712 kmem_free(p, sizeof(*p)); 713} 714 715/* 716 * Called when a process of image vp generated a segfault. 717 */ 718int 719pax_segvguard(struct lwp *l, struct vnode *vp, const char *name, 720 bool crashed) 721{ 722 struct pax_segvguard_entry *p; 723 struct pax_segvguard_uid_entry *up; 724 struct timeval tv; 725 uid_t uid; 726 uint32_t flags; 727 bool have_uid; 728 729 flags = l->l_proc->p_pax; 730 if (!pax_flags_active(flags, P_PAX_GUARD)) 731 return 0; 732 733 if (vp == NULL) 734 return EFAULT; 735 736 /* Check if we already monitor the file. */ 737 p = fileassoc_lookup(vp, segvguard_id); 738 739 /* Fast-path if starting a program we don't know. */ 740 if (p == NULL && !crashed) 741 return 0; 742 743 microtime(&tv); 744 745 /* 746 * If a program we don't know crashed, we need to create a new entry 747 * for it. 748 */ 749 if (p == NULL) { 750 p = kmem_alloc(sizeof(*p), KM_SLEEP); 751 fileassoc_add(vp, segvguard_id, p); 752 LIST_INIT(&p->segv_uids); 753 754 /* 755 * Initialize a new entry with "crashes so far" of 1. 756 * The expiry time is when we purge the entry if it didn't 757 * reach the limit. 758 */ 759 up = kmem_alloc(sizeof(*up), KM_SLEEP); 760 up->sue_uid = kauth_cred_getuid(l->l_cred); 761 up->sue_ncrashes = 1; 762 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 763 up->sue_suspended = 0; 764 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list); 765 return 0; 766 } 767 768 /* 769 * A program we "know" either executed or crashed again. 770 * See if it's a culprit we're familiar with. 771 */ 772 uid = kauth_cred_getuid(l->l_cred); 773 have_uid = false; 774 LIST_FOREACH(up, &p->segv_uids, sue_list) { 775 if (up->sue_uid == uid) { 776 have_uid = true; 777 break; 778 } 779 } 780 781 /* 782 * It's someone else. Add an entry for him if we crashed. 783 */ 784 if (!have_uid) { 785 if (crashed) { 786 up = kmem_alloc(sizeof(*up), KM_SLEEP); 787 up->sue_uid = uid; 788 up->sue_ncrashes = 1; 789 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 790 up->sue_suspended = 0; 791 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list); 792 } 793 return 0; 794 } 795 796 if (crashed) { 797 /* Check if timer on previous crashes expired first. */ 798 if (up->sue_expiry < tv.tv_sec) { 799 log(LOG_INFO, "PaX Segvguard: [%s] Suspension" 800 " expired.\n", name ? name : "unknown"); 801 up->sue_ncrashes = 1; 802 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 803 up->sue_suspended = 0; 804 return 0; 805 } 806 807 up->sue_ncrashes++; 808 809 if (up->sue_ncrashes >= pax_segvguard_maxcrashes) { 810 log(LOG_ALERT, "PaX Segvguard: [%s] Suspending " 811 "execution for %d seconds after %zu crashes.\n", 812 name ? name : "unknown", pax_segvguard_suspension, 813 up->sue_ncrashes); 814 815 /* Suspend this program for a while. */ 816 up->sue_suspended = tv.tv_sec + pax_segvguard_suspension; 817 up->sue_ncrashes = 0; 818 up->sue_expiry = 0; 819 } 820 } else { 821 /* Are we supposed to be suspended? */ 822 if (up->sue_suspended > tv.tv_sec) { 823 log(LOG_ALERT, "PaX Segvguard: [%s] Preventing " 824 "execution due to repeated segfaults.\n", name ? 825 name : "unknown"); 826 return EPERM; 827 } 828 } 829 830 return 0; 831} 832#endif /* PAX_SEGVGUARD */ 833