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