Sat Oct 3 01:41:39 2009 UTC ()
Finish moving socket policy to the subsystem.


(elad)
diff -r1.191 -r1.192 src/sys/kern/uipc_socket.c
diff -r1.18 -r1.19 src/sys/secmodel/suser/secmodel_suser.c

cvs diff -r1.191 -r1.192 src/sys/kern/uipc_socket.c (switch to unified diff)

--- src/sys/kern/uipc_socket.c 2009/10/02 23:50:16 1.191
+++ src/sys/kern/uipc_socket.c 2009/10/03 01:41:39 1.192
@@ -1,1471 +1,1476 @@ @@ -1,1471 +1,1476 @@
1/* $NetBSD: uipc_socket.c,v 1.191 2009/10/02 23:50:16 elad Exp $ */ 1/* $NetBSD: uipc_socket.c,v 1.192 2009/10/03 01:41:39 elad Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran. 8 * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 2004 The FreeBSD Foundation 33 * Copyright (c) 2004 The FreeBSD Foundation
34 * Copyright (c) 2004 Robert Watson 34 * Copyright (c) 2004 Robert Watson
35 * Copyright (c) 1982, 1986, 1988, 1990, 1993 35 * Copyright (c) 1982, 1986, 1988, 1990, 1993
36 * The Regents of the University of California. All rights reserved. 36 * The Regents of the University of California. All rights reserved.
37 * 37 *
38 * Redistribution and use in source and binary forms, with or without 38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions 39 * modification, are permitted provided that the following conditions
40 * are met: 40 * are met:
41 * 1. Redistributions of source code must retain the above copyright 41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer. 42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright 43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the 44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution. 45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors 46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software 47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission. 48 * without specific prior written permission.
49 * 49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE. 60 * SUCH DAMAGE.
61 * 61 *
62 * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95 62 * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95
63 */ 63 */
64 64
65#include <sys/cdefs.h> 65#include <sys/cdefs.h>
66__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.191 2009/10/02 23:50:16 elad Exp $"); 66__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.192 2009/10/03 01:41:39 elad Exp $");
67 67
68#include "opt_compat_netbsd.h" 68#include "opt_compat_netbsd.h"
69#include "opt_sock_counters.h" 69#include "opt_sock_counters.h"
70#include "opt_sosend_loan.h" 70#include "opt_sosend_loan.h"
71#include "opt_mbuftrace.h" 71#include "opt_mbuftrace.h"
72#include "opt_somaxkva.h" 72#include "opt_somaxkva.h"
73#include "opt_multiprocessor.h" /* XXX */ 73#include "opt_multiprocessor.h" /* XXX */
74 74
75#include <sys/param.h> 75#include <sys/param.h>
76#include <sys/systm.h> 76#include <sys/systm.h>
77#include <sys/proc.h> 77#include <sys/proc.h>
78#include <sys/file.h> 78#include <sys/file.h>
79#include <sys/filedesc.h> 79#include <sys/filedesc.h>
80#include <sys/kmem.h> 80#include <sys/kmem.h>
81#include <sys/mbuf.h> 81#include <sys/mbuf.h>
82#include <sys/domain.h> 82#include <sys/domain.h>
83#include <sys/kernel.h> 83#include <sys/kernel.h>
84#include <sys/protosw.h> 84#include <sys/protosw.h>
85#include <sys/socket.h> 85#include <sys/socket.h>
86#include <sys/socketvar.h> 86#include <sys/socketvar.h>
87#include <sys/signalvar.h> 87#include <sys/signalvar.h>
88#include <sys/resourcevar.h> 88#include <sys/resourcevar.h>
89#include <sys/uidinfo.h> 89#include <sys/uidinfo.h>
90#include <sys/event.h> 90#include <sys/event.h>
91#include <sys/poll.h> 91#include <sys/poll.h>
92#include <sys/kauth.h> 92#include <sys/kauth.h>
93#include <sys/mutex.h> 93#include <sys/mutex.h>
94#include <sys/condvar.h> 94#include <sys/condvar.h>
95 95
96#ifdef COMPAT_50 96#ifdef COMPAT_50
97#include <compat/sys/time.h> 97#include <compat/sys/time.h>
98#include <compat/sys/socket.h> 98#include <compat/sys/socket.h>
99#endif 99#endif
100 100
101#include <uvm/uvm.h> 101#include <uvm/uvm.h>
102 102
103MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options"); 103MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
104MALLOC_DEFINE(M_SONAME, "soname", "socket name"); 104MALLOC_DEFINE(M_SONAME, "soname", "socket name");
105 105
106extern const struct fileops socketops; 106extern const struct fileops socketops;
107 107
108extern int somaxconn; /* patchable (XXX sysctl) */ 108extern int somaxconn; /* patchable (XXX sysctl) */
109int somaxconn = SOMAXCONN; 109int somaxconn = SOMAXCONN;
110kmutex_t *softnet_lock; 110kmutex_t *softnet_lock;
111 111
112#ifdef SOSEND_COUNTERS 112#ifdef SOSEND_COUNTERS
113#include <sys/device.h> 113#include <sys/device.h>
114 114
115static struct evcnt sosend_loan_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 115static struct evcnt sosend_loan_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
116 NULL, "sosend", "loan big"); 116 NULL, "sosend", "loan big");
117static struct evcnt sosend_copy_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 117static struct evcnt sosend_copy_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
118 NULL, "sosend", "copy big"); 118 NULL, "sosend", "copy big");
119static struct evcnt sosend_copy_small = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 119static struct evcnt sosend_copy_small = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
120 NULL, "sosend", "copy small"); 120 NULL, "sosend", "copy small");
121static struct evcnt sosend_kvalimit = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 121static struct evcnt sosend_kvalimit = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
122 NULL, "sosend", "kva limit"); 122 NULL, "sosend", "kva limit");
123 123
124#define SOSEND_COUNTER_INCR(ev) (ev)->ev_count++ 124#define SOSEND_COUNTER_INCR(ev) (ev)->ev_count++
125 125
126EVCNT_ATTACH_STATIC(sosend_loan_big); 126EVCNT_ATTACH_STATIC(sosend_loan_big);
127EVCNT_ATTACH_STATIC(sosend_copy_big); 127EVCNT_ATTACH_STATIC(sosend_copy_big);
128EVCNT_ATTACH_STATIC(sosend_copy_small); 128EVCNT_ATTACH_STATIC(sosend_copy_small);
129EVCNT_ATTACH_STATIC(sosend_kvalimit); 129EVCNT_ATTACH_STATIC(sosend_kvalimit);
130#else 130#else
131 131
132#define SOSEND_COUNTER_INCR(ev) /* nothing */ 132#define SOSEND_COUNTER_INCR(ev) /* nothing */
133 133
134#endif /* SOSEND_COUNTERS */ 134#endif /* SOSEND_COUNTERS */
135 135
136static struct callback_entry sokva_reclaimerentry; 136static struct callback_entry sokva_reclaimerentry;
137 137
138#if defined(SOSEND_NO_LOAN) || defined(MULTIPROCESSOR) 138#if defined(SOSEND_NO_LOAN) || defined(MULTIPROCESSOR)
139int sock_loan_thresh = -1; 139int sock_loan_thresh = -1;
140#else 140#else
141int sock_loan_thresh = 4096; 141int sock_loan_thresh = 4096;
142#endif 142#endif
143 143
144static kmutex_t so_pendfree_lock; 144static kmutex_t so_pendfree_lock;
145static struct mbuf *so_pendfree; 145static struct mbuf *so_pendfree;
146 146
147#ifndef SOMAXKVA 147#ifndef SOMAXKVA
148#define SOMAXKVA (16 * 1024 * 1024) 148#define SOMAXKVA (16 * 1024 * 1024)
149#endif 149#endif
150int somaxkva = SOMAXKVA; 150int somaxkva = SOMAXKVA;
151static int socurkva; 151static int socurkva;
152static kcondvar_t socurkva_cv; 152static kcondvar_t socurkva_cv;
153 153
154static kauth_listener_t socket_listener; 154static kauth_listener_t socket_listener;
155 155
156#define SOCK_LOAN_CHUNK 65536 156#define SOCK_LOAN_CHUNK 65536
157 157
158static size_t sodopendfree(void); 158static size_t sodopendfree(void);
159static size_t sodopendfreel(void); 159static size_t sodopendfreel(void);
160 160
161static void sysctl_kern_somaxkva_setup(void); 161static void sysctl_kern_somaxkva_setup(void);
162static struct sysctllog *socket_sysctllog; 162static struct sysctllog *socket_sysctllog;
163 163
164static vsize_t 164static vsize_t
165sokvareserve(struct socket *so, vsize_t len) 165sokvareserve(struct socket *so, vsize_t len)
166{ 166{
167 int error; 167 int error;
168 168
169 mutex_enter(&so_pendfree_lock); 169 mutex_enter(&so_pendfree_lock);
170 while (socurkva + len > somaxkva) { 170 while (socurkva + len > somaxkva) {
171 size_t freed; 171 size_t freed;
172 172
173 /* 173 /*
174 * try to do pendfree. 174 * try to do pendfree.
175 */ 175 */
176 176
177 freed = sodopendfreel(); 177 freed = sodopendfreel();
178 178
179 /* 179 /*
180 * if some kva was freed, try again. 180 * if some kva was freed, try again.
181 */ 181 */
182 182
183 if (freed) 183 if (freed)
184 continue; 184 continue;
185 185
186 SOSEND_COUNTER_INCR(&sosend_kvalimit); 186 SOSEND_COUNTER_INCR(&sosend_kvalimit);
187 error = cv_wait_sig(&socurkva_cv, &so_pendfree_lock); 187 error = cv_wait_sig(&socurkva_cv, &so_pendfree_lock);
188 if (error) { 188 if (error) {
189 len = 0; 189 len = 0;
190 break; 190 break;
191 } 191 }
192 } 192 }
193 socurkva += len; 193 socurkva += len;
194 mutex_exit(&so_pendfree_lock); 194 mutex_exit(&so_pendfree_lock);
195 return len; 195 return len;
196} 196}
197 197
198static void 198static void
199sokvaunreserve(vsize_t len) 199sokvaunreserve(vsize_t len)
200{ 200{
201 201
202 mutex_enter(&so_pendfree_lock); 202 mutex_enter(&so_pendfree_lock);
203 socurkva -= len; 203 socurkva -= len;
204 cv_broadcast(&socurkva_cv); 204 cv_broadcast(&socurkva_cv);
205 mutex_exit(&so_pendfree_lock); 205 mutex_exit(&so_pendfree_lock);
206} 206}
207 207
208/* 208/*
209 * sokvaalloc: allocate kva for loan. 209 * sokvaalloc: allocate kva for loan.
210 */ 210 */
211 211
212vaddr_t 212vaddr_t
213sokvaalloc(vsize_t len, struct socket *so) 213sokvaalloc(vsize_t len, struct socket *so)
214{ 214{
215 vaddr_t lva; 215 vaddr_t lva;
216 216
217 /* 217 /*
218 * reserve kva. 218 * reserve kva.
219 */ 219 */
220 220
221 if (sokvareserve(so, len) == 0) 221 if (sokvareserve(so, len) == 0)
222 return 0; 222 return 0;
223 223
224 /* 224 /*
225 * allocate kva. 225 * allocate kva.
226 */ 226 */
227 227
228 lva = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); 228 lva = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
229 if (lva == 0) { 229 if (lva == 0) {
230 sokvaunreserve(len); 230 sokvaunreserve(len);
231 return (0); 231 return (0);
232 } 232 }
233 233
234 return lva; 234 return lva;
235} 235}
236 236
237/* 237/*
238 * sokvafree: free kva for loan. 238 * sokvafree: free kva for loan.
239 */ 239 */
240 240
241void 241void
242sokvafree(vaddr_t sva, vsize_t len) 242sokvafree(vaddr_t sva, vsize_t len)
243{ 243{
244 244
245 /* 245 /*
246 * free kva. 246 * free kva.
247 */ 247 */
248 248
249 uvm_km_free(kernel_map, sva, len, UVM_KMF_VAONLY); 249 uvm_km_free(kernel_map, sva, len, UVM_KMF_VAONLY);
250 250
251 /* 251 /*
252 * unreserve kva. 252 * unreserve kva.
253 */ 253 */
254 254
255 sokvaunreserve(len); 255 sokvaunreserve(len);
256} 256}
257 257
258static void 258static void
259sodoloanfree(struct vm_page **pgs, void *buf, size_t size) 259sodoloanfree(struct vm_page **pgs, void *buf, size_t size)
260{ 260{
261 vaddr_t sva, eva; 261 vaddr_t sva, eva;
262 vsize_t len; 262 vsize_t len;
263 int npgs; 263 int npgs;
264 264
265 KASSERT(pgs != NULL); 265 KASSERT(pgs != NULL);
266 266
267 eva = round_page((vaddr_t) buf + size); 267 eva = round_page((vaddr_t) buf + size);
268 sva = trunc_page((vaddr_t) buf); 268 sva = trunc_page((vaddr_t) buf);
269 len = eva - sva; 269 len = eva - sva;
270 npgs = len >> PAGE_SHIFT; 270 npgs = len >> PAGE_SHIFT;
271 271
272 pmap_kremove(sva, len); 272 pmap_kremove(sva, len);
273 pmap_update(pmap_kernel()); 273 pmap_update(pmap_kernel());
274 uvm_unloan(pgs, npgs, UVM_LOAN_TOPAGE); 274 uvm_unloan(pgs, npgs, UVM_LOAN_TOPAGE);
275 sokvafree(sva, len); 275 sokvafree(sva, len);
276} 276}
277 277
278static size_t 278static size_t
279sodopendfree(void) 279sodopendfree(void)
280{ 280{
281 size_t rv; 281 size_t rv;
282 282
283 if (__predict_true(so_pendfree == NULL)) 283 if (__predict_true(so_pendfree == NULL))
284 return 0; 284 return 0;
285 285
286 mutex_enter(&so_pendfree_lock); 286 mutex_enter(&so_pendfree_lock);
287 rv = sodopendfreel(); 287 rv = sodopendfreel();
288 mutex_exit(&so_pendfree_lock); 288 mutex_exit(&so_pendfree_lock);
289 289
290 return rv; 290 return rv;
291} 291}
292 292
293/* 293/*
294 * sodopendfreel: free mbufs on "pendfree" list. 294 * sodopendfreel: free mbufs on "pendfree" list.
295 * unlock and relock so_pendfree_lock when freeing mbufs. 295 * unlock and relock so_pendfree_lock when freeing mbufs.
296 * 296 *
297 * => called with so_pendfree_lock held. 297 * => called with so_pendfree_lock held.
298 */ 298 */
299 299
300static size_t 300static size_t
301sodopendfreel(void) 301sodopendfreel(void)
302{ 302{
303 struct mbuf *m, *next; 303 struct mbuf *m, *next;
304 size_t rv = 0; 304 size_t rv = 0;
305 305
306 KASSERT(mutex_owned(&so_pendfree_lock)); 306 KASSERT(mutex_owned(&so_pendfree_lock));
307 307
308 while (so_pendfree != NULL) { 308 while (so_pendfree != NULL) {
309 m = so_pendfree; 309 m = so_pendfree;
310 so_pendfree = NULL; 310 so_pendfree = NULL;
311 mutex_exit(&so_pendfree_lock); 311 mutex_exit(&so_pendfree_lock);
312 312
313 for (; m != NULL; m = next) { 313 for (; m != NULL; m = next) {
314 next = m->m_next; 314 next = m->m_next;
315 KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0); 315 KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0);
316 KASSERT(m->m_ext.ext_refcnt == 0); 316 KASSERT(m->m_ext.ext_refcnt == 0);
317 317
318 rv += m->m_ext.ext_size; 318 rv += m->m_ext.ext_size;
319 sodoloanfree(m->m_ext.ext_pgs, m->m_ext.ext_buf, 319 sodoloanfree(m->m_ext.ext_pgs, m->m_ext.ext_buf,
320 m->m_ext.ext_size); 320 m->m_ext.ext_size);
321 pool_cache_put(mb_cache, m); 321 pool_cache_put(mb_cache, m);
322 } 322 }
323 323
324 mutex_enter(&so_pendfree_lock); 324 mutex_enter(&so_pendfree_lock);
325 } 325 }
326 326
327 return (rv); 327 return (rv);
328} 328}
329 329
330void 330void
331soloanfree(struct mbuf *m, void *buf, size_t size, void *arg) 331soloanfree(struct mbuf *m, void *buf, size_t size, void *arg)
332{ 332{
333 333
334 KASSERT(m != NULL); 334 KASSERT(m != NULL);
335 335
336 /* 336 /*
337 * postpone freeing mbuf. 337 * postpone freeing mbuf.
338 * 338 *
339 * we can't do it in interrupt context 339 * we can't do it in interrupt context
340 * because we need to put kva back to kernel_map. 340 * because we need to put kva back to kernel_map.
341 */ 341 */
342 342
343 mutex_enter(&so_pendfree_lock); 343 mutex_enter(&so_pendfree_lock);
344 m->m_next = so_pendfree; 344 m->m_next = so_pendfree;
345 so_pendfree = m; 345 so_pendfree = m;
346 cv_broadcast(&socurkva_cv); 346 cv_broadcast(&socurkva_cv);
347 mutex_exit(&so_pendfree_lock); 347 mutex_exit(&so_pendfree_lock);
348} 348}
349 349
350static long 350static long
351sosend_loan(struct socket *so, struct uio *uio, struct mbuf *m, long space) 351sosend_loan(struct socket *so, struct uio *uio, struct mbuf *m, long space)
352{ 352{
353 struct iovec *iov = uio->uio_iov; 353 struct iovec *iov = uio->uio_iov;
354 vaddr_t sva, eva; 354 vaddr_t sva, eva;
355 vsize_t len; 355 vsize_t len;
356 vaddr_t lva; 356 vaddr_t lva;
357 int npgs, error; 357 int npgs, error;
358 vaddr_t va; 358 vaddr_t va;
359 int i; 359 int i;
360 360
361 if (VMSPACE_IS_KERNEL_P(uio->uio_vmspace)) 361 if (VMSPACE_IS_KERNEL_P(uio->uio_vmspace))
362 return (0); 362 return (0);
363 363
364 if (iov->iov_len < (size_t) space) 364 if (iov->iov_len < (size_t) space)
365 space = iov->iov_len; 365 space = iov->iov_len;
366 if (space > SOCK_LOAN_CHUNK) 366 if (space > SOCK_LOAN_CHUNK)
367 space = SOCK_LOAN_CHUNK; 367 space = SOCK_LOAN_CHUNK;
368 368
369 eva = round_page((vaddr_t) iov->iov_base + space); 369 eva = round_page((vaddr_t) iov->iov_base + space);
370 sva = trunc_page((vaddr_t) iov->iov_base); 370 sva = trunc_page((vaddr_t) iov->iov_base);
371 len = eva - sva; 371 len = eva - sva;
372 npgs = len >> PAGE_SHIFT; 372 npgs = len >> PAGE_SHIFT;
373 373
374 KASSERT(npgs <= M_EXT_MAXPAGES); 374 KASSERT(npgs <= M_EXT_MAXPAGES);
375 375
376 lva = sokvaalloc(len, so); 376 lva = sokvaalloc(len, so);
377 if (lva == 0) 377 if (lva == 0)
378 return 0; 378 return 0;
379 379
380 error = uvm_loan(&uio->uio_vmspace->vm_map, sva, len, 380 error = uvm_loan(&uio->uio_vmspace->vm_map, sva, len,
381 m->m_ext.ext_pgs, UVM_LOAN_TOPAGE); 381 m->m_ext.ext_pgs, UVM_LOAN_TOPAGE);
382 if (error) { 382 if (error) {
383 sokvafree(lva, len); 383 sokvafree(lva, len);
384 return (0); 384 return (0);
385 } 385 }
386 386
387 for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE) 387 for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE)
388 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]), 388 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]),
389 VM_PROT_READ); 389 VM_PROT_READ);
390 pmap_update(pmap_kernel()); 390 pmap_update(pmap_kernel());
391 391
392 lva += (vaddr_t) iov->iov_base & PAGE_MASK; 392 lva += (vaddr_t) iov->iov_base & PAGE_MASK;
393 393
394 MEXTADD(m, (void *) lva, space, M_MBUF, soloanfree, so); 394 MEXTADD(m, (void *) lva, space, M_MBUF, soloanfree, so);
395 m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP; 395 m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
396 396
397 uio->uio_resid -= space; 397 uio->uio_resid -= space;
398 /* uio_offset not updated, not set/used for write(2) */ 398 /* uio_offset not updated, not set/used for write(2) */
399 uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + space; 399 uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + space;
400 uio->uio_iov->iov_len -= space; 400 uio->uio_iov->iov_len -= space;
401 if (uio->uio_iov->iov_len == 0) { 401 if (uio->uio_iov->iov_len == 0) {
402 uio->uio_iov++; 402 uio->uio_iov++;
403 uio->uio_iovcnt--; 403 uio->uio_iovcnt--;
404 } 404 }
405 405
406 return (space); 406 return (space);
407} 407}
408 408
409static int 409static int
410sokva_reclaim_callback(struct callback_entry *ce, void *obj, void *arg) 410sokva_reclaim_callback(struct callback_entry *ce, void *obj, void *arg)
411{ 411{
412 412
413 KASSERT(ce == &sokva_reclaimerentry); 413 KASSERT(ce == &sokva_reclaimerentry);
414 KASSERT(obj == NULL); 414 KASSERT(obj == NULL);
415 415
416 sodopendfree(); 416 sodopendfree();
417 if (!vm_map_starved_p(kernel_map)) { 417 if (!vm_map_starved_p(kernel_map)) {
418 return CALLBACK_CHAIN_ABORT; 418 return CALLBACK_CHAIN_ABORT;
419 } 419 }
420 return CALLBACK_CHAIN_CONTINUE; 420 return CALLBACK_CHAIN_CONTINUE;
421} 421}
422 422
423struct mbuf * 423struct mbuf *
424getsombuf(struct socket *so, int type) 424getsombuf(struct socket *so, int type)
425{ 425{
426 struct mbuf *m; 426 struct mbuf *m;
427 427
428 m = m_get(M_WAIT, type); 428 m = m_get(M_WAIT, type);
429 MCLAIM(m, so->so_mowner); 429 MCLAIM(m, so->so_mowner);
430 return m; 430 return m;
431} 431}
432 432
433static int 433static int
434socket_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 434socket_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
435 void *arg0, void *arg1, void *arg2, void *arg3) 435 void *arg0, void *arg1, void *arg2, void *arg3)
436{ 436{
437 int result; 437 int result;
438 enum kauth_network_req req; 438 enum kauth_network_req req;
439 439
440 result = KAUTH_RESULT_DEFER; 440 result = KAUTH_RESULT_DEFER;
441 req = (enum kauth_network_req)arg0; 441 req = (enum kauth_network_req)arg0;
442 442
443 if (action != KAUTH_NETWORK_SOCKET) 443 if (action != KAUTH_NETWORK_SOCKET)
444 return result; 444 return result;
445 445
446 switch (req) { 446 switch (req) {
447 case KAUTH_REQ_NETWORK_SOCKET_DROP: { 447 case KAUTH_REQ_NETWORK_SOCKET_DROP: {
448 /* Normal users can only drop their own connections. */ 448 /* Normal users can only drop their own connections. */
449 struct socket *so = (struct socket *)arg1; 449 struct socket *so = (struct socket *)arg1;
450 uid_t sockuid = so->so_uidinfo->ui_uid; 450 uid_t sockuid = so->so_uidinfo->ui_uid;
451 451
452 if (sockuid == kauth_cred_getuid(cred) || 452 if (sockuid == kauth_cred_getuid(cred) ||
453 sockuid == kauth_cred_geteuid(cred)) 453 sockuid == kauth_cred_geteuid(cred))
454 result = KAUTH_RESULT_ALLOW; 454 result = KAUTH_RESULT_ALLOW;
455 455
456 break; 456 break;
457 } 457 }
458 458
459 case KAUTH_REQ_NETWORK_SOCKET_OPEN: 459 case KAUTH_REQ_NETWORK_SOCKET_OPEN:
460 /* We allow "raw" routing/bluetooth sockets to anyone. */ 460 /* We allow "raw" routing/bluetooth sockets to anyone. */
461 if ((u_long)arg1 == PF_ROUTE || (u_long)arg1 == PF_BLUETOOTH) 461 if ((u_long)arg1 == PF_ROUTE || (u_long)arg1 == PF_BLUETOOTH)
462 result = KAUTH_RESULT_ALLOW; 462 result = KAUTH_RESULT_ALLOW;
463 else { 463 else {
464 /* Privileged, let secmodel handle this. */ 464 /* Privileged, let secmodel handle this. */
465 if ((u_long)arg2 == SOCK_RAW) 465 if ((u_long)arg2 == SOCK_RAW)
466 break; 466 break;
467 } 467 }
468 468
469 result = KAUTH_RESULT_ALLOW; 469 result = KAUTH_RESULT_ALLOW;
470 470
471 break; 471 break;
472 472
 473 case KAUTH_REQ_NETWORK_SOCKET_CANSEE:
 474 result = KAUTH_RESULT_ALLOW;
 475
 476 break;
 477
473 default: 478 default:
474 break; 479 break;
475 } 480 }
476 481
477 return result; 482 return result;
478} 483}
479 484
480void 485void
481soinit(void) 486soinit(void)
482{ 487{
483 488
484 sysctl_kern_somaxkva_setup(); 489 sysctl_kern_somaxkva_setup();
485 490
486 mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM); 491 mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM);
487 softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 492 softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
488 cv_init(&socurkva_cv, "sokva"); 493 cv_init(&socurkva_cv, "sokva");
489 soinit2(); 494 soinit2();
490 495
491 /* Set the initial adjusted socket buffer size. */ 496 /* Set the initial adjusted socket buffer size. */
492 if (sb_max_set(sb_max)) 497 if (sb_max_set(sb_max))
493 panic("bad initial sb_max value: %lu", sb_max); 498 panic("bad initial sb_max value: %lu", sb_max);
494 499
495 callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback, 500 callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback,
496 &sokva_reclaimerentry, NULL, sokva_reclaim_callback); 501 &sokva_reclaimerentry, NULL, sokva_reclaim_callback);
497 502
498 socket_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 503 socket_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
499 socket_listener_cb, NULL); 504 socket_listener_cb, NULL);
500} 505}
501 506
502/* 507/*
503 * Socket operation routines. 508 * Socket operation routines.
504 * These routines are called by the routines in 509 * These routines are called by the routines in
505 * sys_socket.c or from a system process, and 510 * sys_socket.c or from a system process, and
506 * implement the semantics of socket operations by 511 * implement the semantics of socket operations by
507 * switching out to the protocol specific routines. 512 * switching out to the protocol specific routines.
508 */ 513 */
509/*ARGSUSED*/ 514/*ARGSUSED*/
510int 515int
511socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l, 516socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l,
512 struct socket *lockso) 517 struct socket *lockso)
513{ 518{
514 const struct protosw *prp; 519 const struct protosw *prp;
515 struct socket *so; 520 struct socket *so;
516 uid_t uid; 521 uid_t uid;
517 int error; 522 int error;
518 kmutex_t *lock; 523 kmutex_t *lock;
519 524
520 error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET, 525 error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,
521 KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type), 526 KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type),
522 KAUTH_ARG(proto)); 527 KAUTH_ARG(proto));
523 if (error != 0) 528 if (error != 0)
524 return error; 529 return error;
525 530
526 if (proto) 531 if (proto)
527 prp = pffindproto(dom, proto, type); 532 prp = pffindproto(dom, proto, type);
528 else 533 else
529 prp = pffindtype(dom, type); 534 prp = pffindtype(dom, type);
530 if (prp == NULL) { 535 if (prp == NULL) {
531 /* no support for domain */ 536 /* no support for domain */
532 if (pffinddomain(dom) == 0) 537 if (pffinddomain(dom) == 0)
533 return EAFNOSUPPORT; 538 return EAFNOSUPPORT;
534 /* no support for socket type */ 539 /* no support for socket type */
535 if (proto == 0 && type != 0) 540 if (proto == 0 && type != 0)
536 return EPROTOTYPE; 541 return EPROTOTYPE;
537 return EPROTONOSUPPORT; 542 return EPROTONOSUPPORT;
538 } 543 }
539 if (prp->pr_usrreq == NULL) 544 if (prp->pr_usrreq == NULL)
540 return EPROTONOSUPPORT; 545 return EPROTONOSUPPORT;
541 if (prp->pr_type != type) 546 if (prp->pr_type != type)
542 return EPROTOTYPE; 547 return EPROTOTYPE;
543 548
544 so = soget(true); 549 so = soget(true);
545 so->so_type = type; 550 so->so_type = type;
546 so->so_proto = prp; 551 so->so_proto = prp;
547 so->so_send = sosend; 552 so->so_send = sosend;
548 so->so_receive = soreceive; 553 so->so_receive = soreceive;
549#ifdef MBUFTRACE 554#ifdef MBUFTRACE
550 so->so_rcv.sb_mowner = &prp->pr_domain->dom_mowner; 555 so->so_rcv.sb_mowner = &prp->pr_domain->dom_mowner;
551 so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner; 556 so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;
552 so->so_mowner = &prp->pr_domain->dom_mowner; 557 so->so_mowner = &prp->pr_domain->dom_mowner;
553#endif 558#endif
554 /* so->so_cred = kauth_cred_dup(l->l_cred); */ 559 /* so->so_cred = kauth_cred_dup(l->l_cred); */
555 uid = kauth_cred_geteuid(l->l_cred); 560 uid = kauth_cred_geteuid(l->l_cred);
556 so->so_uidinfo = uid_find(uid); 561 so->so_uidinfo = uid_find(uid);
557 so->so_egid = kauth_cred_getegid(l->l_cred); 562 so->so_egid = kauth_cred_getegid(l->l_cred);
558 so->so_cpid = l->l_proc->p_pid; 563 so->so_cpid = l->l_proc->p_pid;
559 if (lockso != NULL) { 564 if (lockso != NULL) {
560 /* Caller wants us to share a lock. */ 565 /* Caller wants us to share a lock. */
561 lock = lockso->so_lock; 566 lock = lockso->so_lock;
562 so->so_lock = lock; 567 so->so_lock = lock;
563 mutex_obj_hold(lock); 568 mutex_obj_hold(lock);
564 mutex_enter(lock); 569 mutex_enter(lock);
565 } else { 570 } else {
566 /* Lock assigned and taken during PRU_ATTACH. */ 571 /* Lock assigned and taken during PRU_ATTACH. */
567 } 572 }
568 error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL, 573 error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,
569 (struct mbuf *)(long)proto, NULL, l); 574 (struct mbuf *)(long)proto, NULL, l);
570 KASSERT(solocked(so)); 575 KASSERT(solocked(so));
571 if (error != 0) { 576 if (error != 0) {
572 so->so_state |= SS_NOFDREF; 577 so->so_state |= SS_NOFDREF;
573 sofree(so); 578 sofree(so);
574 return error; 579 return error;
575 } 580 }
576 sounlock(so); 581 sounlock(so);
577 *aso = so; 582 *aso = so;
578 return 0; 583 return 0;
579} 584}
580 585
581/* On success, write file descriptor to fdout and return zero. On 586/* On success, write file descriptor to fdout and return zero. On
582 * failure, return non-zero; *fdout will be undefined. 587 * failure, return non-zero; *fdout will be undefined.
583 */ 588 */
584int 589int
585fsocreate(int domain, struct socket **sop, int type, int protocol, 590fsocreate(int domain, struct socket **sop, int type, int protocol,
586 struct lwp *l, int *fdout) 591 struct lwp *l, int *fdout)
587{ 592{
588 struct socket *so; 593 struct socket *so;
589 struct file *fp; 594 struct file *fp;
590 int fd, error; 595 int fd, error;
591 596
592 if ((error = fd_allocfile(&fp, &fd)) != 0) 597 if ((error = fd_allocfile(&fp, &fd)) != 0)
593 return (error); 598 return (error);
594 fp->f_flag = FREAD|FWRITE; 599 fp->f_flag = FREAD|FWRITE;
595 fp->f_type = DTYPE_SOCKET; 600 fp->f_type = DTYPE_SOCKET;
596 fp->f_ops = &socketops; 601 fp->f_ops = &socketops;
597 error = socreate(domain, &so, type, protocol, l, NULL); 602 error = socreate(domain, &so, type, protocol, l, NULL);
598 if (error != 0) { 603 if (error != 0) {
599 fd_abort(curproc, fp, fd); 604 fd_abort(curproc, fp, fd);
600 } else { 605 } else {
601 if (sop != NULL) 606 if (sop != NULL)
602 *sop = so; 607 *sop = so;
603 fp->f_data = so; 608 fp->f_data = so;
604 fd_affix(curproc, fp, fd); 609 fd_affix(curproc, fp, fd);
605 *fdout = fd; 610 *fdout = fd;
606 } 611 }
607 return error; 612 return error;
608} 613}
609 614
610int 615int
611sofamily(const struct socket *so) 616sofamily(const struct socket *so)
612{ 617{
613 const struct protosw *pr; 618 const struct protosw *pr;
614 const struct domain *dom; 619 const struct domain *dom;
615 620
616 if ((pr = so->so_proto) == NULL) 621 if ((pr = so->so_proto) == NULL)
617 return AF_UNSPEC; 622 return AF_UNSPEC;
618 if ((dom = pr->pr_domain) == NULL) 623 if ((dom = pr->pr_domain) == NULL)
619 return AF_UNSPEC; 624 return AF_UNSPEC;
620 return dom->dom_family; 625 return dom->dom_family;
621} 626}
622 627
623int 628int
624sobind(struct socket *so, struct mbuf *nam, struct lwp *l) 629sobind(struct socket *so, struct mbuf *nam, struct lwp *l)
625{ 630{
626 int error; 631 int error;
627 632
628 solock(so); 633 solock(so);
629 error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, l); 634 error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, l);
630 sounlock(so); 635 sounlock(so);
631 return error; 636 return error;
632} 637}
633 638
634int 639int
635solisten(struct socket *so, int backlog, struct lwp *l) 640solisten(struct socket *so, int backlog, struct lwp *l)
636{ 641{
637 int error; 642 int error;
638 643
639 solock(so); 644 solock(so);
640 if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING |  645 if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING |
641 SS_ISDISCONNECTING)) != 0) { 646 SS_ISDISCONNECTING)) != 0) {
642 sounlock(so); 647 sounlock(so);
643 return (EOPNOTSUPP); 648 return (EOPNOTSUPP);
644 } 649 }
645 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, 650 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL,
646 NULL, NULL, l); 651 NULL, NULL, l);
647 if (error != 0) { 652 if (error != 0) {
648 sounlock(so); 653 sounlock(so);
649 return error; 654 return error;
650 } 655 }
651 if (TAILQ_EMPTY(&so->so_q)) 656 if (TAILQ_EMPTY(&so->so_q))
652 so->so_options |= SO_ACCEPTCONN; 657 so->so_options |= SO_ACCEPTCONN;
653 if (backlog < 0) 658 if (backlog < 0)
654 backlog = 0; 659 backlog = 0;
655 so->so_qlimit = min(backlog, somaxconn); 660 so->so_qlimit = min(backlog, somaxconn);
656 sounlock(so); 661 sounlock(so);
657 return 0; 662 return 0;
658} 663}
659 664
660void 665void
661sofree(struct socket *so) 666sofree(struct socket *so)
662{ 667{
663 u_int refs; 668 u_int refs;
664 669
665 KASSERT(solocked(so)); 670 KASSERT(solocked(so));
666 671
667 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) { 672 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) {
668 sounlock(so); 673 sounlock(so);
669 return; 674 return;
670 } 675 }
671 if (so->so_head) { 676 if (so->so_head) {
672 /* 677 /*
673 * We must not decommission a socket that's on the accept(2) 678 * We must not decommission a socket that's on the accept(2)
674 * queue. If we do, then accept(2) may hang after select(2) 679 * queue. If we do, then accept(2) may hang after select(2)
675 * indicated that the listening socket was ready. 680 * indicated that the listening socket was ready.
676 */ 681 */
677 if (!soqremque(so, 0)) { 682 if (!soqremque(so, 0)) {
678 sounlock(so); 683 sounlock(so);
679 return; 684 return;
680 } 685 }
681 } 686 }
682 if (so->so_rcv.sb_hiwat) 687 if (so->so_rcv.sb_hiwat)
683 (void)chgsbsize(so->so_uidinfo, &so->so_rcv.sb_hiwat, 0, 688 (void)chgsbsize(so->so_uidinfo, &so->so_rcv.sb_hiwat, 0,
684 RLIM_INFINITY); 689 RLIM_INFINITY);
685 if (so->so_snd.sb_hiwat) 690 if (so->so_snd.sb_hiwat)
686 (void)chgsbsize(so->so_uidinfo, &so->so_snd.sb_hiwat, 0, 691 (void)chgsbsize(so->so_uidinfo, &so->so_snd.sb_hiwat, 0,
687 RLIM_INFINITY); 692 RLIM_INFINITY);
688 sbrelease(&so->so_snd, so); 693 sbrelease(&so->so_snd, so);
689 KASSERT(!cv_has_waiters(&so->so_cv)); 694 KASSERT(!cv_has_waiters(&so->so_cv));
690 KASSERT(!cv_has_waiters(&so->so_rcv.sb_cv)); 695 KASSERT(!cv_has_waiters(&so->so_rcv.sb_cv));
691 KASSERT(!cv_has_waiters(&so->so_snd.sb_cv)); 696 KASSERT(!cv_has_waiters(&so->so_snd.sb_cv));
692 sorflush(so); 697 sorflush(so);
693 refs = so->so_aborting; /* XXX */ 698 refs = so->so_aborting; /* XXX */
694 /* Remove acccept filter if one is present. */ 699 /* Remove acccept filter if one is present. */
695 if (so->so_accf != NULL) 700 if (so->so_accf != NULL)
696 (void)accept_filt_clear(so); 701 (void)accept_filt_clear(so);
697 /* kauth_cred_free(so->so_cred); */ 702 /* kauth_cred_free(so->so_cred); */
698 sounlock(so); 703 sounlock(so);
699 if (refs == 0) /* XXX */ 704 if (refs == 0) /* XXX */
700 soput(so); 705 soput(so);
701} 706}
702 707
703/* 708/*
704 * Close a socket on last file table reference removal. 709 * Close a socket on last file table reference removal.
705 * Initiate disconnect if connected. 710 * Initiate disconnect if connected.
706 * Free socket when disconnect complete. 711 * Free socket when disconnect complete.
707 */ 712 */
708int 713int
709soclose(struct socket *so) 714soclose(struct socket *so)
710{ 715{
711 struct socket *so2; 716 struct socket *so2;
712 int error; 717 int error;
713 int error2; 718 int error2;
714 719
715 error = 0; 720 error = 0;
716 solock(so); 721 solock(so);
717 if (so->so_options & SO_ACCEPTCONN) { 722 if (so->so_options & SO_ACCEPTCONN) {
718 for (;;) { 723 for (;;) {
719 if ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) { 724 if ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {
720 KASSERT(solocked2(so, so2)); 725 KASSERT(solocked2(so, so2));
721 (void) soqremque(so2, 0); 726 (void) soqremque(so2, 0);
722 /* soabort drops the lock. */ 727 /* soabort drops the lock. */
723 (void) soabort(so2); 728 (void) soabort(so2);
724 solock(so); 729 solock(so);
725 continue; 730 continue;
726 } 731 }
727 if ((so2 = TAILQ_FIRST(&so->so_q)) != 0) { 732 if ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {
728 KASSERT(solocked2(so, so2)); 733 KASSERT(solocked2(so, so2));
729 (void) soqremque(so2, 1); 734 (void) soqremque(so2, 1);
730 /* soabort drops the lock. */ 735 /* soabort drops the lock. */
731 (void) soabort(so2); 736 (void) soabort(so2);
732 solock(so); 737 solock(so);
733 continue; 738 continue;
734 } 739 }
735 break; 740 break;
736 } 741 }
737 } 742 }
738 if (so->so_pcb == 0) 743 if (so->so_pcb == 0)
739 goto discard; 744 goto discard;
740 if (so->so_state & SS_ISCONNECTED) { 745 if (so->so_state & SS_ISCONNECTED) {
741 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 746 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
742 error = sodisconnect(so); 747 error = sodisconnect(so);
743 if (error) 748 if (error)
744 goto drop; 749 goto drop;
745 } 750 }
746 if (so->so_options & SO_LINGER) { 751 if (so->so_options & SO_LINGER) {
747 if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio) 752 if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio)
748 goto drop; 753 goto drop;
749 while (so->so_state & SS_ISCONNECTED) { 754 while (so->so_state & SS_ISCONNECTED) {
750 error = sowait(so, true, so->so_linger * hz); 755 error = sowait(so, true, so->so_linger * hz);
751 if (error) 756 if (error)
752 break; 757 break;
753 } 758 }
754 } 759 }
755 } 760 }
756 drop: 761 drop:
757 if (so->so_pcb) { 762 if (so->so_pcb) {
758 error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 763 error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
759 NULL, NULL, NULL, NULL); 764 NULL, NULL, NULL, NULL);
760 if (error == 0) 765 if (error == 0)
761 error = error2; 766 error = error2;
762 } 767 }
763 discard: 768 discard:
764 if (so->so_state & SS_NOFDREF) 769 if (so->so_state & SS_NOFDREF)
765 panic("soclose: NOFDREF"); 770 panic("soclose: NOFDREF");
766 so->so_state |= SS_NOFDREF; 771 so->so_state |= SS_NOFDREF;
767 sofree(so); 772 sofree(so);
768 return (error); 773 return (error);
769} 774}
770 775
771/* 776/*
772 * Must be called with the socket locked.. Will return with it unlocked. 777 * Must be called with the socket locked.. Will return with it unlocked.
773 */ 778 */
774int 779int
775soabort(struct socket *so) 780soabort(struct socket *so)
776{ 781{
777 u_int refs; 782 u_int refs;
778 int error; 783 int error;
779  784
780 KASSERT(solocked(so)); 785 KASSERT(solocked(so));
781 KASSERT(so->so_head == NULL); 786 KASSERT(so->so_head == NULL);
782 787
783 so->so_aborting++; /* XXX */ 788 so->so_aborting++; /* XXX */
784 error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL, 789 error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL,
785 NULL, NULL, NULL); 790 NULL, NULL, NULL);
786 refs = --so->so_aborting; /* XXX */ 791 refs = --so->so_aborting; /* XXX */
787 if (error || (refs == 0)) { 792 if (error || (refs == 0)) {
788 sofree(so); 793 sofree(so);
789 } else { 794 } else {
790 sounlock(so); 795 sounlock(so);
791 } 796 }
792 return error; 797 return error;
793} 798}
794 799
795int 800int
796soaccept(struct socket *so, struct mbuf *nam) 801soaccept(struct socket *so, struct mbuf *nam)
797{ 802{
798 int error; 803 int error;
799 804
800 KASSERT(solocked(so)); 805 KASSERT(solocked(so));
801 806
802 error = 0; 807 error = 0;
803 if ((so->so_state & SS_NOFDREF) == 0) 808 if ((so->so_state & SS_NOFDREF) == 0)
804 panic("soaccept: !NOFDREF"); 809 panic("soaccept: !NOFDREF");
805 so->so_state &= ~SS_NOFDREF; 810 so->so_state &= ~SS_NOFDREF;
806 if ((so->so_state & SS_ISDISCONNECTED) == 0 || 811 if ((so->so_state & SS_ISDISCONNECTED) == 0 ||
807 (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0) 812 (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)
808 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 813 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
809 NULL, nam, NULL, NULL); 814 NULL, nam, NULL, NULL);
810 else 815 else
811 error = ECONNABORTED; 816 error = ECONNABORTED;
812 817
813 return (error); 818 return (error);
814} 819}
815 820
816int 821int
817soconnect(struct socket *so, struct mbuf *nam, struct lwp *l) 822soconnect(struct socket *so, struct mbuf *nam, struct lwp *l)
818{ 823{
819 int error; 824 int error;
820 825
821 KASSERT(solocked(so)); 826 KASSERT(solocked(so));
822 827
823 if (so->so_options & SO_ACCEPTCONN) 828 if (so->so_options & SO_ACCEPTCONN)
824 return (EOPNOTSUPP); 829 return (EOPNOTSUPP);
825 /* 830 /*
826 * If protocol is connection-based, can only connect once. 831 * If protocol is connection-based, can only connect once.
827 * Otherwise, if connected, try to disconnect first. 832 * Otherwise, if connected, try to disconnect first.
828 * This allows user to disconnect by connecting to, e.g., 833 * This allows user to disconnect by connecting to, e.g.,
829 * a null address. 834 * a null address.
830 */ 835 */
831 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 836 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
832 ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 837 ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
833 (error = sodisconnect(so)))) 838 (error = sodisconnect(so))))
834 error = EISCONN; 839 error = EISCONN;
835 else 840 else
836 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 841 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
837 NULL, nam, NULL, l); 842 NULL, nam, NULL, l);
838 return (error); 843 return (error);
839} 844}
840 845
841int 846int
842soconnect2(struct socket *so1, struct socket *so2) 847soconnect2(struct socket *so1, struct socket *so2)
843{ 848{
844 int error; 849 int error;
845 850
846 KASSERT(solocked2(so1, so2)); 851 KASSERT(solocked2(so1, so2));
847 852
848 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 853 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
849 NULL, (struct mbuf *)so2, NULL, NULL); 854 NULL, (struct mbuf *)so2, NULL, NULL);
850 return (error); 855 return (error);
851} 856}
852 857
853int 858int
854sodisconnect(struct socket *so) 859sodisconnect(struct socket *so)
855{ 860{
856 int error; 861 int error;
857 862
858 KASSERT(solocked(so)); 863 KASSERT(solocked(so));
859 864
860 if ((so->so_state & SS_ISCONNECTED) == 0) { 865 if ((so->so_state & SS_ISCONNECTED) == 0) {
861 error = ENOTCONN; 866 error = ENOTCONN;
862 } else if (so->so_state & SS_ISDISCONNECTING) { 867 } else if (so->so_state & SS_ISDISCONNECTING) {
863 error = EALREADY; 868 error = EALREADY;
864 } else { 869 } else {
865 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 870 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
866 NULL, NULL, NULL, NULL); 871 NULL, NULL, NULL, NULL);
867 } 872 }
868 sodopendfree(); 873 sodopendfree();
869 return (error); 874 return (error);
870} 875}
871 876
872#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) 877#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
873/* 878/*
874 * Send on a socket. 879 * Send on a socket.
875 * If send must go all at once and message is larger than 880 * If send must go all at once and message is larger than
876 * send buffering, then hard error. 881 * send buffering, then hard error.
877 * Lock against other senders. 882 * Lock against other senders.
878 * If must go all at once and not enough room now, then 883 * If must go all at once and not enough room now, then
879 * inform user that this would block and do nothing. 884 * inform user that this would block and do nothing.
880 * Otherwise, if nonblocking, send as much as possible. 885 * Otherwise, if nonblocking, send as much as possible.
881 * The data to be sent is described by "uio" if nonzero, 886 * The data to be sent is described by "uio" if nonzero,
882 * otherwise by the mbuf chain "top" (which must be null 887 * otherwise by the mbuf chain "top" (which must be null
883 * if uio is not). Data provided in mbuf chain must be small 888 * if uio is not). Data provided in mbuf chain must be small
884 * enough to send all at once. 889 * enough to send all at once.
885 * 890 *
886 * Returns nonzero on error, timeout or signal; callers 891 * Returns nonzero on error, timeout or signal; callers
887 * must check for short counts if EINTR/ERESTART are returned. 892 * must check for short counts if EINTR/ERESTART are returned.
888 * Data and control buffers are freed on return. 893 * Data and control buffers are freed on return.
889 */ 894 */
890int 895int
891sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, 896sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top,
892 struct mbuf *control, int flags, struct lwp *l) 897 struct mbuf *control, int flags, struct lwp *l)
893{ 898{
894 struct mbuf **mp, *m; 899 struct mbuf **mp, *m;
895 struct proc *p; 900 struct proc *p;
896 long space, len, resid, clen, mlen; 901 long space, len, resid, clen, mlen;
897 int error, s, dontroute, atomic; 902 int error, s, dontroute, atomic;
898 903
899 p = l->l_proc; 904 p = l->l_proc;
900 sodopendfree(); 905 sodopendfree();
901 clen = 0; 906 clen = 0;
902 907
903 /* 908 /*
904 * solock() provides atomicity of access. splsoftnet() prevents 909 * solock() provides atomicity of access. splsoftnet() prevents
905 * protocol processing soft interrupts from interrupting us and 910 * protocol processing soft interrupts from interrupting us and
906 * blocking (expensive). 911 * blocking (expensive).
907 */ 912 */
908 s = splsoftnet(); 913 s = splsoftnet();
909 solock(so); 914 solock(so);
910 atomic = sosendallatonce(so) || top; 915 atomic = sosendallatonce(so) || top;
911 if (uio) 916 if (uio)
912 resid = uio->uio_resid; 917 resid = uio->uio_resid;
913 else 918 else
914 resid = top->m_pkthdr.len; 919 resid = top->m_pkthdr.len;
915 /* 920 /*
916 * In theory resid should be unsigned. 921 * In theory resid should be unsigned.
917 * However, space must be signed, as it might be less than 0 922 * However, space must be signed, as it might be less than 0
918 * if we over-committed, and we must use a signed comparison 923 * if we over-committed, and we must use a signed comparison
919 * of space and resid. On the other hand, a negative resid 924 * of space and resid. On the other hand, a negative resid
920 * causes us to loop sending 0-length segments to the protocol. 925 * causes us to loop sending 0-length segments to the protocol.
921 */ 926 */
922 if (resid < 0) { 927 if (resid < 0) {
923 error = EINVAL; 928 error = EINVAL;
924 goto out; 929 goto out;
925 } 930 }
926 dontroute = 931 dontroute =
927 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 932 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
928 (so->so_proto->pr_flags & PR_ATOMIC); 933 (so->so_proto->pr_flags & PR_ATOMIC);
929 l->l_ru.ru_msgsnd++; 934 l->l_ru.ru_msgsnd++;
930 if (control) 935 if (control)
931 clen = control->m_len; 936 clen = control->m_len;
932 restart: 937 restart:
933 if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) 938 if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
934 goto out; 939 goto out;
935 do { 940 do {
936 if (so->so_state & SS_CANTSENDMORE) { 941 if (so->so_state & SS_CANTSENDMORE) {
937 error = EPIPE; 942 error = EPIPE;
938 goto release; 943 goto release;
939 } 944 }
940 if (so->so_error) { 945 if (so->so_error) {
941 error = so->so_error; 946 error = so->so_error;
942 so->so_error = 0; 947 so->so_error = 0;
943 goto release; 948 goto release;
944 } 949 }
945 if ((so->so_state & SS_ISCONNECTED) == 0) { 950 if ((so->so_state & SS_ISCONNECTED) == 0) {
946 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 951 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
947 if ((so->so_state & SS_ISCONFIRMING) == 0 && 952 if ((so->so_state & SS_ISCONFIRMING) == 0 &&
948 !(resid == 0 && clen != 0)) { 953 !(resid == 0 && clen != 0)) {
949 error = ENOTCONN; 954 error = ENOTCONN;
950 goto release; 955 goto release;
951 } 956 }
952 } else if (addr == 0) { 957 } else if (addr == 0) {
953 error = EDESTADDRREQ; 958 error = EDESTADDRREQ;
954 goto release; 959 goto release;
955 } 960 }
956 } 961 }
957 space = sbspace(&so->so_snd); 962 space = sbspace(&so->so_snd);
958 if (flags & MSG_OOB) 963 if (flags & MSG_OOB)
959 space += 1024; 964 space += 1024;
960 if ((atomic && resid > so->so_snd.sb_hiwat) || 965 if ((atomic && resid > so->so_snd.sb_hiwat) ||
961 clen > so->so_snd.sb_hiwat) { 966 clen > so->so_snd.sb_hiwat) {
962 error = EMSGSIZE; 967 error = EMSGSIZE;
963 goto release; 968 goto release;
964 } 969 }
965 if (space < resid + clen && 970 if (space < resid + clen &&
966 (atomic || space < so->so_snd.sb_lowat || space < clen)) { 971 (atomic || space < so->so_snd.sb_lowat || space < clen)) {
967 if (so->so_nbio) { 972 if (so->so_nbio) {
968 error = EWOULDBLOCK; 973 error = EWOULDBLOCK;
969 goto release; 974 goto release;
970 } 975 }
971 sbunlock(&so->so_snd); 976 sbunlock(&so->so_snd);
972 error = sbwait(&so->so_snd); 977 error = sbwait(&so->so_snd);
973 if (error) 978 if (error)
974 goto out; 979 goto out;
975 goto restart; 980 goto restart;
976 } 981 }
977 mp = &top; 982 mp = &top;
978 space -= clen; 983 space -= clen;
979 do { 984 do {
980 if (uio == NULL) { 985 if (uio == NULL) {
981 /* 986 /*
982 * Data is prepackaged in "top". 987 * Data is prepackaged in "top".
983 */ 988 */
984 resid = 0; 989 resid = 0;
985 if (flags & MSG_EOR) 990 if (flags & MSG_EOR)
986 top->m_flags |= M_EOR; 991 top->m_flags |= M_EOR;
987 } else do { 992 } else do {
988 sounlock(so); 993 sounlock(so);
989 splx(s); 994 splx(s);
990 if (top == NULL) { 995 if (top == NULL) {
991 m = m_gethdr(M_WAIT, MT_DATA); 996 m = m_gethdr(M_WAIT, MT_DATA);
992 mlen = MHLEN; 997 mlen = MHLEN;
993 m->m_pkthdr.len = 0; 998 m->m_pkthdr.len = 0;
994 m->m_pkthdr.rcvif = NULL; 999 m->m_pkthdr.rcvif = NULL;
995 } else { 1000 } else {
996 m = m_get(M_WAIT, MT_DATA); 1001 m = m_get(M_WAIT, MT_DATA);
997 mlen = MLEN; 1002 mlen = MLEN;
998 } 1003 }
999 MCLAIM(m, so->so_snd.sb_mowner); 1004 MCLAIM(m, so->so_snd.sb_mowner);
1000 if (sock_loan_thresh >= 0 && 1005 if (sock_loan_thresh >= 0 &&
1001 uio->uio_iov->iov_len >= sock_loan_thresh && 1006 uio->uio_iov->iov_len >= sock_loan_thresh &&
1002 space >= sock_loan_thresh && 1007 space >= sock_loan_thresh &&
1003 (len = sosend_loan(so, uio, m, 1008 (len = sosend_loan(so, uio, m,
1004 space)) != 0) { 1009 space)) != 0) {
1005 SOSEND_COUNTER_INCR(&sosend_loan_big); 1010 SOSEND_COUNTER_INCR(&sosend_loan_big);
1006 space -= len; 1011 space -= len;
1007 goto have_data; 1012 goto have_data;
1008 } 1013 }
1009 if (resid >= MINCLSIZE && space >= MCLBYTES) { 1014 if (resid >= MINCLSIZE && space >= MCLBYTES) {
1010 SOSEND_COUNTER_INCR(&sosend_copy_big); 1015 SOSEND_COUNTER_INCR(&sosend_copy_big);
1011 m_clget(m, M_WAIT); 1016 m_clget(m, M_WAIT);
1012 if ((m->m_flags & M_EXT) == 0) 1017 if ((m->m_flags & M_EXT) == 0)
1013 goto nopages; 1018 goto nopages;
1014 mlen = MCLBYTES; 1019 mlen = MCLBYTES;
1015 if (atomic && top == 0) { 1020 if (atomic && top == 0) {
1016 len = lmin(MCLBYTES - max_hdr, 1021 len = lmin(MCLBYTES - max_hdr,
1017 resid); 1022 resid);
1018 m->m_data += max_hdr; 1023 m->m_data += max_hdr;
1019 } else 1024 } else
1020 len = lmin(MCLBYTES, resid); 1025 len = lmin(MCLBYTES, resid);
1021 space -= len; 1026 space -= len;
1022 } else { 1027 } else {
1023 nopages: 1028 nopages:
1024 SOSEND_COUNTER_INCR(&sosend_copy_small); 1029 SOSEND_COUNTER_INCR(&sosend_copy_small);
1025 len = lmin(lmin(mlen, resid), space); 1030 len = lmin(lmin(mlen, resid), space);
1026 space -= len; 1031 space -= len;
1027 /* 1032 /*
1028 * For datagram protocols, leave room 1033 * For datagram protocols, leave room
1029 * for protocol headers in first mbuf. 1034 * for protocol headers in first mbuf.
1030 */ 1035 */
1031 if (atomic && top == 0 && len < mlen) 1036 if (atomic && top == 0 && len < mlen)
1032 MH_ALIGN(m, len); 1037 MH_ALIGN(m, len);
1033 } 1038 }
1034 error = uiomove(mtod(m, void *), (int)len, uio); 1039 error = uiomove(mtod(m, void *), (int)len, uio);
1035 have_data: 1040 have_data:
1036 resid = uio->uio_resid; 1041 resid = uio->uio_resid;
1037 m->m_len = len; 1042 m->m_len = len;
1038 *mp = m; 1043 *mp = m;
1039 top->m_pkthdr.len += len; 1044 top->m_pkthdr.len += len;
1040 s = splsoftnet(); 1045 s = splsoftnet();
1041 solock(so); 1046 solock(so);
1042 if (error != 0) 1047 if (error != 0)
1043 goto release; 1048 goto release;
1044 mp = &m->m_next; 1049 mp = &m->m_next;
1045 if (resid <= 0) { 1050 if (resid <= 0) {
1046 if (flags & MSG_EOR) 1051 if (flags & MSG_EOR)
1047 top->m_flags |= M_EOR; 1052 top->m_flags |= M_EOR;
1048 break; 1053 break;
1049 } 1054 }
1050 } while (space > 0 && atomic); 1055 } while (space > 0 && atomic);
1051 1056
1052 if (so->so_state & SS_CANTSENDMORE) { 1057 if (so->so_state & SS_CANTSENDMORE) {
1053 error = EPIPE; 1058 error = EPIPE;
1054 goto release; 1059 goto release;
1055 } 1060 }
1056 if (dontroute) 1061 if (dontroute)
1057 so->so_options |= SO_DONTROUTE; 1062 so->so_options |= SO_DONTROUTE;
1058 if (resid > 0) 1063 if (resid > 0)
1059 so->so_state |= SS_MORETOCOME; 1064 so->so_state |= SS_MORETOCOME;
1060 error = (*so->so_proto->pr_usrreq)(so, 1065 error = (*so->so_proto->pr_usrreq)(so,
1061 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 1066 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
1062 top, addr, control, curlwp); 1067 top, addr, control, curlwp);
1063 if (dontroute) 1068 if (dontroute)
1064 so->so_options &= ~SO_DONTROUTE; 1069 so->so_options &= ~SO_DONTROUTE;
1065 if (resid > 0) 1070 if (resid > 0)
1066 so->so_state &= ~SS_MORETOCOME; 1071 so->so_state &= ~SS_MORETOCOME;
1067 clen = 0; 1072 clen = 0;
1068 control = NULL; 1073 control = NULL;
1069 top = NULL; 1074 top = NULL;
1070 mp = &top; 1075 mp = &top;
1071 if (error != 0) 1076 if (error != 0)
1072 goto release; 1077 goto release;
1073 } while (resid && space > 0); 1078 } while (resid && space > 0);
1074 } while (resid); 1079 } while (resid);
1075 1080
1076 release: 1081 release:
1077 sbunlock(&so->so_snd); 1082 sbunlock(&so->so_snd);
1078 out: 1083 out:
1079 sounlock(so); 1084 sounlock(so);
1080 splx(s); 1085 splx(s);
1081 if (top) 1086 if (top)
1082 m_freem(top); 1087 m_freem(top);
1083 if (control) 1088 if (control)
1084 m_freem(control); 1089 m_freem(control);
1085 return (error); 1090 return (error);
1086} 1091}
1087 1092
1088/* 1093/*
1089 * Following replacement or removal of the first mbuf on the first 1094 * Following replacement or removal of the first mbuf on the first
1090 * mbuf chain of a socket buffer, push necessary state changes back 1095 * mbuf chain of a socket buffer, push necessary state changes back
1091 * into the socket buffer so that other consumers see the values 1096 * into the socket buffer so that other consumers see the values
1092 * consistently. 'nextrecord' is the callers locally stored value of 1097 * consistently. 'nextrecord' is the callers locally stored value of
1093 * the original value of sb->sb_mb->m_nextpkt which must be restored 1098 * the original value of sb->sb_mb->m_nextpkt which must be restored
1094 * when the lead mbuf changes. NOTE: 'nextrecord' may be NULL. 1099 * when the lead mbuf changes. NOTE: 'nextrecord' may be NULL.
1095 */ 1100 */
1096static void 1101static void
1097sbsync(struct sockbuf *sb, struct mbuf *nextrecord) 1102sbsync(struct sockbuf *sb, struct mbuf *nextrecord)
1098{ 1103{
1099 1104
1100 KASSERT(solocked(sb->sb_so)); 1105 KASSERT(solocked(sb->sb_so));
1101 1106
1102 /* 1107 /*
1103 * First, update for the new value of nextrecord. If necessary, 1108 * First, update for the new value of nextrecord. If necessary,
1104 * make it the first record. 1109 * make it the first record.
1105 */ 1110 */
1106 if (sb->sb_mb != NULL) 1111 if (sb->sb_mb != NULL)
1107 sb->sb_mb->m_nextpkt = nextrecord; 1112 sb->sb_mb->m_nextpkt = nextrecord;
1108 else 1113 else
1109 sb->sb_mb = nextrecord; 1114 sb->sb_mb = nextrecord;
1110 1115
1111 /* 1116 /*
1112 * Now update any dependent socket buffer fields to reflect 1117 * Now update any dependent socket buffer fields to reflect
1113 * the new state. This is an inline of SB_EMPTY_FIXUP, with 1118 * the new state. This is an inline of SB_EMPTY_FIXUP, with
1114 * the addition of a second clause that takes care of the 1119 * the addition of a second clause that takes care of the
1115 * case where sb_mb has been updated, but remains the last 1120 * case where sb_mb has been updated, but remains the last
1116 * record. 1121 * record.
1117 */ 1122 */
1118 if (sb->sb_mb == NULL) { 1123 if (sb->sb_mb == NULL) {
1119 sb->sb_mbtail = NULL; 1124 sb->sb_mbtail = NULL;
1120 sb->sb_lastrecord = NULL; 1125 sb->sb_lastrecord = NULL;
1121 } else if (sb->sb_mb->m_nextpkt == NULL) 1126 } else if (sb->sb_mb->m_nextpkt == NULL)
1122 sb->sb_lastrecord = sb->sb_mb; 1127 sb->sb_lastrecord = sb->sb_mb;
1123} 1128}
1124 1129
1125/* 1130/*
1126 * Implement receive operations on a socket. 1131 * Implement receive operations on a socket.
1127 * We depend on the way that records are added to the sockbuf 1132 * We depend on the way that records are added to the sockbuf
1128 * by sbappend*. In particular, each record (mbufs linked through m_next) 1133 * by sbappend*. In particular, each record (mbufs linked through m_next)
1129 * must begin with an address if the protocol so specifies, 1134 * must begin with an address if the protocol so specifies,
1130 * followed by an optional mbuf or mbufs containing ancillary data, 1135 * followed by an optional mbuf or mbufs containing ancillary data,
1131 * and then zero or more mbufs of data. 1136 * and then zero or more mbufs of data.
1132 * In order to avoid blocking network interrupts for the entire time here, 1137 * In order to avoid blocking network interrupts for the entire time here,
1133 * we splx() while doing the actual copy to user space. 1138 * we splx() while doing the actual copy to user space.
1134 * Although the sockbuf is locked, new data may still be appended, 1139 * Although the sockbuf is locked, new data may still be appended,
1135 * and thus we must maintain consistency of the sockbuf during that time. 1140 * and thus we must maintain consistency of the sockbuf during that time.
1136 * 1141 *
1137 * The caller may receive the data as a single mbuf chain by supplying 1142 * The caller may receive the data as a single mbuf chain by supplying
1138 * an mbuf **mp0 for use in returning the chain. The uio is then used 1143 * an mbuf **mp0 for use in returning the chain. The uio is then used
1139 * only for the count in uio_resid. 1144 * only for the count in uio_resid.
1140 */ 1145 */
1141int 1146int
1142soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, 1147soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio,
1143 struct mbuf **mp0, struct mbuf **controlp, int *flagsp) 1148 struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
1144{ 1149{
1145 struct lwp *l = curlwp; 1150 struct lwp *l = curlwp;
1146 struct mbuf *m, **mp, *mt; 1151 struct mbuf *m, **mp, *mt;
1147 int atomic, flags, len, error, s, offset, moff, type, orig_resid; 1152 int atomic, flags, len, error, s, offset, moff, type, orig_resid;
1148 const struct protosw *pr; 1153 const struct protosw *pr;
1149 struct mbuf *nextrecord; 1154 struct mbuf *nextrecord;
1150 int mbuf_removed = 0; 1155 int mbuf_removed = 0;
1151 const struct domain *dom; 1156 const struct domain *dom;
1152 1157
1153 pr = so->so_proto; 1158 pr = so->so_proto;
1154 atomic = pr->pr_flags & PR_ATOMIC; 1159 atomic = pr->pr_flags & PR_ATOMIC;
1155 dom = pr->pr_domain; 1160 dom = pr->pr_domain;
1156 mp = mp0; 1161 mp = mp0;
1157 type = 0; 1162 type = 0;
1158 orig_resid = uio->uio_resid; 1163 orig_resid = uio->uio_resid;
1159 1164
1160 if (paddr != NULL) 1165 if (paddr != NULL)
1161 *paddr = NULL; 1166 *paddr = NULL;
1162 if (controlp != NULL) 1167 if (controlp != NULL)
1163 *controlp = NULL; 1168 *controlp = NULL;
1164 if (flagsp != NULL) 1169 if (flagsp != NULL)
1165 flags = *flagsp &~ MSG_EOR; 1170 flags = *flagsp &~ MSG_EOR;
1166 else 1171 else
1167 flags = 0; 1172 flags = 0;
1168 1173
1169 if ((flags & MSG_DONTWAIT) == 0) 1174 if ((flags & MSG_DONTWAIT) == 0)
1170 sodopendfree(); 1175 sodopendfree();
1171 1176
1172 if (flags & MSG_OOB) { 1177 if (flags & MSG_OOB) {
1173 m = m_get(M_WAIT, MT_DATA); 1178 m = m_get(M_WAIT, MT_DATA);
1174 solock(so); 1179 solock(so);
1175 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, 1180 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
1176 (struct mbuf *)(long)(flags & MSG_PEEK), NULL, l); 1181 (struct mbuf *)(long)(flags & MSG_PEEK), NULL, l);
1177 sounlock(so); 1182 sounlock(so);
1178 if (error) 1183 if (error)
1179 goto bad; 1184 goto bad;
1180 do { 1185 do {
1181 error = uiomove(mtod(m, void *), 1186 error = uiomove(mtod(m, void *),
1182 (int) min(uio->uio_resid, m->m_len), uio); 1187 (int) min(uio->uio_resid, m->m_len), uio);
1183 m = m_free(m); 1188 m = m_free(m);
1184 } while (uio->uio_resid > 0 && error == 0 && m); 1189 } while (uio->uio_resid > 0 && error == 0 && m);
1185 bad: 1190 bad:
1186 if (m != NULL) 1191 if (m != NULL)
1187 m_freem(m); 1192 m_freem(m);
1188 return error; 1193 return error;
1189 } 1194 }
1190 if (mp != NULL) 1195 if (mp != NULL)
1191 *mp = NULL; 1196 *mp = NULL;
1192 1197
1193 /* 1198 /*
1194 * solock() provides atomicity of access. splsoftnet() prevents 1199 * solock() provides atomicity of access. splsoftnet() prevents
1195 * protocol processing soft interrupts from interrupting us and 1200 * protocol processing soft interrupts from interrupting us and
1196 * blocking (expensive). 1201 * blocking (expensive).
1197 */ 1202 */
1198 s = splsoftnet(); 1203 s = splsoftnet();
1199 solock(so); 1204 solock(so);
1200 if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) 1205 if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
1201 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l); 1206 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l);
1202 1207
1203 restart: 1208 restart:
1204 if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) { 1209 if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) {
1205 sounlock(so); 1210 sounlock(so);
1206 splx(s); 1211 splx(s);
1207 return error; 1212 return error;
1208 } 1213 }
1209 1214
1210 m = so->so_rcv.sb_mb; 1215 m = so->so_rcv.sb_mb;
1211 /* 1216 /*
1212 * If we have less data than requested, block awaiting more 1217 * If we have less data than requested, block awaiting more
1213 * (subject to any timeout) if: 1218 * (subject to any timeout) if:
1214 * 1. the current count is less than the low water mark, 1219 * 1. the current count is less than the low water mark,
1215 * 2. MSG_WAITALL is set, and it is possible to do the entire 1220 * 2. MSG_WAITALL is set, and it is possible to do the entire
1216 * receive operation at once if we block (resid <= hiwat), or 1221 * receive operation at once if we block (resid <= hiwat), or
1217 * 3. MSG_DONTWAIT is not set. 1222 * 3. MSG_DONTWAIT is not set.
1218 * If MSG_WAITALL is set but resid is larger than the receive buffer, 1223 * If MSG_WAITALL is set but resid is larger than the receive buffer,
1219 * we have to do the receive in sections, and thus risk returning 1224 * we have to do the receive in sections, and thus risk returning
1220 * a short count if a timeout or signal occurs after we start. 1225 * a short count if a timeout or signal occurs after we start.
1221 */ 1226 */
1222 if (m == NULL || 1227 if (m == NULL ||
1223 ((flags & MSG_DONTWAIT) == 0 && 1228 ((flags & MSG_DONTWAIT) == 0 &&
1224 so->so_rcv.sb_cc < uio->uio_resid && 1229 so->so_rcv.sb_cc < uio->uio_resid &&
1225 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || 1230 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
1226 ((flags & MSG_WAITALL) && 1231 ((flags & MSG_WAITALL) &&
1227 uio->uio_resid <= so->so_rcv.sb_hiwat)) && 1232 uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
1228 m->m_nextpkt == NULL && !atomic)) { 1233 m->m_nextpkt == NULL && !atomic)) {
1229#ifdef DIAGNOSTIC 1234#ifdef DIAGNOSTIC
1230 if (m == NULL && so->so_rcv.sb_cc) 1235 if (m == NULL && so->so_rcv.sb_cc)
1231 panic("receive 1"); 1236 panic("receive 1");
1232#endif 1237#endif
1233 if (so->so_error) { 1238 if (so->so_error) {
1234 if (m != NULL) 1239 if (m != NULL)
1235 goto dontblock; 1240 goto dontblock;
1236 error = so->so_error; 1241 error = so->so_error;
1237 if ((flags & MSG_PEEK) == 0) 1242 if ((flags & MSG_PEEK) == 0)
1238 so->so_error = 0; 1243 so->so_error = 0;
1239 goto release; 1244 goto release;
1240 } 1245 }
1241 if (so->so_state & SS_CANTRCVMORE) { 1246 if (so->so_state & SS_CANTRCVMORE) {
1242 if (m != NULL) 1247 if (m != NULL)
1243 goto dontblock; 1248 goto dontblock;
1244 else 1249 else
1245 goto release; 1250 goto release;
1246 } 1251 }
1247 for (; m != NULL; m = m->m_next) 1252 for (; m != NULL; m = m->m_next)
1248 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { 1253 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
1249 m = so->so_rcv.sb_mb; 1254 m = so->so_rcv.sb_mb;
1250 goto dontblock; 1255 goto dontblock;
1251 } 1256 }
1252 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 1257 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
1253 (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 1258 (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
1254 error = ENOTCONN; 1259 error = ENOTCONN;
1255 goto release; 1260 goto release;
1256 } 1261 }
1257 if (uio->uio_resid == 0) 1262 if (uio->uio_resid == 0)
1258 goto release; 1263 goto release;
1259 if (so->so_nbio || (flags & MSG_DONTWAIT)) { 1264 if (so->so_nbio || (flags & MSG_DONTWAIT)) {
1260 error = EWOULDBLOCK; 1265 error = EWOULDBLOCK;
1261 goto release; 1266 goto release;
1262 } 1267 }
1263 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); 1268 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
1264 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); 1269 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
1265 sbunlock(&so->so_rcv); 1270 sbunlock(&so->so_rcv);
1266 error = sbwait(&so->so_rcv); 1271 error = sbwait(&so->so_rcv);
1267 if (error != 0) { 1272 if (error != 0) {
1268 sounlock(so); 1273 sounlock(so);
1269 splx(s); 1274 splx(s);
1270 return error; 1275 return error;
1271 } 1276 }
1272 goto restart; 1277 goto restart;
1273 } 1278 }
1274 dontblock: 1279 dontblock:
1275 /* 1280 /*
1276 * On entry here, m points to the first record of the socket buffer. 1281 * On entry here, m points to the first record of the socket buffer.
1277 * From this point onward, we maintain 'nextrecord' as a cache of the 1282 * From this point onward, we maintain 'nextrecord' as a cache of the
1278 * pointer to the next record in the socket buffer. We must keep the 1283 * pointer to the next record in the socket buffer. We must keep the
1279 * various socket buffer pointers and local stack versions of the 1284 * various socket buffer pointers and local stack versions of the
1280 * pointers in sync, pushing out modifications before dropping the 1285 * pointers in sync, pushing out modifications before dropping the
1281 * socket lock, and re-reading them when picking it up. 1286 * socket lock, and re-reading them when picking it up.
1282 * 1287 *
1283 * Otherwise, we will race with the network stack appending new data 1288 * Otherwise, we will race with the network stack appending new data
1284 * or records onto the socket buffer by using inconsistent/stale 1289 * or records onto the socket buffer by using inconsistent/stale
1285 * versions of the field, possibly resulting in socket buffer 1290 * versions of the field, possibly resulting in socket buffer
1286 * corruption. 1291 * corruption.
1287 * 1292 *
1288 * By holding the high-level sblock(), we prevent simultaneous 1293 * By holding the high-level sblock(), we prevent simultaneous
1289 * readers from pulling off the front of the socket buffer. 1294 * readers from pulling off the front of the socket buffer.
1290 */ 1295 */
1291 if (l != NULL) 1296 if (l != NULL)
1292 l->l_ru.ru_msgrcv++; 1297 l->l_ru.ru_msgrcv++;
1293 KASSERT(m == so->so_rcv.sb_mb); 1298 KASSERT(m == so->so_rcv.sb_mb);
1294 SBLASTRECORDCHK(&so->so_rcv, "soreceive 1"); 1299 SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");
1295 SBLASTMBUFCHK(&so->so_rcv, "soreceive 1"); 1300 SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");
1296 nextrecord = m->m_nextpkt; 1301 nextrecord = m->m_nextpkt;
1297 if (pr->pr_flags & PR_ADDR) { 1302 if (pr->pr_flags & PR_ADDR) {
1298#ifdef DIAGNOSTIC 1303#ifdef DIAGNOSTIC
1299 if (m->m_type != MT_SONAME) 1304 if (m->m_type != MT_SONAME)
1300 panic("receive 1a"); 1305 panic("receive 1a");
1301#endif 1306#endif
1302 orig_resid = 0; 1307 orig_resid = 0;
1303 if (flags & MSG_PEEK) { 1308 if (flags & MSG_PEEK) {
1304 if (paddr) 1309 if (paddr)
1305 *paddr = m_copy(m, 0, m->m_len); 1310 *paddr = m_copy(m, 0, m->m_len);
1306 m = m->m_next; 1311 m = m->m_next;
1307 } else { 1312 } else {
1308 sbfree(&so->so_rcv, m); 1313 sbfree(&so->so_rcv, m);
1309 mbuf_removed = 1; 1314 mbuf_removed = 1;
1310 if (paddr != NULL) { 1315 if (paddr != NULL) {
1311 *paddr = m; 1316 *paddr = m;
1312 so->so_rcv.sb_mb = m->m_next; 1317 so->so_rcv.sb_mb = m->m_next;
1313 m->m_next = NULL; 1318 m->m_next = NULL;
1314 m = so->so_rcv.sb_mb; 1319 m = so->so_rcv.sb_mb;
1315 } else { 1320 } else {
1316 MFREE(m, so->so_rcv.sb_mb); 1321 MFREE(m, so->so_rcv.sb_mb);
1317 m = so->so_rcv.sb_mb; 1322 m = so->so_rcv.sb_mb;
1318 } 1323 }
1319 sbsync(&so->so_rcv, nextrecord); 1324 sbsync(&so->so_rcv, nextrecord);
1320 } 1325 }
1321 } 1326 }
1322 1327
1323 /* 1328 /*
1324 * Process one or more MT_CONTROL mbufs present before any data mbufs 1329 * Process one or more MT_CONTROL mbufs present before any data mbufs
1325 * in the first mbuf chain on the socket buffer. If MSG_PEEK, we 1330 * in the first mbuf chain on the socket buffer. If MSG_PEEK, we
1326 * just copy the data; if !MSG_PEEK, we call into the protocol to 1331 * just copy the data; if !MSG_PEEK, we call into the protocol to
1327 * perform externalization (or freeing if controlp == NULL). 1332 * perform externalization (or freeing if controlp == NULL).
1328 */ 1333 */
1329 if (__predict_false(m != NULL && m->m_type == MT_CONTROL)) { 1334 if (__predict_false(m != NULL && m->m_type == MT_CONTROL)) {
1330 struct mbuf *cm = NULL, *cmn; 1335 struct mbuf *cm = NULL, *cmn;
1331 struct mbuf **cme = &cm; 1336 struct mbuf **cme = &cm;
1332 1337
1333 do { 1338 do {
1334 if (flags & MSG_PEEK) { 1339 if (flags & MSG_PEEK) {
1335 if (controlp != NULL) { 1340 if (controlp != NULL) {
1336 *controlp = m_copy(m, 0, m->m_len); 1341 *controlp = m_copy(m, 0, m->m_len);
1337 controlp = &(*controlp)->m_next; 1342 controlp = &(*controlp)->m_next;
1338 } 1343 }
1339 m = m->m_next; 1344 m = m->m_next;
1340 } else { 1345 } else {
1341 sbfree(&so->so_rcv, m); 1346 sbfree(&so->so_rcv, m);
1342 so->so_rcv.sb_mb = m->m_next; 1347 so->so_rcv.sb_mb = m->m_next;
1343 m->m_next = NULL; 1348 m->m_next = NULL;
1344 *cme = m; 1349 *cme = m;
1345 cme = &(*cme)->m_next; 1350 cme = &(*cme)->m_next;
1346 m = so->so_rcv.sb_mb; 1351 m = so->so_rcv.sb_mb;
1347 } 1352 }
1348 } while (m != NULL && m->m_type == MT_CONTROL); 1353 } while (m != NULL && m->m_type == MT_CONTROL);
1349 if ((flags & MSG_PEEK) == 0) 1354 if ((flags & MSG_PEEK) == 0)
1350 sbsync(&so->so_rcv, nextrecord); 1355 sbsync(&so->so_rcv, nextrecord);
1351 for (; cm != NULL; cm = cmn) { 1356 for (; cm != NULL; cm = cmn) {
1352 cmn = cm->m_next; 1357 cmn = cm->m_next;
1353 cm->m_next = NULL; 1358 cm->m_next = NULL;
1354 type = mtod(cm, struct cmsghdr *)->cmsg_type; 1359 type = mtod(cm, struct cmsghdr *)->cmsg_type;
1355 if (controlp != NULL) { 1360 if (controlp != NULL) {
1356 if (dom->dom_externalize != NULL && 1361 if (dom->dom_externalize != NULL &&
1357 type == SCM_RIGHTS) { 1362 type == SCM_RIGHTS) {
1358 sounlock(so); 1363 sounlock(so);
1359 splx(s); 1364 splx(s);
1360 error = (*dom->dom_externalize)(cm, l); 1365 error = (*dom->dom_externalize)(cm, l);
1361 s = splsoftnet(); 1366 s = splsoftnet();
1362 solock(so); 1367 solock(so);
1363 } 1368 }
1364 *controlp = cm; 1369 *controlp = cm;
1365 while (*controlp != NULL) 1370 while (*controlp != NULL)
1366 controlp = &(*controlp)->m_next; 1371 controlp = &(*controlp)->m_next;
1367 } else { 1372 } else {
1368 /* 1373 /*
1369 * Dispose of any SCM_RIGHTS message that went 1374 * Dispose of any SCM_RIGHTS message that went
1370 * through the read path rather than recv. 1375 * through the read path rather than recv.
1371 */ 1376 */
1372 if (dom->dom_dispose != NULL && 1377 if (dom->dom_dispose != NULL &&
1373 type == SCM_RIGHTS) { 1378 type == SCM_RIGHTS) {
1374 sounlock(so); 1379 sounlock(so);
1375 (*dom->dom_dispose)(cm); 1380 (*dom->dom_dispose)(cm);
1376 solock(so); 1381 solock(so);
1377 } 1382 }
1378 m_freem(cm); 1383 m_freem(cm);
1379 } 1384 }
1380 } 1385 }
1381 if (m != NULL) 1386 if (m != NULL)
1382 nextrecord = so->so_rcv.sb_mb->m_nextpkt; 1387 nextrecord = so->so_rcv.sb_mb->m_nextpkt;
1383 else 1388 else
1384 nextrecord = so->so_rcv.sb_mb; 1389 nextrecord = so->so_rcv.sb_mb;
1385 orig_resid = 0; 1390 orig_resid = 0;
1386 } 1391 }
1387 1392
1388 /* If m is non-NULL, we have some data to read. */ 1393 /* If m is non-NULL, we have some data to read. */
1389 if (__predict_true(m != NULL)) { 1394 if (__predict_true(m != NULL)) {
1390 type = m->m_type; 1395 type = m->m_type;
1391 if (type == MT_OOBDATA) 1396 if (type == MT_OOBDATA)
1392 flags |= MSG_OOB; 1397 flags |= MSG_OOB;
1393 } 1398 }
1394 SBLASTRECORDCHK(&so->so_rcv, "soreceive 2"); 1399 SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");
1395 SBLASTMBUFCHK(&so->so_rcv, "soreceive 2"); 1400 SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");
1396 1401
1397 moff = 0; 1402 moff = 0;
1398 offset = 0; 1403 offset = 0;
1399 while (m != NULL && uio->uio_resid > 0 && error == 0) { 1404 while (m != NULL && uio->uio_resid > 0 && error == 0) {
1400 if (m->m_type == MT_OOBDATA) { 1405 if (m->m_type == MT_OOBDATA) {
1401 if (type != MT_OOBDATA) 1406 if (type != MT_OOBDATA)
1402 break; 1407 break;
1403 } else if (type == MT_OOBDATA) 1408 } else if (type == MT_OOBDATA)
1404 break; 1409 break;
1405#ifdef DIAGNOSTIC 1410#ifdef DIAGNOSTIC
1406 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 1411 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
1407 panic("receive 3"); 1412 panic("receive 3");
1408#endif 1413#endif
1409 so->so_state &= ~SS_RCVATMARK; 1414 so->so_state &= ~SS_RCVATMARK;
1410 len = uio->uio_resid; 1415 len = uio->uio_resid;
1411 if (so->so_oobmark && len > so->so_oobmark - offset) 1416 if (so->so_oobmark && len > so->so_oobmark - offset)
1412 len = so->so_oobmark - offset; 1417 len = so->so_oobmark - offset;
1413 if (len > m->m_len - moff) 1418 if (len > m->m_len - moff)
1414 len = m->m_len - moff; 1419 len = m->m_len - moff;
1415 /* 1420 /*
1416 * If mp is set, just pass back the mbufs. 1421 * If mp is set, just pass back the mbufs.
1417 * Otherwise copy them out via the uio, then free. 1422 * Otherwise copy them out via the uio, then free.
1418 * Sockbuf must be consistent here (points to current mbuf, 1423 * Sockbuf must be consistent here (points to current mbuf,
1419 * it points to next record) when we drop priority; 1424 * it points to next record) when we drop priority;
1420 * we must note any additions to the sockbuf when we 1425 * we must note any additions to the sockbuf when we
1421 * block interrupts again. 1426 * block interrupts again.
1422 */ 1427 */
1423 if (mp == NULL) { 1428 if (mp == NULL) {
1424 SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove"); 1429 SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
1425 SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); 1430 SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
1426 sounlock(so); 1431 sounlock(so);
1427 splx(s); 1432 splx(s);
1428 error = uiomove(mtod(m, char *) + moff, (int)len, uio); 1433 error = uiomove(mtod(m, char *) + moff, (int)len, uio);
1429 s = splsoftnet(); 1434 s = splsoftnet();
1430 solock(so); 1435 solock(so);
1431 if (error != 0) { 1436 if (error != 0) {
1432 /* 1437 /*
1433 * If any part of the record has been removed 1438 * If any part of the record has been removed
1434 * (such as the MT_SONAME mbuf, which will 1439 * (such as the MT_SONAME mbuf, which will
1435 * happen when PR_ADDR, and thus also 1440 * happen when PR_ADDR, and thus also
1436 * PR_ATOMIC, is set), then drop the entire 1441 * PR_ATOMIC, is set), then drop the entire
1437 * record to maintain the atomicity of the 1442 * record to maintain the atomicity of the
1438 * receive operation. 1443 * receive operation.
1439 * 1444 *
1440 * This avoids a later panic("receive 1a") 1445 * This avoids a later panic("receive 1a")
1441 * when compiled with DIAGNOSTIC. 1446 * when compiled with DIAGNOSTIC.
1442 */ 1447 */
1443 if (m && mbuf_removed && atomic) 1448 if (m && mbuf_removed && atomic)
1444 (void) sbdroprecord(&so->so_rcv); 1449 (void) sbdroprecord(&so->so_rcv);
1445 1450
1446 goto release; 1451 goto release;
1447 } 1452 }
1448 } else 1453 } else
1449 uio->uio_resid -= len; 1454 uio->uio_resid -= len;
1450 if (len == m->m_len - moff) { 1455 if (len == m->m_len - moff) {
1451 if (m->m_flags & M_EOR) 1456 if (m->m_flags & M_EOR)
1452 flags |= MSG_EOR; 1457 flags |= MSG_EOR;
1453 if (flags & MSG_PEEK) { 1458 if (flags & MSG_PEEK) {
1454 m = m->m_next; 1459 m = m->m_next;
1455 moff = 0; 1460 moff = 0;
1456 } else { 1461 } else {
1457 nextrecord = m->m_nextpkt; 1462 nextrecord = m->m_nextpkt;
1458 sbfree(&so->so_rcv, m); 1463 sbfree(&so->so_rcv, m);
1459 if (mp) { 1464 if (mp) {
1460 *mp = m; 1465 *mp = m;
1461 mp = &m->m_next; 1466 mp = &m->m_next;
1462 so->so_rcv.sb_mb = m = m->m_next; 1467 so->so_rcv.sb_mb = m = m->m_next;
1463 *mp = NULL; 1468 *mp = NULL;
1464 } else { 1469 } else {
1465 MFREE(m, so->so_rcv.sb_mb); 1470 MFREE(m, so->so_rcv.sb_mb);
1466 m = so->so_rcv.sb_mb; 1471 m = so->so_rcv.sb_mb;
1467 } 1472 }
1468 /* 1473 /*
1469 * If m != NULL, we also know that 1474 * If m != NULL, we also know that
1470 * so->so_rcv.sb_mb != NULL. 1475 * so->so_rcv.sb_mb != NULL.
1471 */ 1476 */

cvs diff -r1.18 -r1.19 src/sys/secmodel/suser/secmodel_suser.c (switch to unified diff)

--- src/sys/secmodel/suser/secmodel_suser.c 2009/10/03 01:30:25 1.18
+++ src/sys/secmodel/suser/secmodel_suser.c 2009/10/03 01:41:39 1.19
@@ -1,1003 +1,1003 @@ @@ -1,1003 +1,1003 @@
1/* $NetBSD: secmodel_suser.c,v 1.18 2009/10/03 01:30:25 elad Exp $ */ 1/* $NetBSD: secmodel_suser.c,v 1.19 2009/10/03 01:41:39 elad Exp $ */
2/*- 2/*-
3 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> 3 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products 14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission. 15 * derived from this software without specific prior written permission.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * This file contains kauth(9) listeners needed to implement the traditional 30 * This file contains kauth(9) listeners needed to implement the traditional
31 * NetBSD superuser access restrictions. 31 * NetBSD superuser access restrictions.
32 * 32 *
33 * There are two main resources a request can be issued to: user-owned and 33 * There are two main resources a request can be issued to: user-owned and
34 * system owned. For the first, traditional Unix access checks are done, as 34 * system owned. For the first, traditional Unix access checks are done, as
35 * well as superuser checks. If needed, the request context is examined before 35 * well as superuser checks. If needed, the request context is examined before
36 * a decision is made. For the latter, usually only superuser checks are done 36 * a decision is made. For the latter, usually only superuser checks are done
37 * as normal users are not allowed to access system resources. 37 * as normal users are not allowed to access system resources.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.18 2009/10/03 01:30:25 elad Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.19 2009/10/03 01:41:39 elad Exp $");
42 42
43#include <sys/types.h> 43#include <sys/types.h>
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/kauth.h> 45#include <sys/kauth.h>
46 46
47#include <sys/mutex.h> 47#include <sys/mutex.h>
48#include <sys/mount.h> 48#include <sys/mount.h>
49#include <sys/socketvar.h> 49#include <sys/socketvar.h>
50#include <sys/sysctl.h> 50#include <sys/sysctl.h>
51#include <sys/vnode.h> 51#include <sys/vnode.h>
52#include <sys/proc.h> 52#include <sys/proc.h>
53#include <sys/uidinfo.h> 53#include <sys/uidinfo.h>
54#include <sys/module.h> 54#include <sys/module.h>
55 55
56#include <miscfs/procfs/procfs.h> 56#include <miscfs/procfs/procfs.h>
57 57
58#include <secmodel/suser/suser.h> 58#include <secmodel/suser/suser.h>
59 59
60MODULE(MODULE_CLASS_SECMODEL, suser, NULL); 60MODULE(MODULE_CLASS_SECMODEL, suser, NULL);
61 61
62static int secmodel_bsd44_curtain; 62static int secmodel_bsd44_curtain;
63/* static */ int dovfsusermount; 63/* static */ int dovfsusermount;
64 64
65static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep, 65static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep,
66 l_device, l_vnode; 66 l_device, l_vnode;
67 67
68static struct sysctllog *suser_sysctl_log; 68static struct sysctllog *suser_sysctl_log;
69 69
70void 70void
71sysctl_security_suser_setup(struct sysctllog **clog) 71sysctl_security_suser_setup(struct sysctllog **clog)
72{ 72{
73 const struct sysctlnode *rnode; 73 const struct sysctlnode *rnode;
74 74
75 sysctl_createv(clog, 0, NULL, &rnode, 75 sysctl_createv(clog, 0, NULL, &rnode,
76 CTLFLAG_PERMANENT, 76 CTLFLAG_PERMANENT,
77 CTLTYPE_NODE, "security", NULL, 77 CTLTYPE_NODE, "security", NULL,
78 NULL, 0, NULL, 0, 78 NULL, 0, NULL, 0,
79 CTL_SECURITY, CTL_EOL); 79 CTL_SECURITY, CTL_EOL);
80 80
81 sysctl_createv(clog, 0, &rnode, &rnode, 81 sysctl_createv(clog, 0, &rnode, &rnode,
82 CTLFLAG_PERMANENT, 82 CTLFLAG_PERMANENT,
83 CTLTYPE_NODE, "models", NULL, 83 CTLTYPE_NODE, "models", NULL,
84 NULL, 0, NULL, 0, 84 NULL, 0, NULL, 0,
85 CTL_CREATE, CTL_EOL); 85 CTL_CREATE, CTL_EOL);
86 86
87 sysctl_createv(clog, 0, &rnode, &rnode, 87 sysctl_createv(clog, 0, &rnode, &rnode,
88 CTLFLAG_PERMANENT, 88 CTLFLAG_PERMANENT,
89 CTLTYPE_NODE, "suser", NULL, 89 CTLTYPE_NODE, "suser", NULL,
90 NULL, 0, NULL, 0, 90 NULL, 0, NULL, 0,
91 CTL_CREATE, CTL_EOL); 91 CTL_CREATE, CTL_EOL);
92 92
93 sysctl_createv(clog, 0, &rnode, NULL, 93 sysctl_createv(clog, 0, &rnode, NULL,
94 CTLFLAG_PERMANENT, 94 CTLFLAG_PERMANENT,
95 CTLTYPE_STRING, "name", NULL, 95 CTLTYPE_STRING, "name", NULL,
96 NULL, 0, __UNCONST("Traditional NetBSD: Superuser"), 0, 96 NULL, 0, __UNCONST("Traditional NetBSD: Superuser"), 0,
97 CTL_CREATE, CTL_EOL); 97 CTL_CREATE, CTL_EOL);
98 98
99 sysctl_createv(clog, 0, &rnode, NULL, 99 sysctl_createv(clog, 0, &rnode, NULL,
100 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 100 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
101 CTLTYPE_INT, "curtain", 101 CTLTYPE_INT, "curtain",
102 SYSCTL_DESCR("Curtain information about objects to "\ 102 SYSCTL_DESCR("Curtain information about objects to "\
103 "users not owning them."), 103 "users not owning them."),
104 NULL, 0, &secmodel_bsd44_curtain, 0, 104 NULL, 0, &secmodel_bsd44_curtain, 0,
105 CTL_CREATE, CTL_EOL); 105 CTL_CREATE, CTL_EOL);
106 106
107 sysctl_createv(clog, 0, &rnode, NULL, 107 sysctl_createv(clog, 0, &rnode, NULL,
108 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 108 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
109 CTLTYPE_INT, "usermount", 109 CTLTYPE_INT, "usermount",
110 SYSCTL_DESCR("Whether unprivileged users may mount " 110 SYSCTL_DESCR("Whether unprivileged users may mount "
111 "filesystems"), 111 "filesystems"),
112 NULL, 0, &dovfsusermount, 0, 112 NULL, 0, &dovfsusermount, 0,
113 CTL_CREATE, CTL_EOL); 113 CTL_CREATE, CTL_EOL);
114 114
115 /* Compatibility: security.curtain */ 115 /* Compatibility: security.curtain */
116 sysctl_createv(clog, 0, NULL, &rnode, 116 sysctl_createv(clog, 0, NULL, &rnode,
117 CTLFLAG_PERMANENT, 117 CTLFLAG_PERMANENT,
118 CTLTYPE_NODE, "security", NULL, 118 CTLTYPE_NODE, "security", NULL,
119 NULL, 0, NULL, 0, 119 NULL, 0, NULL, 0,
120 CTL_SECURITY, CTL_EOL); 120 CTL_SECURITY, CTL_EOL);
121 121
122 sysctl_createv(clog, 0, &rnode, NULL, 122 sysctl_createv(clog, 0, &rnode, NULL,
123 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 123 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
124 CTLTYPE_INT, "curtain", 124 CTLTYPE_INT, "curtain",
125 SYSCTL_DESCR("Curtain information about objects to "\ 125 SYSCTL_DESCR("Curtain information about objects to "\
126 "users not owning them."), 126 "users not owning them."),
127 NULL, 0, &secmodel_bsd44_curtain, 0, 127 NULL, 0, &secmodel_bsd44_curtain, 0,
128 CTL_CREATE, CTL_EOL); 128 CTL_CREATE, CTL_EOL);
129 129
130 /* Compatibility: vfs.generic.usermount */ 130 /* Compatibility: vfs.generic.usermount */
131 sysctl_createv(clog, 0, NULL, NULL, 131 sysctl_createv(clog, 0, NULL, NULL,
132 CTLFLAG_PERMANENT, 132 CTLFLAG_PERMANENT,
133 CTLTYPE_NODE, "vfs", NULL, 133 CTLTYPE_NODE, "vfs", NULL,
134 NULL, 0, NULL, 0, 134 NULL, 0, NULL, 0,
135 CTL_VFS, CTL_EOL); 135 CTL_VFS, CTL_EOL);
136 136
137 sysctl_createv(clog, 0, NULL, NULL, 137 sysctl_createv(clog, 0, NULL, NULL,
138 CTLFLAG_PERMANENT, 138 CTLFLAG_PERMANENT,
139 CTLTYPE_NODE, "generic", 139 CTLTYPE_NODE, "generic",
140 SYSCTL_DESCR("Non-specific vfs related information"), 140 SYSCTL_DESCR("Non-specific vfs related information"),
141 NULL, 0, NULL, 0, 141 NULL, 0, NULL, 0,
142 CTL_VFS, VFS_GENERIC, CTL_EOL); 142 CTL_VFS, VFS_GENERIC, CTL_EOL);
143 143
144 sysctl_createv(clog, 0, NULL, NULL, 144 sysctl_createv(clog, 0, NULL, NULL,
145 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 145 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
146 CTLTYPE_INT, "usermount", 146 CTLTYPE_INT, "usermount",
147 SYSCTL_DESCR("Whether unprivileged users may mount " 147 SYSCTL_DESCR("Whether unprivileged users may mount "
148 "filesystems"), 148 "filesystems"),
149 NULL, 0, &dovfsusermount, 0, 149 NULL, 0, &dovfsusermount, 0,
150 CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL); 150 CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);
151} 151}
152 152
153void 153void
154secmodel_suser_init(void) 154secmodel_suser_init(void)
155{ 155{
156 secmodel_bsd44_curtain = 0; 156 secmodel_bsd44_curtain = 0;
157 dovfsusermount = 0; 157 dovfsusermount = 0;
158} 158}
159 159
160void 160void
161secmodel_suser_start(void) 161secmodel_suser_start(void)
162{ 162{
163 l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC, 163 l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC,
164 secmodel_suser_generic_cb, NULL); 164 secmodel_suser_generic_cb, NULL);
165 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 165 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
166 secmodel_suser_system_cb, NULL); 166 secmodel_suser_system_cb, NULL);
167 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 167 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
168 secmodel_suser_process_cb, NULL); 168 secmodel_suser_process_cb, NULL);
169 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 169 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
170 secmodel_suser_network_cb, NULL); 170 secmodel_suser_network_cb, NULL);
171 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 171 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
172 secmodel_suser_machdep_cb, NULL); 172 secmodel_suser_machdep_cb, NULL);
173 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 173 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
174 secmodel_suser_device_cb, NULL); 174 secmodel_suser_device_cb, NULL);
175 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE, 175 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
176 secmodel_suser_vnode_cb, NULL); 176 secmodel_suser_vnode_cb, NULL);
177} 177}
178 178
179void 179void
180secmodel_suser_stop(void) 180secmodel_suser_stop(void)
181{ 181{
182 kauth_unlisten_scope(l_generic); 182 kauth_unlisten_scope(l_generic);
183 kauth_unlisten_scope(l_system); 183 kauth_unlisten_scope(l_system);
184 kauth_unlisten_scope(l_process); 184 kauth_unlisten_scope(l_process);
185 kauth_unlisten_scope(l_network); 185 kauth_unlisten_scope(l_network);
186 kauth_unlisten_scope(l_machdep); 186 kauth_unlisten_scope(l_machdep);
187 kauth_unlisten_scope(l_device); 187 kauth_unlisten_scope(l_device);
188 kauth_unlisten_scope(l_vnode); 188 kauth_unlisten_scope(l_vnode);
189} 189}
190 190
191static int 191static int
192suser_modcmd(modcmd_t cmd, void *arg) 192suser_modcmd(modcmd_t cmd, void *arg)
193{ 193{
194 int error = 0; 194 int error = 0;
195 195
196 switch (cmd) { 196 switch (cmd) {
197 case MODULE_CMD_INIT: 197 case MODULE_CMD_INIT:
198 secmodel_suser_init(); 198 secmodel_suser_init();
199 secmodel_suser_start(); 199 secmodel_suser_start();
200 sysctl_security_suser_setup(&suser_sysctl_log); 200 sysctl_security_suser_setup(&suser_sysctl_log);
201 break; 201 break;
202 202
203 case MODULE_CMD_FINI: 203 case MODULE_CMD_FINI:
204 sysctl_teardown(&suser_sysctl_log); 204 sysctl_teardown(&suser_sysctl_log);
205 secmodel_suser_stop(); 205 secmodel_suser_stop();
206 break; 206 break;
207 207
208 case MODULE_CMD_AUTOUNLOAD: 208 case MODULE_CMD_AUTOUNLOAD:
209 error = EPERM; 209 error = EPERM;
210 break; 210 break;
211 211
212 default: 212 default:
213 error = ENOTTY; 213 error = ENOTTY;
214 break; 214 break;
215 } 215 }
216 216
217 return (error); 217 return (error);
218} 218}
219 219
220/* 220/*
221 * kauth(9) listener 221 * kauth(9) listener
222 * 222 *
223 * Security model: Traditional NetBSD 223 * Security model: Traditional NetBSD
224 * Scope: Generic 224 * Scope: Generic
225 * Responsibility: Superuser access 225 * Responsibility: Superuser access
226 */ 226 */
227int 227int
228secmodel_suser_generic_cb(kauth_cred_t cred, kauth_action_t action, 228secmodel_suser_generic_cb(kauth_cred_t cred, kauth_action_t action,
229 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 229 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
230{ 230{
231 bool isroot; 231 bool isroot;
232 int result; 232 int result;
233 233
234 isroot = (kauth_cred_geteuid(cred) == 0); 234 isroot = (kauth_cred_geteuid(cred) == 0);
235 result = KAUTH_RESULT_DEFER; 235 result = KAUTH_RESULT_DEFER;
236 236
237 switch (action) { 237 switch (action) {
238 case KAUTH_GENERIC_ISSUSER: 238 case KAUTH_GENERIC_ISSUSER:
239 if (isroot) 239 if (isroot)
240 result = KAUTH_RESULT_ALLOW; 240 result = KAUTH_RESULT_ALLOW;
241 break; 241 break;
242 242
243 case KAUTH_GENERIC_CANSEE:  243 case KAUTH_GENERIC_CANSEE:
244 if (!secmodel_bsd44_curtain) 244 if (!secmodel_bsd44_curtain)
245 result = KAUTH_RESULT_ALLOW; 245 result = KAUTH_RESULT_ALLOW;
246 else if (isroot || kauth_cred_uidmatch(cred, arg0)) 246 else if (isroot || kauth_cred_uidmatch(cred, arg0))
247 result = KAUTH_RESULT_ALLOW; 247 result = KAUTH_RESULT_ALLOW;
248 248
249 break; 249 break;
250 250
251 default: 251 default:
252 break; 252 break;
253 } 253 }
254 254
255 return (result); 255 return (result);
256} 256}
257 257
258/* 258/*
259 * kauth(9) listener 259 * kauth(9) listener
260 * 260 *
261 * Security model: Traditional NetBSD 261 * Security model: Traditional NetBSD
262 * Scope: System 262 * Scope: System
263 * Responsibility: Superuser access 263 * Responsibility: Superuser access
264 */ 264 */
265int 265int
266secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action, 266secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
267 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 267 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
268{ 268{
269 bool isroot; 269 bool isroot;
270 int result; 270 int result;
271 enum kauth_system_req req; 271 enum kauth_system_req req;
272 272
273 isroot = (kauth_cred_geteuid(cred) == 0); 273 isroot = (kauth_cred_geteuid(cred) == 0);
274 result = KAUTH_RESULT_DEFER; 274 result = KAUTH_RESULT_DEFER;
275 req = (enum kauth_system_req)arg0; 275 req = (enum kauth_system_req)arg0;
276 276
277 switch (action) { 277 switch (action) {
278 case KAUTH_SYSTEM_CPU: 278 case KAUTH_SYSTEM_CPU:
279 switch (req) { 279 switch (req) {
280 case KAUTH_REQ_SYSTEM_CPU_SETSTATE: 280 case KAUTH_REQ_SYSTEM_CPU_SETSTATE:
281 if (isroot) 281 if (isroot)
282 result = KAUTH_RESULT_ALLOW; 282 result = KAUTH_RESULT_ALLOW;
283 283
284 break; 284 break;
285 285
286 default: 286 default:
287 break; 287 break;
288 } 288 }
289 289
290 break; 290 break;
291 291
292 case KAUTH_SYSTEM_FS_QUOTA: 292 case KAUTH_SYSTEM_FS_QUOTA:
293 switch (req) { 293 switch (req) {
294 case KAUTH_REQ_SYSTEM_FS_QUOTA_GET: 294 case KAUTH_REQ_SYSTEM_FS_QUOTA_GET:
295 case KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF: 295 case KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF:
296 case KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE: 296 case KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE:
297 case KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT: 297 case KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT:
298 if (isroot) 298 if (isroot)
299 result = KAUTH_RESULT_ALLOW; 299 result = KAUTH_RESULT_ALLOW;
300 break; 300 break;
301 301
302 default: 302 default:
303 break; 303 break;
304 } 304 }
305 305
306 break; 306 break;
307 307
308 case KAUTH_SYSTEM_FS_RESERVEDSPACE: 308 case KAUTH_SYSTEM_FS_RESERVEDSPACE:
309 if (isroot) 309 if (isroot)
310 result = KAUTH_RESULT_ALLOW; 310 result = KAUTH_RESULT_ALLOW;
311 break; 311 break;
312 312
313 case KAUTH_SYSTEM_MOUNT: 313 case KAUTH_SYSTEM_MOUNT:
314 switch (req) { 314 switch (req) {
315 case KAUTH_REQ_SYSTEM_MOUNT_GET: 315 case KAUTH_REQ_SYSTEM_MOUNT_GET:
316 result = KAUTH_RESULT_ALLOW; 316 result = KAUTH_RESULT_ALLOW;
317 break; 317 break;
318 318
319 case KAUTH_REQ_SYSTEM_MOUNT_NEW: 319 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
320 if (isroot) 320 if (isroot)
321 result = KAUTH_RESULT_ALLOW; 321 result = KAUTH_RESULT_ALLOW;
322 else if (dovfsusermount) { 322 else if (dovfsusermount) {
323 struct vnode *vp = arg1; 323 struct vnode *vp = arg1;
324 u_long flags = (u_long)arg2; 324 u_long flags = (u_long)arg2;
325 325
326 if (!(flags & MNT_NODEV) || 326 if (!(flags & MNT_NODEV) ||
327 !(flags & MNT_NOSUID)) 327 !(flags & MNT_NOSUID))
328 break; 328 break;
329 329
330 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) && 330 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) &&
331 !(flags & MNT_NOEXEC)) 331 !(flags & MNT_NOEXEC))
332 break; 332 break;
333 333
334 result = KAUTH_RESULT_ALLOW; 334 result = KAUTH_RESULT_ALLOW;
335 } 335 }
336 336
337 break; 337 break;
338 338
339 case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT: 339 case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
340 if (isroot) 340 if (isroot)
341 result = KAUTH_RESULT_ALLOW; 341 result = KAUTH_RESULT_ALLOW;
342 else { 342 else {
343 struct mount *mp = arg1; 343 struct mount *mp = arg1;
344 344
345 if (mp->mnt_stat.f_owner == 345 if (mp->mnt_stat.f_owner ==
346 kauth_cred_geteuid(cred)) 346 kauth_cred_geteuid(cred))
347 result = KAUTH_RESULT_ALLOW; 347 result = KAUTH_RESULT_ALLOW;
348 } 348 }
349 349
350 break; 350 break;
351 351
352 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: 352 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
353 if (isroot) 353 if (isroot)
354 result = KAUTH_RESULT_ALLOW; 354 result = KAUTH_RESULT_ALLOW;
355 else if (dovfsusermount) { 355 else if (dovfsusermount) {
356 struct mount *mp = arg1; 356 struct mount *mp = arg1;
357 u_long flags = (u_long)arg2; 357 u_long flags = (u_long)arg2;
358 358
359 /* No exporting for non-root. */ 359 /* No exporting for non-root. */
360 if (flags & MNT_EXPORTED) 360 if (flags & MNT_EXPORTED)
361 break; 361 break;
362 362
363 if (!(flags & MNT_NODEV) || 363 if (!(flags & MNT_NODEV) ||
364 !(flags & MNT_NOSUID)) 364 !(flags & MNT_NOSUID))
365 break; 365 break;
366 366
367 /* 367 /*
368 * Only super-user, or user that did the mount, 368 * Only super-user, or user that did the mount,
369 * can update. 369 * can update.
370 */ 370 */
371 if (mp->mnt_stat.f_owner != 371 if (mp->mnt_stat.f_owner !=
372 kauth_cred_geteuid(cred)) 372 kauth_cred_geteuid(cred))
373 break; 373 break;
374 374
375 /* Retain 'noexec'. */ 375 /* Retain 'noexec'. */
376 if ((mp->mnt_flag & MNT_NOEXEC) && 376 if ((mp->mnt_flag & MNT_NOEXEC) &&
377 !(flags & MNT_NOEXEC)) 377 !(flags & MNT_NOEXEC))
378 break; 378 break;
379 379
380 result = KAUTH_RESULT_ALLOW; 380 result = KAUTH_RESULT_ALLOW;
381 } 381 }
382 382
383 break; 383 break;
384 384
385 default: 385 default:
386 break; 386 break;
387 } 387 }
388 388
389 break; 389 break;
390 390
391 case KAUTH_SYSTEM_PSET: 391 case KAUTH_SYSTEM_PSET:
392 switch (req) { 392 switch (req) {
393 case KAUTH_REQ_SYSTEM_PSET_ASSIGN: 393 case KAUTH_REQ_SYSTEM_PSET_ASSIGN:
394 case KAUTH_REQ_SYSTEM_PSET_BIND: 394 case KAUTH_REQ_SYSTEM_PSET_BIND:
395 case KAUTH_REQ_SYSTEM_PSET_CREATE: 395 case KAUTH_REQ_SYSTEM_PSET_CREATE:
396 case KAUTH_REQ_SYSTEM_PSET_DESTROY: 396 case KAUTH_REQ_SYSTEM_PSET_DESTROY:
397 if (isroot) 397 if (isroot)
398 result = KAUTH_RESULT_ALLOW; 398 result = KAUTH_RESULT_ALLOW;
399 399
400 break; 400 break;
401 401
402 default: 402 default:
403 break; 403 break;
404 } 404 }
405 405
406 break; 406 break;
407 407
408 case KAUTH_SYSTEM_TIME: 408 case KAUTH_SYSTEM_TIME:
409 switch (req) { 409 switch (req) {
410 case KAUTH_REQ_SYSTEM_TIME_ADJTIME: 410 case KAUTH_REQ_SYSTEM_TIME_ADJTIME:
411 case KAUTH_REQ_SYSTEM_TIME_NTPADJTIME: 411 case KAUTH_REQ_SYSTEM_TIME_NTPADJTIME:
412 case KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS: 412 case KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS:
413 if (isroot) 413 if (isroot)
414 result = KAUTH_RESULT_ALLOW; 414 result = KAUTH_RESULT_ALLOW;
415 break; 415 break;
416 416
417 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { 417 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
418 bool device_context = (bool)arg3; 418 bool device_context = (bool)arg3;
419 419
420 if (device_context || isroot) 420 if (device_context || isroot)
421 result = KAUTH_RESULT_ALLOW; 421 result = KAUTH_RESULT_ALLOW;
422 422
423 break; 423 break;
424 } 424 }
425 425
426 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: 426 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
427 if (isroot) 427 if (isroot)
428 result = KAUTH_RESULT_ALLOW; 428 result = KAUTH_RESULT_ALLOW;
429 break; 429 break;
430 430
431 default: 431 default:
432 break; 432 break;
433 } 433 }
434 break; 434 break;
435 435
436 case KAUTH_SYSTEM_SYSCTL: 436 case KAUTH_SYSTEM_SYSCTL:
437 switch (req) { 437 switch (req) {
438 case KAUTH_REQ_SYSTEM_SYSCTL_ADD: 438 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
439 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: 439 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
440 case KAUTH_REQ_SYSTEM_SYSCTL_DESC: 440 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
441 case KAUTH_REQ_SYSTEM_SYSCTL_MODIFY: 441 case KAUTH_REQ_SYSTEM_SYSCTL_MODIFY:
442 case KAUTH_REQ_SYSTEM_SYSCTL_PRVT: 442 case KAUTH_REQ_SYSTEM_SYSCTL_PRVT:
443 if (isroot) 443 if (isroot)
444 result = KAUTH_RESULT_ALLOW; 444 result = KAUTH_RESULT_ALLOW;
445 break; 445 break;
446 446
447 default: 447 default:
448 break; 448 break;
449 } 449 }
450 450
451 break; 451 break;
452 452
453 case KAUTH_SYSTEM_SWAPCTL: 453 case KAUTH_SYSTEM_SWAPCTL:
454 case KAUTH_SYSTEM_ACCOUNTING: 454 case KAUTH_SYSTEM_ACCOUNTING:
455 case KAUTH_SYSTEM_REBOOT: 455 case KAUTH_SYSTEM_REBOOT:
456 case KAUTH_SYSTEM_CHROOT: 456 case KAUTH_SYSTEM_CHROOT:
457 case KAUTH_SYSTEM_FILEHANDLE: 457 case KAUTH_SYSTEM_FILEHANDLE:
458 case KAUTH_SYSTEM_MKNOD: 458 case KAUTH_SYSTEM_MKNOD:
459 if (isroot) 459 if (isroot)
460 result = KAUTH_RESULT_ALLOW; 460 result = KAUTH_RESULT_ALLOW;
461 break; 461 break;
462 462
463 case KAUTH_SYSTEM_CHSYSFLAGS: 463 case KAUTH_SYSTEM_CHSYSFLAGS:
464 /* 464 /*
465 * Needs to be checked in conjunction with the immutable and 465 * Needs to be checked in conjunction with the immutable and
466 * append-only flags (usually). Should be handled differently. 466 * append-only flags (usually). Should be handled differently.
467 * Infects ufs, ext2fs, tmpfs, and rump. 467 * Infects ufs, ext2fs, tmpfs, and rump.
468 */ 468 */
469 if (isroot) 469 if (isroot)
470 result = KAUTH_RESULT_ALLOW; 470 result = KAUTH_RESULT_ALLOW;
471 471
472 break; 472 break;
473 473
474 case KAUTH_SYSTEM_SETIDCORE: 474 case KAUTH_SYSTEM_SETIDCORE:
475 if (isroot) 475 if (isroot)
476 result = KAUTH_RESULT_ALLOW; 476 result = KAUTH_RESULT_ALLOW;
477 477
478 break; 478 break;
479 479
480 case KAUTH_SYSTEM_MODULE: 480 case KAUTH_SYSTEM_MODULE:
481 if (isroot) 481 if (isroot)
482 result = KAUTH_RESULT_ALLOW; 482 result = KAUTH_RESULT_ALLOW;
483 483
484 break; 484 break;
485 485
486 default: 486 default:
487 break; 487 break;
488 } 488 }
489 489
490 return (result); 490 return (result);
491} 491}
492 492
493/* 493/*
494 * kauth(9) listener 494 * kauth(9) listener
495 * 495 *
496 * Security model: Traditional NetBSD 496 * Security model: Traditional NetBSD
497 * Scope: Process 497 * Scope: Process
498 * Responsibility: Superuser access 498 * Responsibility: Superuser access
499 */ 499 */
500int 500int
501secmodel_suser_process_cb(kauth_cred_t cred, kauth_action_t action, 501secmodel_suser_process_cb(kauth_cred_t cred, kauth_action_t action,
502 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 502 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
503{ 503{
504 struct proc *p; 504 struct proc *p;
505 bool isroot; 505 bool isroot;
506 int result; 506 int result;
507 507
508 isroot = (kauth_cred_geteuid(cred) == 0); 508 isroot = (kauth_cred_geteuid(cred) == 0);
509 result = KAUTH_RESULT_DEFER; 509 result = KAUTH_RESULT_DEFER;
510 p = arg0; 510 p = arg0;
511 511
512 switch (action) { 512 switch (action) {
513 case KAUTH_PROCESS_SIGNAL: 513 case KAUTH_PROCESS_SIGNAL:
514 if (isroot) 514 if (isroot)
515 result = KAUTH_RESULT_ALLOW; 515 result = KAUTH_RESULT_ALLOW;
516 516
517 break; 517 break;
518 518
519 case KAUTH_PROCESS_CANSEE: { 519 case KAUTH_PROCESS_CANSEE: {
520 unsigned long req; 520 unsigned long req;
521 521
522 req = (unsigned long)arg1; 522 req = (unsigned long)arg1;
523 523
524 switch (req) { 524 switch (req) {
525 case KAUTH_REQ_PROCESS_CANSEE_ARGS: 525 case KAUTH_REQ_PROCESS_CANSEE_ARGS:
526 case KAUTH_REQ_PROCESS_CANSEE_ENTRY: 526 case KAUTH_REQ_PROCESS_CANSEE_ENTRY:
527 case KAUTH_REQ_PROCESS_CANSEE_OPENFILES: 527 case KAUTH_REQ_PROCESS_CANSEE_OPENFILES:
528 if (!secmodel_bsd44_curtain) 528 if (!secmodel_bsd44_curtain)
529 result = KAUTH_RESULT_ALLOW; 529 result = KAUTH_RESULT_ALLOW;
530 else if (isroot || kauth_cred_uidmatch(cred, p->p_cred)) 530 else if (isroot || kauth_cred_uidmatch(cred, p->p_cred))
531 result = KAUTH_RESULT_ALLOW; 531 result = KAUTH_RESULT_ALLOW;
532 break; 532 break;
533 533
534 case KAUTH_REQ_PROCESS_CANSEE_ENV: 534 case KAUTH_REQ_PROCESS_CANSEE_ENV:
535 if (!isroot && 535 if (!isroot &&
536 (kauth_cred_getuid(cred) != 536 (kauth_cred_getuid(cred) !=
537 kauth_cred_getuid(p->p_cred) || 537 kauth_cred_getuid(p->p_cred) ||
538 kauth_cred_getuid(cred) != 538 kauth_cred_getuid(cred) !=
539 kauth_cred_getsvuid(p->p_cred))) 539 kauth_cred_getsvuid(p->p_cred)))
540 break; 540 break;
541 else 541 else
542 result = KAUTH_RESULT_ALLOW; 542 result = KAUTH_RESULT_ALLOW;
543 543
544 break; 544 break;
545 545
546 default: 546 default:
547 break; 547 break;
548 } 548 }
549 549
550 break; 550 break;
551 } 551 }
552 552
553 case KAUTH_PROCESS_KTRACE: 553 case KAUTH_PROCESS_KTRACE:
554 if (isroot) 554 if (isroot)
555 result = KAUTH_RESULT_ALLOW; 555 result = KAUTH_RESULT_ALLOW;
556 556
557 break; 557 break;
558 558
559 case KAUTH_PROCESS_PROCFS: 559 case KAUTH_PROCESS_PROCFS:
560 if (isroot) 560 if (isroot)
561 result = KAUTH_RESULT_ALLOW; 561 result = KAUTH_RESULT_ALLOW;
562 562
563 break; 563 break;
564 564
565 case KAUTH_PROCESS_PTRACE: 565 case KAUTH_PROCESS_PTRACE:
566 if (isroot) 566 if (isroot)
567 result = KAUTH_RESULT_ALLOW; 567 result = KAUTH_RESULT_ALLOW;
568 568
569 break; 569 break;
570 570
571 case KAUTH_PROCESS_CORENAME: 571 case KAUTH_PROCESS_CORENAME:
572 if (isroot || proc_uidmatch(cred, p->p_cred) == 0) 572 if (isroot || proc_uidmatch(cred, p->p_cred) == 0)
573 result = KAUTH_RESULT_ALLOW; 573 result = KAUTH_RESULT_ALLOW;
574 574
575 break; 575 break;
576 576
577 case KAUTH_PROCESS_FORK: { 577 case KAUTH_PROCESS_FORK: {
578 int lnprocs = (int)(unsigned long)arg2; 578 int lnprocs = (int)(unsigned long)arg2;
579 579
580 /* 580 /*
581 * Don't allow a nonprivileged user to use the last few 581 * Don't allow a nonprivileged user to use the last few
582 * processes. The variable lnprocs is the current number of 582 * processes. The variable lnprocs is the current number of
583 * processes, maxproc is the limit. 583 * processes, maxproc is the limit.
584 */ 584 */
585 if (__predict_false((lnprocs >= maxproc - 5) && !isroot)) 585 if (__predict_false((lnprocs >= maxproc - 5) && !isroot))
586 break; 586 break;
587 else 587 else
588 result = KAUTH_RESULT_ALLOW; 588 result = KAUTH_RESULT_ALLOW;
589 589
590 break; 590 break;
591 } 591 }
592 592
593 case KAUTH_PROCESS_KEVENT_FILTER: 593 case KAUTH_PROCESS_KEVENT_FILTER:
594 if (isroot) 594 if (isroot)
595 result = KAUTH_RESULT_ALLOW; 595 result = KAUTH_RESULT_ALLOW;
596 596
597 break; 597 break;
598 598
599 case KAUTH_PROCESS_NICE: 599 case KAUTH_PROCESS_NICE:
600 if (isroot) 600 if (isroot)
601 result = KAUTH_RESULT_ALLOW; 601 result = KAUTH_RESULT_ALLOW;
602 602
603 break; 603 break;
604 604
605 case KAUTH_PROCESS_RLIMIT: { 605 case KAUTH_PROCESS_RLIMIT: {
606 enum kauth_process_req req; 606 enum kauth_process_req req;
607 607
608 req = (enum kauth_process_req)(unsigned long)arg1; 608 req = (enum kauth_process_req)(unsigned long)arg1;
609 609
610 switch (req) { 610 switch (req) {
611 case KAUTH_REQ_PROCESS_RLIMIT_SET: 611 case KAUTH_REQ_PROCESS_RLIMIT_SET:
612 case KAUTH_REQ_PROCESS_RLIMIT_GET: 612 case KAUTH_REQ_PROCESS_RLIMIT_GET:
613 if (isroot) 613 if (isroot)
614 result = KAUTH_RESULT_ALLOW; 614 result = KAUTH_RESULT_ALLOW;
615 615
616 break; 616 break;
617 617
618 default: 618 default:
619 break; 619 break;
620 } 620 }
621 621
622 break; 622 break;
623 } 623 }
624 624
625 case KAUTH_PROCESS_SCHEDULER_GETPARAM: 625 case KAUTH_PROCESS_SCHEDULER_GETPARAM:
626 case KAUTH_PROCESS_SCHEDULER_SETPARAM: 626 case KAUTH_PROCESS_SCHEDULER_SETPARAM:
627 case KAUTH_PROCESS_SCHEDULER_SETAFFINITY: 627 case KAUTH_PROCESS_SCHEDULER_SETAFFINITY:
628 if (isroot) 628 if (isroot)
629 result = KAUTH_RESULT_ALLOW; 629 result = KAUTH_RESULT_ALLOW;
630 630
631 break; 631 break;
632 632
633 case KAUTH_PROCESS_SETID: 633 case KAUTH_PROCESS_SETID:
634 if (isroot) 634 if (isroot)
635 result = KAUTH_RESULT_ALLOW; 635 result = KAUTH_RESULT_ALLOW;
636 break; 636 break;
637 637
638 case KAUTH_PROCESS_STOPFLAG: 638 case KAUTH_PROCESS_STOPFLAG:
639 if (isroot || proc_uidmatch(cred, p->p_cred) == 0) { 639 if (isroot || proc_uidmatch(cred, p->p_cred) == 0) {
640 result = KAUTH_RESULT_ALLOW; 640 result = KAUTH_RESULT_ALLOW;
641 break; 641 break;
642 } 642 }
643 break; 643 break;
644 644
645 default: 645 default:
646 break; 646 break;
647 } 647 }
648 648
649 return (result); 649 return (result);
650} 650}
651 651
652/* 652/*
653 * kauth(9) listener 653 * kauth(9) listener
654 * 654 *
655 * Security model: Traditional NetBSD 655 * Security model: Traditional NetBSD
656 * Scope: Network 656 * Scope: Network
657 * Responsibility: Superuser access 657 * Responsibility: Superuser access
658 */ 658 */
659int 659int
660secmodel_suser_network_cb(kauth_cred_t cred, kauth_action_t action, 660secmodel_suser_network_cb(kauth_cred_t cred, kauth_action_t action,
661 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 661 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
662{ 662{
663 bool isroot; 663 bool isroot;
664 int result; 664 int result;
665 enum kauth_network_req req; 665 enum kauth_network_req req;
666 666
667 isroot = (kauth_cred_geteuid(cred) == 0); 667 isroot = (kauth_cred_geteuid(cred) == 0);
668 result = KAUTH_RESULT_DEFER; 668 result = KAUTH_RESULT_DEFER;
669 req = (enum kauth_network_req)arg0; 669 req = (enum kauth_network_req)arg0;
670 670
671 switch (action) { 671 switch (action) {
672 case KAUTH_NETWORK_ALTQ: 672 case KAUTH_NETWORK_ALTQ:
673 switch (req) { 673 switch (req) {
674 case KAUTH_REQ_NETWORK_ALTQ_AFMAP: 674 case KAUTH_REQ_NETWORK_ALTQ_AFMAP:
675 case KAUTH_REQ_NETWORK_ALTQ_BLUE: 675 case KAUTH_REQ_NETWORK_ALTQ_BLUE:
676 case KAUTH_REQ_NETWORK_ALTQ_CBQ: 676 case KAUTH_REQ_NETWORK_ALTQ_CBQ:
677 case KAUTH_REQ_NETWORK_ALTQ_CDNR: 677 case KAUTH_REQ_NETWORK_ALTQ_CDNR:
678 case KAUTH_REQ_NETWORK_ALTQ_CONF: 678 case KAUTH_REQ_NETWORK_ALTQ_CONF:
679 case KAUTH_REQ_NETWORK_ALTQ_FIFOQ: 679 case KAUTH_REQ_NETWORK_ALTQ_FIFOQ:
680 case KAUTH_REQ_NETWORK_ALTQ_HFSC: 680 case KAUTH_REQ_NETWORK_ALTQ_HFSC:
681 case KAUTH_REQ_NETWORK_ALTQ_JOBS: 681 case KAUTH_REQ_NETWORK_ALTQ_JOBS:
682 case KAUTH_REQ_NETWORK_ALTQ_PRIQ: 682 case KAUTH_REQ_NETWORK_ALTQ_PRIQ:
683 case KAUTH_REQ_NETWORK_ALTQ_RED: 683 case KAUTH_REQ_NETWORK_ALTQ_RED:
684 case KAUTH_REQ_NETWORK_ALTQ_RIO: 684 case KAUTH_REQ_NETWORK_ALTQ_RIO:
685 case KAUTH_REQ_NETWORK_ALTQ_WFQ: 685 case KAUTH_REQ_NETWORK_ALTQ_WFQ:
686 if (isroot) 686 if (isroot)
687 result = KAUTH_RESULT_ALLOW; 687 result = KAUTH_RESULT_ALLOW;
688 break; 688 break;
689 689
690 default: 690 default:
691 break; 691 break;
692 } 692 }
693 693
694 break; 694 break;
695 695
696 case KAUTH_NETWORK_BIND: 696 case KAUTH_NETWORK_BIND:
697 switch (req) { 697 switch (req) {
698 case KAUTH_REQ_NETWORK_BIND_PORT: 698 case KAUTH_REQ_NETWORK_BIND_PORT:
699 result = KAUTH_RESULT_ALLOW; 699 result = KAUTH_RESULT_ALLOW;
700 break; 700 break;
701 701
702 case KAUTH_REQ_NETWORK_BIND_PRIVPORT: 702 case KAUTH_REQ_NETWORK_BIND_PRIVPORT:
703 if (isroot) 703 if (isroot)
704 result = KAUTH_RESULT_ALLOW; 704 result = KAUTH_RESULT_ALLOW;
705 break; 705 break;
706 706
707 default: 707 default:
708 break; 708 break;
709 } 709 }
710 break; 710 break;
711 711
712 case KAUTH_NETWORK_FORWSRCRT: 712 case KAUTH_NETWORK_FORWSRCRT:
713 if (isroot) 713 if (isroot)
714 result = KAUTH_RESULT_ALLOW; 714 result = KAUTH_RESULT_ALLOW;
715 715
716 break; 716 break;
717 717
718 case KAUTH_NETWORK_INTERFACE: 718 case KAUTH_NETWORK_INTERFACE:
719 switch (req) { 719 switch (req) {
720 case KAUTH_REQ_NETWORK_INTERFACE_GET: 720 case KAUTH_REQ_NETWORK_INTERFACE_GET:
721 case KAUTH_REQ_NETWORK_INTERFACE_SET: 721 case KAUTH_REQ_NETWORK_INTERFACE_SET:
722 result = KAUTH_RESULT_ALLOW; 722 result = KAUTH_RESULT_ALLOW;
723 break; 723 break;
724 724
725 case KAUTH_REQ_NETWORK_INTERFACE_GETPRIV: 725 case KAUTH_REQ_NETWORK_INTERFACE_GETPRIV:
726 case KAUTH_REQ_NETWORK_INTERFACE_SETPRIV: 726 case KAUTH_REQ_NETWORK_INTERFACE_SETPRIV:
727 if (isroot) 727 if (isroot)
728 result = KAUTH_RESULT_ALLOW; 728 result = KAUTH_RESULT_ALLOW;
729 break; 729 break;
730 730
731 default: 731 default:
732 break; 732 break;
733 } 733 }
734 break; 734 break;
735 735
736 case KAUTH_NETWORK_INTERFACE_PPP: 736 case KAUTH_NETWORK_INTERFACE_PPP:
737 switch (req) { 737 switch (req) {
738 case KAUTH_REQ_NETWORK_INTERFACE_PPP_ADD: 738 case KAUTH_REQ_NETWORK_INTERFACE_PPP_ADD:
739 if (isroot) 739 if (isroot)
740 result = KAUTH_RESULT_ALLOW; 740 result = KAUTH_RESULT_ALLOW;
741 break; 741 break;
742 742
743 default: 743 default:
744 break; 744 break;
745 } 745 }
746 746
747 break; 747 break;
748 748
749 case KAUTH_NETWORK_INTERFACE_SLIP: 749 case KAUTH_NETWORK_INTERFACE_SLIP:
750 switch (req) { 750 switch (req) {
751 case KAUTH_REQ_NETWORK_INTERFACE_SLIP_ADD: 751 case KAUTH_REQ_NETWORK_INTERFACE_SLIP_ADD:
752 if (isroot) 752 if (isroot)
753 result = KAUTH_RESULT_ALLOW; 753 result = KAUTH_RESULT_ALLOW;
754 break; 754 break;
755 755
756 default: 756 default:
757 break; 757 break;
758 } 758 }
759 759
760 break; 760 break;
761 761
762 case KAUTH_NETWORK_INTERFACE_STRIP: 762 case KAUTH_NETWORK_INTERFACE_STRIP:
763 switch (req) { 763 switch (req) {
764 case KAUTH_REQ_NETWORK_INTERFACE_STRIP_ADD: 764 case KAUTH_REQ_NETWORK_INTERFACE_STRIP_ADD:
765 if (isroot) 765 if (isroot)
766 result = KAUTH_RESULT_ALLOW; 766 result = KAUTH_RESULT_ALLOW;
767 break; 767 break;
768 768
769 default: 769 default:
770 break; 770 break;
771 } 771 }
772 772
773 break; 773 break;
774 774
775 case KAUTH_NETWORK_INTERFACE_TUN: 775 case KAUTH_NETWORK_INTERFACE_TUN:
776 switch (req) { 776 switch (req) {
777 case KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD: 777 case KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD:
778 if (isroot) 778 if (isroot)
779 result = KAUTH_RESULT_ALLOW; 779 result = KAUTH_RESULT_ALLOW;
780 break; 780 break;
781 781
782 default: 782 default:
783 break; 783 break;
784 } 784 }
785 785
786 break; 786 break;
787 787
788 case KAUTH_NETWORK_NFS: 788 case KAUTH_NETWORK_NFS:
789 switch (req) { 789 switch (req) {
790 case KAUTH_REQ_NETWORK_NFS_EXPORT: 790 case KAUTH_REQ_NETWORK_NFS_EXPORT:
791 case KAUTH_REQ_NETWORK_NFS_SVC: 791 case KAUTH_REQ_NETWORK_NFS_SVC:
792 if (isroot) 792 if (isroot)
793 result = KAUTH_RESULT_ALLOW; 793 result = KAUTH_RESULT_ALLOW;
794 794
795 break; 795 break;
796 796
797 default: 797 default:
798 break; 798 break;
799 } 799 }
800 break; 800 break;
801 801
802 case KAUTH_NETWORK_ROUTE: 802 case KAUTH_NETWORK_ROUTE:
803 if (isroot) 803 if (isroot)
804 result = KAUTH_RESULT_ALLOW; 804 result = KAUTH_RESULT_ALLOW;
805 805
806 break; 806 break;
807 807
808 case KAUTH_NETWORK_SOCKET: 808 case KAUTH_NETWORK_SOCKET:
809 switch (req) { 809 switch (req) {
810 case KAUTH_REQ_NETWORK_SOCKET_DROP: 810 case KAUTH_REQ_NETWORK_SOCKET_DROP:
811 case KAUTH_REQ_NETWORK_SOCKET_OPEN: 811 case KAUTH_REQ_NETWORK_SOCKET_OPEN:
812 case KAUTH_REQ_NETWORK_SOCKET_RAWSOCK: 812 case KAUTH_REQ_NETWORK_SOCKET_RAWSOCK:
813 case KAUTH_REQ_NETWORK_SOCKET_SETPRIV: 813 case KAUTH_REQ_NETWORK_SOCKET_SETPRIV:
814 if (isroot) 814 if (isroot)
815 result = KAUTH_RESULT_ALLOW; 815 result = KAUTH_RESULT_ALLOW;
816 break; 816 break;
817 817
818 case KAUTH_REQ_NETWORK_SOCKET_CANSEE: 818 case KAUTH_REQ_NETWORK_SOCKET_CANSEE:
819 if (isroot) { 819 if (isroot) {
820 result = KAUTH_RESULT_ALLOW; 820 result = KAUTH_RESULT_ALLOW;
821 break; 821 break;
822 } 822 }
823 823
824 if (secmodel_bsd44_curtain) { 824 if (secmodel_bsd44_curtain) {
 825 struct socket *so;
825 uid_t so_uid; 826 uid_t so_uid;
826 827
827 so_uid = 828 so = (struct socket *)arg1;
828 ((struct socket *)arg1)->so_uidinfo->ui_uid; 829 so_uid = so->so_uidinfo->ui_uid;
829 if (kauth_cred_geteuid(cred) == so_uid) 830 if (kauth_cred_geteuid(cred) != so_uid)
830 result = KAUTH_RESULT_ALLOW; 831 result = KAUTH_RESULT_DENY;
831 } else 832 }
832 result = KAUTH_RESULT_ALLOW; 
833 833
834 break; 834 break;
835 835
836 default: 836 default:
837 break; 837 break;
838 } 838 }
839 839
840 break; 840 break;
841 841
842 842
843 default: 843 default:
844 break; 844 break;
845 } 845 }
846 846
847 return (result); 847 return (result);
848} 848}
849 849
850/* 850/*
851 * kauth(9) listener 851 * kauth(9) listener
852 * 852 *
853 * Security model: Traditional NetBSD 853 * Security model: Traditional NetBSD
854 * Scope: Machdep 854 * Scope: Machdep
855 * Responsibility: Superuser access 855 * Responsibility: Superuser access
856 */ 856 */
857int 857int
858secmodel_suser_machdep_cb(kauth_cred_t cred, kauth_action_t action, 858secmodel_suser_machdep_cb(kauth_cred_t cred, kauth_action_t action,
859 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 859 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
860{ 860{
861 bool isroot; 861 bool isroot;
862 int result; 862 int result;
863 863
864 isroot = (kauth_cred_geteuid(cred) == 0); 864 isroot = (kauth_cred_geteuid(cred) == 0);
865 result = KAUTH_RESULT_DEFER; 865 result = KAUTH_RESULT_DEFER;
866 866
867 switch (action) { 867 switch (action) {
868 case KAUTH_MACHDEP_IOPERM_GET: 868 case KAUTH_MACHDEP_IOPERM_GET:
869 case KAUTH_MACHDEP_LDT_GET: 869 case KAUTH_MACHDEP_LDT_GET:
870 case KAUTH_MACHDEP_LDT_SET: 870 case KAUTH_MACHDEP_LDT_SET:
871 case KAUTH_MACHDEP_MTRR_GET: 871 case KAUTH_MACHDEP_MTRR_GET:
872 result = KAUTH_RESULT_ALLOW; 872 result = KAUTH_RESULT_ALLOW;
873 break; 873 break;
874 874
875 case KAUTH_MACHDEP_CACHEFLUSH: 875 case KAUTH_MACHDEP_CACHEFLUSH:
876 case KAUTH_MACHDEP_IOPERM_SET: 876 case KAUTH_MACHDEP_IOPERM_SET:
877 case KAUTH_MACHDEP_IOPL: 877 case KAUTH_MACHDEP_IOPL:
878 case KAUTH_MACHDEP_MTRR_SET: 878 case KAUTH_MACHDEP_MTRR_SET:
879 case KAUTH_MACHDEP_NVRAM: 879 case KAUTH_MACHDEP_NVRAM:
880 case KAUTH_MACHDEP_UNMANAGEDMEM: 880 case KAUTH_MACHDEP_UNMANAGEDMEM:
881 if (isroot) 881 if (isroot)
882 result = KAUTH_RESULT_ALLOW; 882 result = KAUTH_RESULT_ALLOW;
883 break; 883 break;
884 884
885 default: 885 default:
886 break; 886 break;
887 } 887 }
888 888
889 return (result); 889 return (result);
890} 890}
891 891
892/* 892/*
893 * kauth(9) listener 893 * kauth(9) listener
894 * 894 *
895 * Security model: Traditional NetBSD 895 * Security model: Traditional NetBSD
896 * Scope: Device 896 * Scope: Device
897 * Responsibility: Superuser access 897 * Responsibility: Superuser access
898 */ 898 */
899int 899int
900secmodel_suser_device_cb(kauth_cred_t cred, kauth_action_t action, 900secmodel_suser_device_cb(kauth_cred_t cred, kauth_action_t action,
901 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 901 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
902{ 902{
903 bool isroot; 903 bool isroot;
904 int result; 904 int result;
905 905
906 isroot = (kauth_cred_geteuid(cred) == 0); 906 isroot = (kauth_cred_geteuid(cred) == 0);
907 result = KAUTH_RESULT_DEFER; 907 result = KAUTH_RESULT_DEFER;
908 908
909 switch (action) { 909 switch (action) {
910 case KAUTH_DEVICE_BLUETOOTH_SETPRIV: 910 case KAUTH_DEVICE_BLUETOOTH_SETPRIV:
911 case KAUTH_DEVICE_BLUETOOTH_SEND: 911 case KAUTH_DEVICE_BLUETOOTH_SEND:
912 case KAUTH_DEVICE_BLUETOOTH_RECV: 912 case KAUTH_DEVICE_BLUETOOTH_RECV:
913 if (isroot) 913 if (isroot)
914 result = KAUTH_RESULT_ALLOW; 914 result = KAUTH_RESULT_ALLOW;
915 break; 915 break;
916 916
917 case KAUTH_DEVICE_BLUETOOTH_BCSP: 917 case KAUTH_DEVICE_BLUETOOTH_BCSP:
918 case KAUTH_DEVICE_BLUETOOTH_BTUART: { 918 case KAUTH_DEVICE_BLUETOOTH_BTUART: {
919 enum kauth_device_req req; 919 enum kauth_device_req req;
920 920
921 req = (enum kauth_device_req)arg0; 921 req = (enum kauth_device_req)arg0;
922 switch (req) { 922 switch (req) {
923 case KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD: 923 case KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD:
924 case KAUTH_REQ_DEVICE_BLUETOOTH_BTUART_ADD: 924 case KAUTH_REQ_DEVICE_BLUETOOTH_BTUART_ADD:
925 if (isroot) 925 if (isroot)
926 result = KAUTH_RESULT_ALLOW; 926 result = KAUTH_RESULT_ALLOW;
927 break; 927 break;
928 928
929 default: 929 default:
930 break; 930 break;
931 } 931 }
932 932
933 break; 933 break;
934 } 934 }
935 935
936 case KAUTH_DEVICE_RAWIO_SPEC: 936 case KAUTH_DEVICE_RAWIO_SPEC:
937 case KAUTH_DEVICE_RAWIO_PASSTHRU: 937 case KAUTH_DEVICE_RAWIO_PASSTHRU:
938 /* 938 /*
939 * Decision is root-agnostic. 939 * Decision is root-agnostic.
940 * 940 *
941 * Both requests can be issued on devices subject to their 941 * Both requests can be issued on devices subject to their
942 * permission bits. 942 * permission bits.
943 */ 943 */
944 result = KAUTH_RESULT_ALLOW; 944 result = KAUTH_RESULT_ALLOW;
945 break; 945 break;
946 946
947 case KAUTH_DEVICE_TTY_OPEN: 947 case KAUTH_DEVICE_TTY_OPEN:
948 if (isroot) 948 if (isroot)
949 result = KAUTH_RESULT_ALLOW; 949 result = KAUTH_RESULT_ALLOW;
950 950
951 break; 951 break;
952 952
953 case KAUTH_DEVICE_TTY_PRIVSET: 953 case KAUTH_DEVICE_TTY_PRIVSET:
954 if (isroot) 954 if (isroot)
955 result = KAUTH_RESULT_ALLOW; 955 result = KAUTH_RESULT_ALLOW;
956 956
957 break; 957 break;
958 958
959 case KAUTH_DEVICE_TTY_STI: 959 case KAUTH_DEVICE_TTY_STI:
960 if (isroot) 960 if (isroot)
961 result = KAUTH_RESULT_ALLOW; 961 result = KAUTH_RESULT_ALLOW;
962 962
963 break; 963 break;
964 964
965 case KAUTH_DEVICE_RND_ADDDATA: 965 case KAUTH_DEVICE_RND_ADDDATA:
966 case KAUTH_DEVICE_RND_GETPRIV: 966 case KAUTH_DEVICE_RND_GETPRIV:
967 case KAUTH_DEVICE_RND_SETPRIV: 967 case KAUTH_DEVICE_RND_SETPRIV:
968 if (isroot) 968 if (isroot)
969 result = KAUTH_RESULT_ALLOW; 969 result = KAUTH_RESULT_ALLOW;
970 break; 970 break;
971 971
972 case KAUTH_DEVICE_GPIO_PINSET: 972 case KAUTH_DEVICE_GPIO_PINSET:
973 /* 973 /*
974 * root can access gpio pins, secmodel_securlevel can veto 974 * root can access gpio pins, secmodel_securlevel can veto
975 * this decision. 975 * this decision.
976 */ 976 */
977 if (isroot) 977 if (isroot)
978 result = KAUTH_RESULT_ALLOW; 978 result = KAUTH_RESULT_ALLOW;
979 break; 979 break;
980 980
981 default: 981 default:
982 break; 982 break;
983 } 983 }
984 984
985 return (result); 985 return (result);
986} 986}
987 987
988int 988int
989secmodel_suser_vnode_cb(kauth_cred_t cred, kauth_action_t action, 989secmodel_suser_vnode_cb(kauth_cred_t cred, kauth_action_t action,
990 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 990 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
991{ 991{
992 bool isroot; 992 bool isroot;
993 int result; 993 int result;
994 994
995 isroot = (kauth_cred_geteuid(cred) == 0); 995 isroot = (kauth_cred_geteuid(cred) == 0);
996 result = KAUTH_RESULT_DEFER; 996 result = KAUTH_RESULT_DEFER;
997 997
998 if (isroot) 998 if (isroot)
999 result = KAUTH_RESULT_ALLOW; 999 result = KAUTH_RESULT_ALLOW;
1000 1000
1001 return (result); 1001 return (result);
1002} 1002}
1003 1003