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