Mon Apr 13 16:36:12 2015 UTC ()
<sys/rnd.h> not needed for kern_pax.c.


(riastradh)
diff -r1.27 -r1.28 src/sys/kern/kern_pax.c

cvs diff -r1.27 -r1.28 src/sys/kern/kern_pax.c (switch to unified diff)

--- src/sys/kern/kern_pax.c 2014/02/25 18:30:11 1.27
+++ src/sys/kern/kern_pax.c 2015/04/13 16:36:12 1.28
@@ -1,501 +1,500 @@ @@ -1,501 +1,500 @@
1/* $NetBSD: kern_pax.c,v 1.27 2014/02/25 18:30:11 pooka Exp $ */ 1/* $NetBSD: kern_pax.c,v 1.28 2015/04/13 16:36:12 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> 4 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products 15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission. 16 * derived from this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.27 2014/02/25 18:30:11 pooka Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.28 2015/04/13 16:36:12 riastradh Exp $");
32 32
33#include "opt_pax.h" 33#include "opt_pax.h"
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/proc.h> 36#include <sys/proc.h>
37#include <sys/exec_elf.h> 37#include <sys/exec_elf.h>
38#include <sys/pax.h> 38#include <sys/pax.h>
39#include <sys/sysctl.h> 39#include <sys/sysctl.h>
40#include <sys/kmem.h> 40#include <sys/kmem.h>
41#include <sys/fileassoc.h> 41#include <sys/fileassoc.h>
42#include <sys/syslog.h> 42#include <sys/syslog.h>
43#include <sys/vnode.h> 43#include <sys/vnode.h>
44#include <sys/queue.h> 44#include <sys/queue.h>
45#include <sys/kauth.h> 45#include <sys/kauth.h>
46#include <sys/cprng.h> 46#include <sys/cprng.h>
47 47
48#ifdef PAX_ASLR 48#ifdef PAX_ASLR
49#include <sys/mman.h> 49#include <sys/mman.h>
50#include <sys/rnd.h> 
51#include <sys/exec.h> 50#include <sys/exec.h>
52 51
53int pax_aslr_enabled = 1; 52int pax_aslr_enabled = 1;
54int pax_aslr_global = PAX_ASLR; 53int pax_aslr_global = PAX_ASLR;
55 54
56#ifndef PAX_ASLR_DELTA_MMAP_LSB 55#ifndef PAX_ASLR_DELTA_MMAP_LSB
57#define PAX_ASLR_DELTA_MMAP_LSB PGSHIFT 56#define PAX_ASLR_DELTA_MMAP_LSB PGSHIFT
58#endif 57#endif
59#ifndef PAX_ASLR_DELTA_MMAP_LEN 58#ifndef PAX_ASLR_DELTA_MMAP_LEN
60#define PAX_ASLR_DELTA_MMAP_LEN ((sizeof(void *) * NBBY) / 2) 59#define PAX_ASLR_DELTA_MMAP_LEN ((sizeof(void *) * NBBY) / 2)
61#endif 60#endif
62#ifndef PAX_ASLR_DELTA_STACK_LSB 61#ifndef PAX_ASLR_DELTA_STACK_LSB
63#define PAX_ASLR_DELTA_STACK_LSB PGSHIFT 62#define PAX_ASLR_DELTA_STACK_LSB PGSHIFT
64#endif 63#endif
65#ifndef PAX_ASLR_DELTA_STACK_LEN 64#ifndef PAX_ASLR_DELTA_STACK_LEN
66#define PAX_ASLR_DELTA_STACK_LEN 12 65#define PAX_ASLR_DELTA_STACK_LEN 12
67#endif 66#endif
68 67
69#endif /* PAX_ASLR */ 68#endif /* PAX_ASLR */
70 69
71#ifdef PAX_MPROTECT 70#ifdef PAX_MPROTECT
72static int pax_mprotect_enabled = 1; 71static int pax_mprotect_enabled = 1;
73static int pax_mprotect_global = PAX_MPROTECT; 72static int pax_mprotect_global = PAX_MPROTECT;
74#endif /* PAX_MPROTECT */ 73#endif /* PAX_MPROTECT */
75 74
76#ifdef PAX_SEGVGUARD 75#ifdef PAX_SEGVGUARD
77#ifndef PAX_SEGVGUARD_EXPIRY 76#ifndef PAX_SEGVGUARD_EXPIRY
78#define PAX_SEGVGUARD_EXPIRY (2 * 60) 77#define PAX_SEGVGUARD_EXPIRY (2 * 60)
79#endif 78#endif
80 79
81#ifndef PAX_SEGVGUARD_SUSPENSION 80#ifndef PAX_SEGVGUARD_SUSPENSION
82#define PAX_SEGVGUARD_SUSPENSION (10 * 60) 81#define PAX_SEGVGUARD_SUSPENSION (10 * 60)
83#endif 82#endif
84 83
85#ifndef PAX_SEGVGUARD_MAXCRASHES 84#ifndef PAX_SEGVGUARD_MAXCRASHES
86#define PAX_SEGVGUARD_MAXCRASHES 5 85#define PAX_SEGVGUARD_MAXCRASHES 5
87#endif 86#endif
88 87
89static int pax_segvguard_enabled = 1; 88static int pax_segvguard_enabled = 1;
90static int pax_segvguard_global = PAX_SEGVGUARD; 89static int pax_segvguard_global = PAX_SEGVGUARD;
91static int pax_segvguard_expiry = PAX_SEGVGUARD_EXPIRY; 90static int pax_segvguard_expiry = PAX_SEGVGUARD_EXPIRY;
92static int pax_segvguard_suspension = PAX_SEGVGUARD_SUSPENSION; 91static int pax_segvguard_suspension = PAX_SEGVGUARD_SUSPENSION;
93static int pax_segvguard_maxcrashes = PAX_SEGVGUARD_MAXCRASHES; 92static int pax_segvguard_maxcrashes = PAX_SEGVGUARD_MAXCRASHES;
94 93
95static fileassoc_t segvguard_id; 94static fileassoc_t segvguard_id;
96 95
97struct pax_segvguard_uid_entry { 96struct pax_segvguard_uid_entry {
98 uid_t sue_uid; 97 uid_t sue_uid;
99 size_t sue_ncrashes; 98 size_t sue_ncrashes;
100 time_t sue_expiry; 99 time_t sue_expiry;
101 time_t sue_suspended; 100 time_t sue_suspended;
102 LIST_ENTRY(pax_segvguard_uid_entry) sue_list; 101 LIST_ENTRY(pax_segvguard_uid_entry) sue_list;
103}; 102};
104 103
105struct pax_segvguard_entry { 104struct pax_segvguard_entry {
106 LIST_HEAD(, pax_segvguard_uid_entry) segv_uids; 105 LIST_HEAD(, pax_segvguard_uid_entry) segv_uids;
107}; 106};
108 107
109static void pax_segvguard_cb(void *); 108static void pax_segvguard_cb(void *);
110#endif /* PAX_SEGVGUARD */ 109#endif /* PAX_SEGVGUARD */
111 110
112/* PaX internal setspecific flags */ 111/* PaX internal setspecific flags */
113#define PAX_MPROTECT_EXPLICIT_ENABLE (void *)0x01 112#define PAX_MPROTECT_EXPLICIT_ENABLE (void *)0x01
114#define PAX_MPROTECT_EXPLICIT_DISABLE (void *)0x02 113#define PAX_MPROTECT_EXPLICIT_DISABLE (void *)0x02
115#define PAX_SEGVGUARD_EXPLICIT_ENABLE (void *)0x03 114#define PAX_SEGVGUARD_EXPLICIT_ENABLE (void *)0x03
116#define PAX_SEGVGUARD_EXPLICIT_DISABLE (void *)0x04 115#define PAX_SEGVGUARD_EXPLICIT_DISABLE (void *)0x04
117#define PAX_ASLR_EXPLICIT_ENABLE (void *)0x05 116#define PAX_ASLR_EXPLICIT_ENABLE (void *)0x05
118#define PAX_ASLR_EXPLICIT_DISABLE (void *)0x06 117#define PAX_ASLR_EXPLICIT_DISABLE (void *)0x06
119 118
120SYSCTL_SETUP(sysctl_security_pax_setup, "sysctl security.pax setup") 119SYSCTL_SETUP(sysctl_security_pax_setup, "sysctl security.pax setup")
121{ 120{
122 const struct sysctlnode *rnode = NULL, *cnode; 121 const struct sysctlnode *rnode = NULL, *cnode;
123 122
124 sysctl_createv(clog, 0, NULL, &rnode, 123 sysctl_createv(clog, 0, NULL, &rnode,
125 CTLFLAG_PERMANENT, 124 CTLFLAG_PERMANENT,
126 CTLTYPE_NODE, "pax", 125 CTLTYPE_NODE, "pax",
127 SYSCTL_DESCR("PaX (exploit mitigation) features."), 126 SYSCTL_DESCR("PaX (exploit mitigation) features."),
128 NULL, 0, NULL, 0, 127 NULL, 0, NULL, 0,
129 CTL_SECURITY, CTL_CREATE, CTL_EOL); 128 CTL_SECURITY, CTL_CREATE, CTL_EOL);
130 129
131 cnode = rnode; 130 cnode = rnode;
132 131
133#ifdef PAX_MPROTECT 132#ifdef PAX_MPROTECT
134 rnode = cnode; 133 rnode = cnode;
135 sysctl_createv(clog, 0, &rnode, &rnode, 134 sysctl_createv(clog, 0, &rnode, &rnode,
136 CTLFLAG_PERMANENT, 135 CTLFLAG_PERMANENT,
137 CTLTYPE_NODE, "mprotect", 136 CTLTYPE_NODE, "mprotect",
138 SYSCTL_DESCR("mprotect(2) W^X restrictions."), 137 SYSCTL_DESCR("mprotect(2) W^X restrictions."),
139 NULL, 0, NULL, 0, 138 NULL, 0, NULL, 0,
140 CTL_CREATE, CTL_EOL); 139 CTL_CREATE, CTL_EOL);
141 sysctl_createv(clog, 0, &rnode, NULL, 140 sysctl_createv(clog, 0, &rnode, NULL,
142 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 141 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
143 CTLTYPE_INT, "enabled", 142 CTLTYPE_INT, "enabled",
144 SYSCTL_DESCR("Restrictions enabled."), 143 SYSCTL_DESCR("Restrictions enabled."),
145 NULL, 0, &pax_mprotect_enabled, 0, 144 NULL, 0, &pax_mprotect_enabled, 0,
146 CTL_CREATE, CTL_EOL); 145 CTL_CREATE, CTL_EOL);
147 sysctl_createv(clog, 0, &rnode, NULL, 146 sysctl_createv(clog, 0, &rnode, NULL,
148 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 147 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
149 CTLTYPE_INT, "global", 148 CTLTYPE_INT, "global",
150 SYSCTL_DESCR("When enabled, unless explicitly " 149 SYSCTL_DESCR("When enabled, unless explicitly "
151 "specified, apply restrictions to " 150 "specified, apply restrictions to "
152 "all processes."), 151 "all processes."),
153 NULL, 0, &pax_mprotect_global, 0, 152 NULL, 0, &pax_mprotect_global, 0,
154 CTL_CREATE, CTL_EOL); 153 CTL_CREATE, CTL_EOL);
155#endif /* PAX_MPROTECT */ 154#endif /* PAX_MPROTECT */
156 155
157#ifdef PAX_SEGVGUARD 156#ifdef PAX_SEGVGUARD
158 rnode = cnode; 157 rnode = cnode;
159 sysctl_createv(clog, 0, &rnode, &rnode, 158 sysctl_createv(clog, 0, &rnode, &rnode,
160 CTLFLAG_PERMANENT, 159 CTLFLAG_PERMANENT,
161 CTLTYPE_NODE, "segvguard", 160 CTLTYPE_NODE, "segvguard",
162 SYSCTL_DESCR("PaX segvguard."), 161 SYSCTL_DESCR("PaX segvguard."),
163 NULL, 0, NULL, 0, 162 NULL, 0, NULL, 0,
164 CTL_CREATE, CTL_EOL); 163 CTL_CREATE, CTL_EOL);
165 sysctl_createv(clog, 0, &rnode, NULL, 164 sysctl_createv(clog, 0, &rnode, NULL,
166 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 165 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
167 CTLTYPE_INT, "enabled", 166 CTLTYPE_INT, "enabled",
168 SYSCTL_DESCR("segvguard enabled."), 167 SYSCTL_DESCR("segvguard enabled."),
169 NULL, 0, &pax_segvguard_enabled, 0, 168 NULL, 0, &pax_segvguard_enabled, 0,
170 CTL_CREATE, CTL_EOL); 169 CTL_CREATE, CTL_EOL);
171 sysctl_createv(clog, 0, &rnode, NULL, 170 sysctl_createv(clog, 0, &rnode, NULL,
172 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 171 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
173 CTLTYPE_INT, "global", 172 CTLTYPE_INT, "global",
174 SYSCTL_DESCR("segvguard all programs."), 173 SYSCTL_DESCR("segvguard all programs."),
175 NULL, 0, &pax_segvguard_global, 0, 174 NULL, 0, &pax_segvguard_global, 0,
176 CTL_CREATE, CTL_EOL); 175 CTL_CREATE, CTL_EOL);
177 sysctl_createv(clog, 0, &rnode, NULL, 176 sysctl_createv(clog, 0, &rnode, NULL,
178 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 177 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
179 CTLTYPE_INT, "expiry_timeout", 178 CTLTYPE_INT, "expiry_timeout",
180 SYSCTL_DESCR("Entry expiry timeout (in seconds)."), 179 SYSCTL_DESCR("Entry expiry timeout (in seconds)."),
181 NULL, 0, &pax_segvguard_expiry, 0, 180 NULL, 0, &pax_segvguard_expiry, 0,
182 CTL_CREATE, CTL_EOL); 181 CTL_CREATE, CTL_EOL);
183 sysctl_createv(clog, 0, &rnode, NULL, 182 sysctl_createv(clog, 0, &rnode, NULL,
184 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 183 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
185 CTLTYPE_INT, "suspend_timeout", 184 CTLTYPE_INT, "suspend_timeout",
186 SYSCTL_DESCR("Entry suspension timeout (in seconds)."), 185 SYSCTL_DESCR("Entry suspension timeout (in seconds)."),
187 NULL, 0, &pax_segvguard_suspension, 0, 186 NULL, 0, &pax_segvguard_suspension, 0,
188 CTL_CREATE, CTL_EOL); 187 CTL_CREATE, CTL_EOL);
189 sysctl_createv(clog, 0, &rnode, NULL, 188 sysctl_createv(clog, 0, &rnode, NULL,
190 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 189 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
191 CTLTYPE_INT, "max_crashes", 190 CTLTYPE_INT, "max_crashes",
192 SYSCTL_DESCR("Max number of crashes before expiry."), 191 SYSCTL_DESCR("Max number of crashes before expiry."),
193 NULL, 0, &pax_segvguard_maxcrashes, 0, 192 NULL, 0, &pax_segvguard_maxcrashes, 0,
194 CTL_CREATE, CTL_EOL); 193 CTL_CREATE, CTL_EOL);
195#endif /* PAX_SEGVGUARD */ 194#endif /* PAX_SEGVGUARD */
196 195
197#ifdef PAX_ASLR 196#ifdef PAX_ASLR
198 rnode = cnode; 197 rnode = cnode;
199 sysctl_createv(clog, 0, &rnode, &rnode, 198 sysctl_createv(clog, 0, &rnode, &rnode,
200 CTLFLAG_PERMANENT, 199 CTLFLAG_PERMANENT,
201 CTLTYPE_NODE, "aslr", 200 CTLTYPE_NODE, "aslr",
202 SYSCTL_DESCR("Address Space Layout Randomization."), 201 SYSCTL_DESCR("Address Space Layout Randomization."),
203 NULL, 0, NULL, 0, 202 NULL, 0, NULL, 0,
204 CTL_CREATE, CTL_EOL); 203 CTL_CREATE, CTL_EOL);
205 sysctl_createv(clog, 0, &rnode, NULL, 204 sysctl_createv(clog, 0, &rnode, NULL,
206 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 205 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
207 CTLTYPE_INT, "enabled", 206 CTLTYPE_INT, "enabled",
208 SYSCTL_DESCR("Restrictions enabled."), 207 SYSCTL_DESCR("Restrictions enabled."),
209 NULL, 0, &pax_aslr_enabled, 0, 208 NULL, 0, &pax_aslr_enabled, 0,
210 CTL_CREATE, CTL_EOL); 209 CTL_CREATE, CTL_EOL);
211 sysctl_createv(clog, 0, &rnode, NULL, 210 sysctl_createv(clog, 0, &rnode, NULL,
212 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 211 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
213 CTLTYPE_INT, "global", 212 CTLTYPE_INT, "global",
214 SYSCTL_DESCR("When enabled, unless explicitly " 213 SYSCTL_DESCR("When enabled, unless explicitly "
215 "specified, apply to all processes."), 214 "specified, apply to all processes."),
216 NULL, 0, &pax_aslr_global, 0, 215 NULL, 0, &pax_aslr_global, 0,
217 CTL_CREATE, CTL_EOL); 216 CTL_CREATE, CTL_EOL);
218 sysctl_createv(clog, 0, &rnode, NULL, 217 sysctl_createv(clog, 0, &rnode, NULL,
219 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 218 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
220 CTLTYPE_INT, "mmap_len", 219 CTLTYPE_INT, "mmap_len",
221 SYSCTL_DESCR("Number of bits randomized for " 220 SYSCTL_DESCR("Number of bits randomized for "
222 "mmap(2) calls."), 221 "mmap(2) calls."),
223 NULL, PAX_ASLR_DELTA_MMAP_LEN, NULL, 0, 222 NULL, PAX_ASLR_DELTA_MMAP_LEN, NULL, 0,
224 CTL_CREATE, CTL_EOL); 223 CTL_CREATE, CTL_EOL);
225 sysctl_createv(clog, 0, &rnode, NULL, 224 sysctl_createv(clog, 0, &rnode, NULL,
226 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 225 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
227 CTLTYPE_INT, "stack_len", 226 CTLTYPE_INT, "stack_len",
228 SYSCTL_DESCR("Number of bits randomized for " 227 SYSCTL_DESCR("Number of bits randomized for "
229 "the stack."), 228 "the stack."),
230 NULL, PAX_ASLR_DELTA_STACK_LEN, NULL, 0, 229 NULL, PAX_ASLR_DELTA_STACK_LEN, NULL, 0,
231 CTL_CREATE, CTL_EOL); 230 CTL_CREATE, CTL_EOL);
232 sysctl_createv(clog, 0, &rnode, NULL, 231 sysctl_createv(clog, 0, &rnode, NULL,
233 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 232 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
234 CTLTYPE_INT, "exec_len", 233 CTLTYPE_INT, "exec_len",
235 SYSCTL_DESCR("Number of bits randomized for " 234 SYSCTL_DESCR("Number of bits randomized for "
236 "the PIE exec base."), 235 "the PIE exec base."),
237 NULL, PAX_ASLR_DELTA_EXEC_LEN, NULL, 0, 236 NULL, PAX_ASLR_DELTA_EXEC_LEN, NULL, 0,
238 CTL_CREATE, CTL_EOL); 237 CTL_CREATE, CTL_EOL);
239 238
240#endif /* PAX_ASLR */ 239#endif /* PAX_ASLR */
241} 240}
242 241
243/* 242/*
244 * Initialize PaX. 243 * Initialize PaX.
245 */ 244 */
246void 245void
247pax_init(void) 246pax_init(void)
248{ 247{
249#ifdef PAX_SEGVGUARD 248#ifdef PAX_SEGVGUARD
250 int error; 249 int error;
251#endif /* PAX_SEGVGUARD */ 250#endif /* PAX_SEGVGUARD */
252 251
253#ifdef PAX_SEGVGUARD 252#ifdef PAX_SEGVGUARD
254 error = fileassoc_register("segvguard", pax_segvguard_cb, 253 error = fileassoc_register("segvguard", pax_segvguard_cb,
255 &segvguard_id); 254 &segvguard_id);
256 if (error) { 255 if (error) {
257 panic("pax_init: segvguard_id: error=%d\n", error); 256 panic("pax_init: segvguard_id: error=%d\n", error);
258 } 257 }
259#endif /* PAX_SEGVGUARD */ 258#endif /* PAX_SEGVGUARD */
260} 259}
261 260
262#ifdef PAX_MPROTECT 261#ifdef PAX_MPROTECT
263void 262void
264pax_mprotect(struct lwp *l, vm_prot_t *prot, vm_prot_t *maxprot) 263pax_mprotect(struct lwp *l, vm_prot_t *prot, vm_prot_t *maxprot)
265{ 264{
266 uint32_t f; 265 uint32_t f;
267 266
268 if (!pax_mprotect_enabled) 267 if (!pax_mprotect_enabled)
269 return; 268 return;
270 269
271 f = l->l_proc->p_pax; 270 f = l->l_proc->p_pax;
272 if ((pax_mprotect_global && (f & ELF_NOTE_PAX_NOMPROTECT) != 0) || 271 if ((pax_mprotect_global && (f & ELF_NOTE_PAX_NOMPROTECT) != 0) ||
273 (!pax_mprotect_global && (f & ELF_NOTE_PAX_MPROTECT) == 0)) 272 (!pax_mprotect_global && (f & ELF_NOTE_PAX_MPROTECT) == 0))
274 return; 273 return;
275 274
276 if ((*prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) != VM_PROT_EXECUTE) { 275 if ((*prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) != VM_PROT_EXECUTE) {
277 *prot &= ~VM_PROT_EXECUTE; 276 *prot &= ~VM_PROT_EXECUTE;
278 *maxprot &= ~VM_PROT_EXECUTE; 277 *maxprot &= ~VM_PROT_EXECUTE;
279 } else { 278 } else {
280 *prot &= ~VM_PROT_WRITE; 279 *prot &= ~VM_PROT_WRITE;
281 *maxprot &= ~VM_PROT_WRITE; 280 *maxprot &= ~VM_PROT_WRITE;
282 } 281 }
283} 282}
284#endif /* PAX_MPROTECT */ 283#endif /* PAX_MPROTECT */
285 284
286#ifdef PAX_ASLR 285#ifdef PAX_ASLR
287bool 286bool
288pax_aslr_active(struct lwp *l) 287pax_aslr_active(struct lwp *l)
289{ 288{
290 uint32_t f; 289 uint32_t f;
291 290
292 if (!pax_aslr_enabled) 291 if (!pax_aslr_enabled)
293 return false; 292 return false;
294 293
295 f = l->l_proc->p_pax; 294 f = l->l_proc->p_pax;
296 if ((pax_aslr_global && (f & ELF_NOTE_PAX_NOASLR) != 0) || 295 if ((pax_aslr_global && (f & ELF_NOTE_PAX_NOASLR) != 0) ||
297 (!pax_aslr_global && (f & ELF_NOTE_PAX_ASLR) == 0)) 296 (!pax_aslr_global && (f & ELF_NOTE_PAX_ASLR) == 0))
298 return false; 297 return false;
299 return true; 298 return true;
300} 299}
301 300
302void 301void
303pax_aslr_init(struct lwp *l, struct vmspace *vm) 302pax_aslr_init(struct lwp *l, struct vmspace *vm)
304{ 303{
305 if (!pax_aslr_active(l)) 304 if (!pax_aslr_active(l))
306 return; 305 return;
307 306
308 vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(), 307 vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(),
309 PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN); 308 PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN);
310} 309}
311 310
312void 311void
313pax_aslr(struct lwp *l, vaddr_t *addr, vaddr_t orig_addr, int f) 312pax_aslr(struct lwp *l, vaddr_t *addr, vaddr_t orig_addr, int f)
314{ 313{
315 if (!pax_aslr_active(l)) 314 if (!pax_aslr_active(l))
316 return; 315 return;
317 316
318 if (!(f & MAP_FIXED) && ((orig_addr == 0) || !(f & MAP_ANON))) { 317 if (!(f & MAP_FIXED) && ((orig_addr == 0) || !(f & MAP_ANON))) {
319#ifdef PAX_ASLR_DEBUG 318#ifdef PAX_ASLR_DEBUG
320 uprintf("applying to 0x%lx orig_addr=0x%lx f=%x\n", 319 uprintf("applying to 0x%lx orig_addr=0x%lx f=%x\n",
321 (unsigned long)*addr, (unsigned long)orig_addr, f); 320 (unsigned long)*addr, (unsigned long)orig_addr, f);
322#endif 321#endif
323 if (!(l->l_proc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)) 322 if (!(l->l_proc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN))
324 *addr += l->l_proc->p_vmspace->vm_aslr_delta_mmap; 323 *addr += l->l_proc->p_vmspace->vm_aslr_delta_mmap;
325 else 324 else
326 *addr -= l->l_proc->p_vmspace->vm_aslr_delta_mmap; 325 *addr -= l->l_proc->p_vmspace->vm_aslr_delta_mmap;
327#ifdef PAX_ASLR_DEBUG 326#ifdef PAX_ASLR_DEBUG
328 uprintf("result 0x%lx\n", *addr); 327 uprintf("result 0x%lx\n", *addr);
329#endif 328#endif
330 } 329 }
331#ifdef PAX_ASLR_DEBUG 330#ifdef PAX_ASLR_DEBUG
332 else 331 else
333 uprintf("not applying to 0x%lx orig_addr=0x%lx f=%x\n", 332 uprintf("not applying to 0x%lx orig_addr=0x%lx f=%x\n",
334 (unsigned long)*addr, (unsigned long)orig_addr, f); 333 (unsigned long)*addr, (unsigned long)orig_addr, f);
335#endif 334#endif
336} 335}
337 336
338void 337void
339pax_aslr_stack(struct lwp *l, struct exec_package *epp, u_long *max_stack_size) 338pax_aslr_stack(struct lwp *l, struct exec_package *epp, u_long *max_stack_size)
340{ 339{
341 if (pax_aslr_active(l)) { 340 if (pax_aslr_active(l)) {
342 u_long d = PAX_ASLR_DELTA(cprng_fast32(), 341 u_long d = PAX_ASLR_DELTA(cprng_fast32(),
343 PAX_ASLR_DELTA_STACK_LSB, 342 PAX_ASLR_DELTA_STACK_LSB,
344 PAX_ASLR_DELTA_STACK_LEN); 343 PAX_ASLR_DELTA_STACK_LEN);
345#ifdef PAX_ASLR_DEBUG 344#ifdef PAX_ASLR_DEBUG
346 uprintf("stack 0x%lx d=0x%lx 0x%lx\n", 345 uprintf("stack 0x%lx d=0x%lx 0x%lx\n",
347 epp->ep_minsaddr, d, epp->ep_minsaddr - d); 346 epp->ep_minsaddr, d, epp->ep_minsaddr - d);
348#endif 347#endif
349 epp->ep_minsaddr -= d; 348 epp->ep_minsaddr -= d;
350 *max_stack_size -= d; 349 *max_stack_size -= d;
351 if (epp->ep_ssize > *max_stack_size) 350 if (epp->ep_ssize > *max_stack_size)
352 epp->ep_ssize = *max_stack_size; 351 epp->ep_ssize = *max_stack_size;
353 } 352 }
354} 353}
355#endif /* PAX_ASLR */ 354#endif /* PAX_ASLR */
356 355
357#ifdef PAX_SEGVGUARD 356#ifdef PAX_SEGVGUARD
358static void 357static void
359pax_segvguard_cb(void *v) 358pax_segvguard_cb(void *v)
360{ 359{
361 struct pax_segvguard_entry *p = v; 360 struct pax_segvguard_entry *p = v;
362 struct pax_segvguard_uid_entry *up; 361 struct pax_segvguard_uid_entry *up;
363 362
364 if (p == NULL) { 363 if (p == NULL) {
365 return; 364 return;
366 } 365 }
367 while ((up = LIST_FIRST(&p->segv_uids)) != NULL) { 366 while ((up = LIST_FIRST(&p->segv_uids)) != NULL) {
368 LIST_REMOVE(up, sue_list); 367 LIST_REMOVE(up, sue_list);
369 kmem_free(up, sizeof(*up)); 368 kmem_free(up, sizeof(*up));
370 } 369 }
371 kmem_free(p, sizeof(*p)); 370 kmem_free(p, sizeof(*p));
372} 371}
373 372
374/* 373/*
375 * Called when a process of image vp generated a segfault. 374 * Called when a process of image vp generated a segfault.
376 */ 375 */
377int 376int
378pax_segvguard(struct lwp *l, struct vnode *vp, const char *name, 377pax_segvguard(struct lwp *l, struct vnode *vp, const char *name,
379 bool crashed) 378 bool crashed)
380{ 379{
381 struct pax_segvguard_entry *p; 380 struct pax_segvguard_entry *p;
382 struct pax_segvguard_uid_entry *up; 381 struct pax_segvguard_uid_entry *up;
383 struct timeval tv; 382 struct timeval tv;
384 uid_t uid; 383 uid_t uid;
385 uint32_t f; 384 uint32_t f;
386 bool have_uid; 385 bool have_uid;
387 386
388 if (!pax_segvguard_enabled) 387 if (!pax_segvguard_enabled)
389 return (0); 388 return (0);
390 389
391 f = l->l_proc->p_pax; 390 f = l->l_proc->p_pax;
392 if ((pax_segvguard_global && (f & ELF_NOTE_PAX_NOGUARD) != 0) || 391 if ((pax_segvguard_global && (f & ELF_NOTE_PAX_NOGUARD) != 0) ||
393 (!pax_segvguard_global && (f & ELF_NOTE_PAX_GUARD) == 0)) 392 (!pax_segvguard_global && (f & ELF_NOTE_PAX_GUARD) == 0))
394 return (0); 393 return (0);
395 394
396 if (vp == NULL) 395 if (vp == NULL)
397 return (EFAULT);  396 return (EFAULT);
398 397
399 /* Check if we already monitor the file. */ 398 /* Check if we already monitor the file. */
400 p = fileassoc_lookup(vp, segvguard_id); 399 p = fileassoc_lookup(vp, segvguard_id);
401 400
402 /* Fast-path if starting a program we don't know. */ 401 /* Fast-path if starting a program we don't know. */
403 if (p == NULL && !crashed) 402 if (p == NULL && !crashed)
404 return (0); 403 return (0);
405 404
406 microtime(&tv); 405 microtime(&tv);
407 406
408 /* 407 /*
409 * If a program we don't know crashed, we need to create a new entry 408 * If a program we don't know crashed, we need to create a new entry
410 * for it. 409 * for it.
411 */ 410 */
412 if (p == NULL) { 411 if (p == NULL) {
413 p = kmem_alloc(sizeof(*p), KM_SLEEP); 412 p = kmem_alloc(sizeof(*p), KM_SLEEP);
414 fileassoc_add(vp, segvguard_id, p); 413 fileassoc_add(vp, segvguard_id, p);
415 LIST_INIT(&p->segv_uids); 414 LIST_INIT(&p->segv_uids);
416 415
417 /* 416 /*
418 * Initialize a new entry with "crashes so far" of 1. 417 * Initialize a new entry with "crashes so far" of 1.
419 * The expiry time is when we purge the entry if it didn't 418 * The expiry time is when we purge the entry if it didn't
420 * reach the limit. 419 * reach the limit.
421 */ 420 */
422 up = kmem_alloc(sizeof(*up), KM_SLEEP); 421 up = kmem_alloc(sizeof(*up), KM_SLEEP);
423 up->sue_uid = kauth_cred_getuid(l->l_cred); 422 up->sue_uid = kauth_cred_getuid(l->l_cred);
424 up->sue_ncrashes = 1; 423 up->sue_ncrashes = 1;
425 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 424 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry;
426 up->sue_suspended = 0; 425 up->sue_suspended = 0;
427 426
428 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list); 427 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list);
429 428
430 return (0); 429 return (0);
431 } 430 }
432 431
433 /* 432 /*
434 * A program we "know" either executed or crashed again. 433 * A program we "know" either executed or crashed again.
435 * See if it's a culprit we're familiar with. 434 * See if it's a culprit we're familiar with.
436 */ 435 */
437 uid = kauth_cred_getuid(l->l_cred); 436 uid = kauth_cred_getuid(l->l_cred);
438 have_uid = false; 437 have_uid = false;
439 LIST_FOREACH(up, &p->segv_uids, sue_list) { 438 LIST_FOREACH(up, &p->segv_uids, sue_list) {
440 if (up->sue_uid == uid) { 439 if (up->sue_uid == uid) {
441 have_uid = true; 440 have_uid = true;
442 break; 441 break;
443 } 442 }
444 } 443 }
445 444
446 /* 445 /*
447 * It's someone else. Add an entry for him if we crashed. 446 * It's someone else. Add an entry for him if we crashed.
448 */ 447 */
449 if (!have_uid) { 448 if (!have_uid) {
450 if (crashed) { 449 if (crashed) {
451 up = kmem_alloc(sizeof(*up), KM_SLEEP); 450 up = kmem_alloc(sizeof(*up), KM_SLEEP);
452 up->sue_uid = uid; 451 up->sue_uid = uid;
453 up->sue_ncrashes = 1; 452 up->sue_ncrashes = 1;
454 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 453 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry;
455 up->sue_suspended = 0; 454 up->sue_suspended = 0;
456 455
457 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list); 456 LIST_INSERT_HEAD(&p->segv_uids, up, sue_list);
458 } 457 }
459 return (0); 458 return (0);
460 } 459 }
461 460
462 if (crashed) { 461 if (crashed) {
463 /* Check if timer on previous crashes expired first. */ 462 /* Check if timer on previous crashes expired first. */
464 if (up->sue_expiry < tv.tv_sec) { 463 if (up->sue_expiry < tv.tv_sec) {
465 log(LOG_INFO, "PaX Segvguard: [%s] Suspension" 464 log(LOG_INFO, "PaX Segvguard: [%s] Suspension"
466 " expired.\n", name ? name : "unknown"); 465 " expired.\n", name ? name : "unknown");
467 466
468 up->sue_ncrashes = 1; 467 up->sue_ncrashes = 1;
469 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry; 468 up->sue_expiry = tv.tv_sec + pax_segvguard_expiry;
470 up->sue_suspended = 0; 469 up->sue_suspended = 0;
471 470
472 return (0); 471 return (0);
473 } 472 }
474 473
475 up->sue_ncrashes++; 474 up->sue_ncrashes++;
476 475
477 if (up->sue_ncrashes >= pax_segvguard_maxcrashes) { 476 if (up->sue_ncrashes >= pax_segvguard_maxcrashes) {
478 log(LOG_ALERT, "PaX Segvguard: [%s] Suspending " 477 log(LOG_ALERT, "PaX Segvguard: [%s] Suspending "
479 "execution for %d seconds after %zu crashes.\n", 478 "execution for %d seconds after %zu crashes.\n",
480 name ? name : "unknown", pax_segvguard_suspension, 479 name ? name : "unknown", pax_segvguard_suspension,
481 up->sue_ncrashes); 480 up->sue_ncrashes);
482 481
483 /* Suspend this program for a while. */ 482 /* Suspend this program for a while. */
484 up->sue_suspended = tv.tv_sec + pax_segvguard_suspension; 483 up->sue_suspended = tv.tv_sec + pax_segvguard_suspension;
485 up->sue_ncrashes = 0; 484 up->sue_ncrashes = 0;
486 up->sue_expiry = 0; 485 up->sue_expiry = 0;
487 } 486 }
488 } else { 487 } else {
489 /* Are we supposed to be suspended? */ 488 /* Are we supposed to be suspended? */
490 if (up->sue_suspended > tv.tv_sec) { 489 if (up->sue_suspended > tv.tv_sec) {
491 log(LOG_ALERT, "PaX Segvguard: [%s] Preventing " 490 log(LOG_ALERT, "PaX Segvguard: [%s] Preventing "
492 "execution due to repeated segfaults.\n", name ? 491 "execution due to repeated segfaults.\n", name ?
493 name : "unknown"); 492 name : "unknown");
494 493
495 return (EPERM); 494 return (EPERM);
496 } 495 }
497 } 496 }
498 497
499 return (0); 498 return (0);
500} 499}
501#endif /* PAX_SEGVGUARD */ 500#endif /* PAX_SEGVGUARD */