1 /*
2 * Copyright (c) 1999-2022 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * Kernel Control domain - allows control connections to
31 * and to read/write data.
32 *
33 * Vincent Lubet, 040506
34 * Christophe Allie, 010928
35 * Justin C. Walker, 990319
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/syslog.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/protosw.h>
45 #include <sys/domain.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/sys_domain.h>
49 #include <sys/kern_event.h>
50 #include <sys/kern_control.h>
51 #include <sys/kauth.h>
52 #include <sys/sysctl.h>
53 #include <sys/proc_info.h>
54 #include <net/if_var.h>
55
56 #include <mach/vm_types.h>
57
58 #include <kern/thread.h>
59
60 struct kctl {
61 TAILQ_ENTRY(kctl) next; /* controller chain */
62 kern_ctl_ref kctlref;
63
64 /* controller information provided when registering */
65 char name[MAX_KCTL_NAME]; /* unique identifier */
66 u_int32_t id;
67 u_int32_t reg_unit;
68
69 /* misc communication information */
70 u_int32_t flags; /* support flags */
71 u_int32_t recvbufsize; /* request more than the default buffer size */
72 u_int32_t sendbufsize; /* request more than the default buffer size */
73
74 /* Dispatch functions */
75 ctl_setup_func setup; /* Setup contact */
76 ctl_bind_func bind; /* Prepare contact */
77 ctl_connect_func connect; /* Make contact */
78 ctl_disconnect_func disconnect; /* Break contact */
79 ctl_send_func send; /* Send data to nke */
80 ctl_send_list_func send_list; /* Send list of packets */
81 ctl_setopt_func setopt; /* set kctl configuration */
82 ctl_getopt_func getopt; /* get kctl configuration */
83 ctl_rcvd_func rcvd; /* Notify nke when client reads data */
84
85 TAILQ_HEAD(, ctl_cb) kcb_head;
86 u_int32_t lastunit;
87 };
88
89 #if DEVELOPMENT || DEBUG
90 enum ctl_status {
91 KCTL_DISCONNECTED = 0,
92 KCTL_CONNECTING = 1,
93 KCTL_CONNECTED = 2
94 };
95 #endif /* DEVELOPMENT || DEBUG */
96
97 struct ctl_cb {
98 TAILQ_ENTRY(ctl_cb) next; /* controller chain */
99 lck_mtx_t mtx;
100 struct socket *so; /* controlling socket */
101 struct kctl *kctl; /* back pointer to controller */
102 void *userdata;
103 struct sockaddr_ctl sac;
104 uint32_t usecount;
105 uint32_t kcb_usecount;
106 uint32_t require_clearing_count;
107 #if DEVELOPMENT || DEBUG
108 enum ctl_status status;
109 #endif /* DEVELOPMENT || DEBUG */
110 };
111
112 #ifndef ROUNDUP64
113 #define ROUNDUP64(x) P2ROUNDUP((x), sizeof (u_int64_t))
114 #endif
115
116 #ifndef ADVANCE64
117 #define ADVANCE64(p, n) (void*)((char *)(p) + ROUNDUP64(n))
118 #endif
119
120 /*
121 * Definitions and vars for we support
122 */
123
124 #define CTL_SENDSIZE (2 * 1024) /* default buffer size */
125 #define CTL_RECVSIZE (8 * 1024) /* default buffer size */
126
127 /*
128 * Definitions and vars for we support
129 */
130
131 const u_int32_t ctl_maxunit = 65536;
132 static LCK_ATTR_DECLARE(ctl_lck_attr, 0, 0);
133 static LCK_GRP_DECLARE(ctl_lck_grp, "Kernel Control Protocol");
134 static LCK_MTX_DECLARE_ATTR(ctl_mtx, &ctl_lck_grp, &ctl_lck_attr);
135
136 /* all the controllers are chained */
137 TAILQ_HEAD(kctl_list, kctl) ctl_head = TAILQ_HEAD_INITIALIZER(ctl_head);
138
139 static int ctl_attach(struct socket *, int, struct proc *);
140 static int ctl_detach(struct socket *);
141 static int ctl_sofreelastref(struct socket *so);
142 static int ctl_bind(struct socket *, struct sockaddr *, struct proc *);
143 static int ctl_connect(struct socket *, struct sockaddr *, struct proc *);
144 static int ctl_disconnect(struct socket *);
145 static int ctl_ioctl(struct socket *so, u_long cmd, caddr_t data,
146 struct ifnet *ifp, struct proc *p);
147 static int ctl_send(struct socket *, int, struct mbuf *,
148 struct sockaddr *, struct mbuf *, struct proc *);
149 static int ctl_send_list(struct socket *, struct mbuf *, u_int *, int);
150 static int ctl_ctloutput(struct socket *, struct sockopt *);
151 static int ctl_peeraddr(struct socket *so, struct sockaddr **nam);
152 static int ctl_usr_rcvd(struct socket *so, int flags);
153
154 static struct kctl *ctl_find_by_name(const char *);
155 static struct kctl *ctl_find_by_id_unit(u_int32_t id, u_int32_t unit);
156
157 static struct socket *kcb_find_socket(kern_ctl_ref kctlref, u_int32_t unit,
158 u_int32_t *);
159 static struct ctl_cb *kcb_find(struct kctl *, u_int32_t unit);
160 static void ctl_post_msg(u_int32_t event_code, u_int32_t id);
161
162 static int ctl_lock(struct socket *, int, void *);
163 static int ctl_unlock(struct socket *, int, void *);
164 static lck_mtx_t * ctl_getlock(struct socket *, int);
165
166 static struct pr_usrreqs ctl_usrreqs = {
167 .pru_attach = ctl_attach,
168 .pru_bind = ctl_bind,
169 .pru_connect = ctl_connect,
170 .pru_control = ctl_ioctl,
171 .pru_detach = ctl_detach,
172 .pru_disconnect = ctl_disconnect,
173 .pru_peeraddr = ctl_peeraddr,
174 .pru_rcvd = ctl_usr_rcvd,
175 .pru_send = ctl_send,
176 .pru_send_list = ctl_send_list,
177 .pru_sosend = sosend,
178 .pru_sosend_list = sosend_list,
179 .pru_soreceive = soreceive,
180 };
181
182 static struct protosw kctlsw[] = {
183 {
184 .pr_type = SOCK_DGRAM,
185 .pr_protocol = SYSPROTO_CONTROL,
186 .pr_flags = PR_ATOMIC | PR_CONNREQUIRED | PR_PCBLOCK | PR_WANTRCVD,
187 .pr_ctloutput = ctl_ctloutput,
188 .pr_usrreqs = &ctl_usrreqs,
189 .pr_lock = ctl_lock,
190 .pr_unlock = ctl_unlock,
191 .pr_getlock = ctl_getlock,
192 },
193 {
194 .pr_type = SOCK_STREAM,
195 .pr_protocol = SYSPROTO_CONTROL,
196 .pr_flags = PR_CONNREQUIRED | PR_PCBLOCK | PR_WANTRCVD,
197 .pr_ctloutput = ctl_ctloutput,
198 .pr_usrreqs = &ctl_usrreqs,
199 .pr_lock = ctl_lock,
200 .pr_unlock = ctl_unlock,
201 .pr_getlock = ctl_getlock,
202 }
203 };
204
205 __private_extern__ int kctl_reg_list SYSCTL_HANDLER_ARGS;
206 __private_extern__ int kctl_pcblist SYSCTL_HANDLER_ARGS;
207 __private_extern__ int kctl_getstat SYSCTL_HANDLER_ARGS;
208
209
210 SYSCTL_NODE(_net_systm, OID_AUTO, kctl,
211 CTLFLAG_RW | CTLFLAG_LOCKED, 0, "Kernel control family");
212
213 struct kctlstat kctlstat;
214 SYSCTL_PROC(_net_systm_kctl, OID_AUTO, stats,
215 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
216 kctl_getstat, "S,kctlstat", "");
217
218 SYSCTL_PROC(_net_systm_kctl, OID_AUTO, reg_list,
219 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
220 kctl_reg_list, "S,xkctl_reg", "");
221
222 SYSCTL_PROC(_net_systm_kctl, OID_AUTO, pcblist,
223 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
224 kctl_pcblist, "S,xkctlpcb", "");
225
226 u_int32_t ctl_autorcvbuf_max = 256 * 1024;
227 SYSCTL_INT(_net_systm_kctl, OID_AUTO, autorcvbufmax,
228 CTLFLAG_RW | CTLFLAG_LOCKED, &ctl_autorcvbuf_max, 0, "");
229
230 u_int32_t ctl_autorcvbuf_high = 0;
231 SYSCTL_INT(_net_systm_kctl, OID_AUTO, autorcvbufhigh,
232 CTLFLAG_RD | CTLFLAG_LOCKED, &ctl_autorcvbuf_high, 0, "");
233
234 u_int32_t ctl_debug = 0;
235 SYSCTL_INT(_net_systm_kctl, OID_AUTO, debug,
236 CTLFLAG_RW | CTLFLAG_LOCKED, &ctl_debug, 0, "");
237
238 #if DEVELOPMENT || DEBUG
239 u_int32_t ctl_panic_debug = 0;
240 SYSCTL_INT(_net_systm_kctl, OID_AUTO, panicdebug,
241 CTLFLAG_RW | CTLFLAG_LOCKED, &ctl_panic_debug, 0, "");
242 #endif /* DEVELOPMENT || DEBUG */
243
244 #define KCTL_TBL_INC 16
245
246 static uintptr_t kctl_tbl_size = 0;
247 static u_int32_t kctl_tbl_growing = 0;
248 static u_int32_t kctl_tbl_growing_waiting = 0;
249 static uintptr_t kctl_tbl_count = 0;
250 static struct kctl **kctl_table = NULL;
251 static uintptr_t kctl_ref_gencnt = 0;
252
253 static void kctl_tbl_grow(void);
254 static kern_ctl_ref kctl_make_ref(struct kctl *kctl);
255 static void kctl_delete_ref(kern_ctl_ref);
256 static struct kctl *kctl_from_ref(kern_ctl_ref);
257
258 /*
259 * Install the protosw's for the Kernel Control manager.
260 */
261 __private_extern__ void
kern_control_init(struct domain * dp)262 kern_control_init(struct domain *dp)
263 {
264 struct protosw *pr;
265 int i;
266 int kctl_proto_count = (sizeof(kctlsw) / sizeof(struct protosw));
267
268 VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
269 VERIFY(dp == systemdomain);
270
271 for (i = 0, pr = &kctlsw[0]; i < kctl_proto_count; i++, pr++) {
272 net_add_proto(pr, dp, 1);
273 }
274 }
275
276 static void
kcb_delete(struct ctl_cb * kcb)277 kcb_delete(struct ctl_cb *kcb)
278 {
279 if (kcb != 0) {
280 lck_mtx_destroy(&kcb->mtx, &ctl_lck_grp);
281 kfree_type(struct ctl_cb, kcb);
282 }
283 }
284
285 /*
286 * Kernel Controller user-request functions
287 * attach function must exist and succeed
288 * detach not necessary
289 * we need a pcb for the per socket mutex
290 */
291 static int
ctl_attach(struct socket * so,int proto,struct proc * p)292 ctl_attach(struct socket *so, int proto, struct proc *p)
293 {
294 #pragma unused(proto, p)
295 struct ctl_cb *kcb = 0;
296
297 kcb = kalloc_type(struct ctl_cb, Z_WAITOK | Z_ZERO | Z_NOFAIL);
298
299 lck_mtx_init(&kcb->mtx, &ctl_lck_grp, &ctl_lck_attr);
300 kcb->so = so;
301 so->so_pcb = (caddr_t)kcb;
302
303 /*
304 * For datagram, use character count for sbspace as its value
305 * may be use for packetization and we do not want to
306 * drop packets based on the sbspace hint that was just provided
307 */
308 if (so->so_proto->pr_type == SOCK_DGRAM) {
309 so->so_rcv.sb_flags |= SB_KCTL;
310 so->so_snd.sb_flags |= SB_KCTL;
311 }
312 return 0;
313 }
314
315 static int
ctl_sofreelastref(struct socket * so)316 ctl_sofreelastref(struct socket *so)
317 {
318 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
319
320 so->so_pcb = 0;
321
322 if (kcb != 0) {
323 struct kctl *kctl;
324 if ((kctl = kcb->kctl) != 0) {
325 lck_mtx_lock(&ctl_mtx);
326 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
327 kctlstat.kcs_pcbcount--;
328 kctlstat.kcs_gencnt++;
329 lck_mtx_unlock(&ctl_mtx);
330 }
331 kcb_delete(kcb);
332 }
333 sofreelastref(so, 1);
334 return 0;
335 }
336
337 /*
338 * Use this function and ctl_kcb_require_clearing to serialize
339 * critical calls into the kctl subsystem
340 */
341 static void
ctl_kcb_increment_use_count(struct ctl_cb * kcb,lck_mtx_t * mutex_held)342 ctl_kcb_increment_use_count(struct ctl_cb *kcb, lck_mtx_t *mutex_held)
343 {
344 LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
345 while (kcb->require_clearing_count > 0) {
346 msleep(&kcb->require_clearing_count, mutex_held, PSOCK | PCATCH, "kcb_require_clearing", NULL);
347 }
348 kcb->kcb_usecount++;
349 }
350
351 static void
ctl_kcb_require_clearing(struct ctl_cb * kcb,lck_mtx_t * mutex_held)352 ctl_kcb_require_clearing(struct ctl_cb *kcb, lck_mtx_t *mutex_held)
353 {
354 assert(kcb->kcb_usecount != 0);
355 kcb->require_clearing_count++;
356 kcb->kcb_usecount--;
357 while (kcb->kcb_usecount > 0) { // we need to wait until no one else is running
358 msleep(&kcb->kcb_usecount, mutex_held, PSOCK | PCATCH, "kcb_usecount", NULL);
359 }
360 kcb->kcb_usecount++;
361 }
362
363 static void
ctl_kcb_done_clearing(struct ctl_cb * kcb)364 ctl_kcb_done_clearing(struct ctl_cb *kcb)
365 {
366 assert(kcb->require_clearing_count != 0);
367 kcb->require_clearing_count--;
368 wakeup((caddr_t)&kcb->require_clearing_count);
369 }
370
371 static void
ctl_kcb_decrement_use_count(struct ctl_cb * kcb)372 ctl_kcb_decrement_use_count(struct ctl_cb *kcb)
373 {
374 assert(kcb->kcb_usecount != 0);
375 kcb->kcb_usecount--;
376 if (kcb->require_clearing_count != 0) {
377 wakeup((caddr_t)&kcb->kcb_usecount);
378 }
379 }
380
381 static int
ctl_detach(struct socket * so)382 ctl_detach(struct socket *so)
383 {
384 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
385
386 if (kcb == 0) {
387 return 0;
388 }
389
390 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
391 ctl_kcb_increment_use_count(kcb, mtx_held);
392 ctl_kcb_require_clearing(kcb, mtx_held);
393
394 if (kcb->kctl != NULL && kcb->kctl->bind != NULL &&
395 kcb->userdata != NULL && !(so->so_state & SS_ISCONNECTED)) {
396 // The unit was bound, but not connected
397 // Invoke the disconnected call to cleanup
398 if (kcb->kctl->disconnect != NULL) {
399 socket_unlock(so, 0);
400 (*kcb->kctl->disconnect)(kcb->kctl->kctlref,
401 kcb->sac.sc_unit, kcb->userdata);
402 socket_lock(so, 0);
403 }
404 }
405
406 soisdisconnected(so);
407 #if DEVELOPMENT || DEBUG
408 kcb->status = KCTL_DISCONNECTED;
409 #endif /* DEVELOPMENT || DEBUG */
410 so->so_flags |= SOF_PCBCLEARING;
411 ctl_kcb_done_clearing(kcb);
412 ctl_kcb_decrement_use_count(kcb);
413 return 0;
414 }
415
416 static int
ctl_setup_kctl(struct socket * so,struct sockaddr * nam,struct proc * p)417 ctl_setup_kctl(struct socket *so, struct sockaddr *nam, struct proc *p)
418 {
419 struct kctl *kctl = NULL;
420 int error = 0;
421 struct sockaddr_ctl sa;
422 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
423 struct ctl_cb *kcb_next = NULL;
424 u_int32_t recvbufsize, sendbufsize;
425
426 if (kcb == 0) {
427 panic("ctl_setup_kctl so_pcb null");
428 }
429
430 if (kcb->kctl != NULL) {
431 // Already set up, skip
432 return 0;
433 }
434
435 if (nam->sa_len != sizeof(struct sockaddr_ctl)) {
436 return EINVAL;
437 }
438
439 bcopy(nam, &sa, sizeof(struct sockaddr_ctl));
440
441 lck_mtx_lock(&ctl_mtx);
442 kctl = ctl_find_by_id_unit(sa.sc_id, sa.sc_unit);
443 if (kctl == NULL) {
444 lck_mtx_unlock(&ctl_mtx);
445 return ENOENT;
446 }
447
448 if (((kctl->flags & CTL_FLAG_REG_SOCK_STREAM) &&
449 (so->so_type != SOCK_STREAM)) ||
450 (!(kctl->flags & CTL_FLAG_REG_SOCK_STREAM) &&
451 (so->so_type != SOCK_DGRAM))) {
452 lck_mtx_unlock(&ctl_mtx);
453 return EPROTOTYPE;
454 }
455
456 if (kctl->flags & CTL_FLAG_PRIVILEGED) {
457 if (p == 0) {
458 lck_mtx_unlock(&ctl_mtx);
459 return EINVAL;
460 }
461 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
462 lck_mtx_unlock(&ctl_mtx);
463 return EPERM;
464 }
465 }
466
467 if (kctl->setup != NULL) {
468 error = (*kctl->setup)(&sa.sc_unit, &kcb->userdata);
469 if (error != 0) {
470 lck_mtx_unlock(&ctl_mtx);
471 return error;
472 }
473 } else if ((kctl->flags & CTL_FLAG_REG_ID_UNIT) || sa.sc_unit != 0) {
474 if (kcb_find(kctl, sa.sc_unit) != NULL) {
475 lck_mtx_unlock(&ctl_mtx);
476 return EBUSY;
477 }
478 } else {
479 /* Find an unused ID, assumes control IDs are in order */
480 u_int32_t unit = 1;
481
482 TAILQ_FOREACH(kcb_next, &kctl->kcb_head, next) {
483 if (kcb_next->sac.sc_unit > unit) {
484 /* Found a gap, lets fill it in */
485 break;
486 }
487 unit = kcb_next->sac.sc_unit + 1;
488 if (unit == ctl_maxunit) {
489 break;
490 }
491 }
492
493 if (unit == ctl_maxunit) {
494 lck_mtx_unlock(&ctl_mtx);
495 return EBUSY;
496 }
497
498 sa.sc_unit = unit;
499 }
500
501 bcopy(&sa, &kcb->sac, sizeof(struct sockaddr_ctl));
502 kcb->kctl = kctl;
503 if (kcb_next != NULL) {
504 TAILQ_INSERT_BEFORE(kcb_next, kcb, next);
505 } else {
506 TAILQ_INSERT_TAIL(&kctl->kcb_head, kcb, next);
507 }
508 kctlstat.kcs_pcbcount++;
509 kctlstat.kcs_gencnt++;
510 kctlstat.kcs_connections++;
511 lck_mtx_unlock(&ctl_mtx);
512
513 /*
514 * rdar://15526688: Limit the send and receive sizes to sb_max
515 * by using the same scaling as sbreserve()
516 */
517 if (kctl->sendbufsize > sb_max_adj) {
518 sendbufsize = (u_int32_t)sb_max_adj;
519 } else {
520 sendbufsize = kctl->sendbufsize;
521 }
522
523 if (kctl->recvbufsize > sb_max_adj) {
524 recvbufsize = (u_int32_t)sb_max_adj;
525 } else {
526 recvbufsize = kctl->recvbufsize;
527 }
528
529 error = soreserve(so, sendbufsize, recvbufsize);
530 if (error) {
531 if (ctl_debug) {
532 printf("%s - soreserve(%llx, %u, %u) error %d\n",
533 __func__, (uint64_t)VM_KERNEL_ADDRPERM(so),
534 sendbufsize, recvbufsize, error);
535 }
536 goto done;
537 }
538
539 done:
540 if (error) {
541 soisdisconnected(so);
542 #if DEVELOPMENT || DEBUG
543 kcb->status = KCTL_DISCONNECTED;
544 #endif /* DEVELOPMENT || DEBUG */
545 lck_mtx_lock(&ctl_mtx);
546 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
547 kcb->kctl = NULL;
548 kcb->sac.sc_unit = 0;
549 kctlstat.kcs_pcbcount--;
550 kctlstat.kcs_gencnt++;
551 kctlstat.kcs_conn_fail++;
552 lck_mtx_unlock(&ctl_mtx);
553 }
554 return error;
555 }
556
557 static int
ctl_bind(struct socket * so,struct sockaddr * nam,struct proc * p)558 ctl_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
559 {
560 int error = 0;
561 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
562
563 if (kcb == NULL) {
564 panic("ctl_bind so_pcb null");
565 }
566
567 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
568 ctl_kcb_increment_use_count(kcb, mtx_held);
569 ctl_kcb_require_clearing(kcb, mtx_held);
570
571 error = ctl_setup_kctl(so, nam, p);
572 if (error) {
573 goto out;
574 }
575
576 if (kcb->kctl == NULL) {
577 panic("ctl_bind kctl null");
578 }
579
580 if (kcb->kctl->bind == NULL) {
581 error = EINVAL;
582 goto out;
583 }
584
585 socket_unlock(so, 0);
586 error = (*kcb->kctl->bind)(kcb->kctl->kctlref, &kcb->sac, &kcb->userdata);
587 socket_lock(so, 0);
588
589 out:
590 ctl_kcb_done_clearing(kcb);
591 ctl_kcb_decrement_use_count(kcb);
592 return error;
593 }
594
595 static int
ctl_connect(struct socket * so,struct sockaddr * nam,struct proc * p)596 ctl_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
597 {
598 int error = 0;
599 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
600
601 if (kcb == NULL) {
602 panic("ctl_connect so_pcb null");
603 }
604
605 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
606 ctl_kcb_increment_use_count(kcb, mtx_held);
607 ctl_kcb_require_clearing(kcb, mtx_held);
608
609 #if DEVELOPMENT || DEBUG
610 if (kcb->status != KCTL_DISCONNECTED && ctl_panic_debug) {
611 panic("kctl already connecting/connected");
612 }
613 kcb->status = KCTL_CONNECTING;
614 #endif /* DEVELOPMENT || DEBUG */
615
616 error = ctl_setup_kctl(so, nam, p);
617 if (error) {
618 goto out;
619 }
620
621 if (kcb->kctl == NULL) {
622 panic("ctl_connect kctl null");
623 }
624
625 soisconnecting(so);
626 socket_unlock(so, 0);
627 error = (*kcb->kctl->connect)(kcb->kctl->kctlref, &kcb->sac, &kcb->userdata);
628 socket_lock(so, 0);
629 if (error) {
630 goto end;
631 }
632 soisconnected(so);
633 #if DEVELOPMENT || DEBUG
634 kcb->status = KCTL_CONNECTED;
635 #endif /* DEVELOPMENT || DEBUG */
636
637 end:
638 if (error && kcb->kctl->disconnect) {
639 /*
640 * XXX Make sure we Don't check the return value
641 * of disconnect here.
642 * ipsec/utun_ctl_disconnect will return error when
643 * disconnect gets called after connect failure.
644 * However if we decide to check for disconnect return
645 * value here. Please make sure to revisit
646 * ipsec/utun_ctl_disconnect.
647 */
648 socket_unlock(so, 0);
649 (*kcb->kctl->disconnect)(kcb->kctl->kctlref, kcb->sac.sc_unit, kcb->userdata);
650 socket_lock(so, 0);
651 }
652 if (error) {
653 soisdisconnected(so);
654 #if DEVELOPMENT || DEBUG
655 kcb->status = KCTL_DISCONNECTED;
656 #endif /* DEVELOPMENT || DEBUG */
657 lck_mtx_lock(&ctl_mtx);
658 TAILQ_REMOVE(&kcb->kctl->kcb_head, kcb, next);
659 kcb->kctl = NULL;
660 kcb->sac.sc_unit = 0;
661 kctlstat.kcs_pcbcount--;
662 kctlstat.kcs_gencnt++;
663 kctlstat.kcs_conn_fail++;
664 lck_mtx_unlock(&ctl_mtx);
665 }
666 out:
667 ctl_kcb_done_clearing(kcb);
668 ctl_kcb_decrement_use_count(kcb);
669 return error;
670 }
671
672 static int
ctl_disconnect(struct socket * so)673 ctl_disconnect(struct socket *so)
674 {
675 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
676
677 if ((kcb = (struct ctl_cb *)so->so_pcb)) {
678 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
679 ctl_kcb_increment_use_count(kcb, mtx_held);
680 ctl_kcb_require_clearing(kcb, mtx_held);
681 struct kctl *kctl = kcb->kctl;
682
683 if (kctl && kctl->disconnect) {
684 socket_unlock(so, 0);
685 (*kctl->disconnect)(kctl->kctlref, kcb->sac.sc_unit,
686 kcb->userdata);
687 socket_lock(so, 0);
688 }
689
690 soisdisconnected(so);
691 #if DEVELOPMENT || DEBUG
692 kcb->status = KCTL_DISCONNECTED;
693 #endif /* DEVELOPMENT || DEBUG */
694
695 socket_unlock(so, 0);
696 lck_mtx_lock(&ctl_mtx);
697 kcb->kctl = 0;
698 kcb->sac.sc_unit = 0;
699 while (kcb->usecount != 0) {
700 msleep(&kcb->usecount, &ctl_mtx, 0, "kcb->usecount", 0);
701 }
702 TAILQ_REMOVE(&kctl->kcb_head, kcb, next);
703 kctlstat.kcs_pcbcount--;
704 kctlstat.kcs_gencnt++;
705 lck_mtx_unlock(&ctl_mtx);
706 socket_lock(so, 0);
707 ctl_kcb_done_clearing(kcb);
708 ctl_kcb_decrement_use_count(kcb);
709 }
710 return 0;
711 }
712
713 static int
ctl_peeraddr(struct socket * so,struct sockaddr ** nam)714 ctl_peeraddr(struct socket *so, struct sockaddr **nam)
715 {
716 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
717 struct kctl *kctl;
718 struct sockaddr_ctl sc;
719
720 if (kcb == NULL) { /* sanity check */
721 return ENOTCONN;
722 }
723
724 if ((kctl = kcb->kctl) == NULL) {
725 return EINVAL;
726 }
727
728 bzero(&sc, sizeof(struct sockaddr_ctl));
729 sc.sc_len = sizeof(struct sockaddr_ctl);
730 sc.sc_family = AF_SYSTEM;
731 sc.ss_sysaddr = AF_SYS_CONTROL;
732 sc.sc_id = kctl->id;
733 sc.sc_unit = kcb->sac.sc_unit;
734
735 *nam = dup_sockaddr((struct sockaddr *)&sc, 1);
736
737 return 0;
738 }
739
740 static void
ctl_sbrcv_trim(struct socket * so)741 ctl_sbrcv_trim(struct socket *so)
742 {
743 struct sockbuf *sb = &so->so_rcv;
744
745 if (sb->sb_hiwat > sb->sb_idealsize) {
746 u_int32_t diff;
747 int32_t trim;
748
749 /*
750 * The difference between the ideal size and the
751 * current size is the upper bound of the trimage
752 */
753 diff = sb->sb_hiwat - sb->sb_idealsize;
754 /*
755 * We cannot trim below the outstanding data
756 */
757 trim = sb->sb_hiwat - sb->sb_cc;
758
759 trim = imin(trim, (int32_t)diff);
760
761 if (trim > 0) {
762 sbreserve(sb, (sb->sb_hiwat - trim));
763
764 if (ctl_debug) {
765 printf("%s - shrunk to %d\n",
766 __func__, sb->sb_hiwat);
767 }
768 }
769 }
770 }
771
772 static int
ctl_usr_rcvd(struct socket * so,int flags)773 ctl_usr_rcvd(struct socket *so, int flags)
774 {
775 int error = 0;
776 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
777 struct kctl *kctl;
778
779 if (kcb == NULL) {
780 return ENOTCONN;
781 }
782
783 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
784 ctl_kcb_increment_use_count(kcb, mtx_held);
785
786 if ((kctl = kcb->kctl) == NULL) {
787 error = EINVAL;
788 goto out;
789 }
790
791 if (kctl->rcvd) {
792 socket_unlock(so, 0);
793 (*kctl->rcvd)(kctl->kctlref, kcb->sac.sc_unit, kcb->userdata, flags);
794 socket_lock(so, 0);
795 }
796
797 ctl_sbrcv_trim(so);
798
799 out:
800 ctl_kcb_decrement_use_count(kcb);
801 return error;
802 }
803
804 static int
ctl_send(struct socket * so,int flags,struct mbuf * m,struct sockaddr * addr,struct mbuf * control,struct proc * p)805 ctl_send(struct socket *so, int flags, struct mbuf *m,
806 struct sockaddr *addr, struct mbuf *control,
807 struct proc *p)
808 {
809 #pragma unused(addr, p)
810 int error = 0;
811 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
812 struct kctl *kctl;
813
814 if (control) {
815 m_freem(control);
816 }
817
818 if (kcb == NULL) { /* sanity check */
819 m_freem(m);
820 return ENOTCONN;
821 }
822
823 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
824 ctl_kcb_increment_use_count(kcb, mtx_held);
825
826 if (error == 0 && (kctl = kcb->kctl) == NULL) {
827 error = EINVAL;
828 }
829
830 if (error == 0 && kctl->send) {
831 so_tc_update_stats(m, so, m_get_service_class(m));
832 socket_unlock(so, 0);
833 error = (*kctl->send)(kctl->kctlref, kcb->sac.sc_unit, kcb->userdata,
834 m, flags);
835 socket_lock(so, 0);
836 } else {
837 m_freem(m);
838 if (error == 0) {
839 error = ENOTSUP;
840 }
841 }
842 if (error != 0) {
843 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_send_fail);
844 }
845 ctl_kcb_decrement_use_count(kcb);
846
847 return error;
848 }
849
850 static int
ctl_send_list(struct socket * so,struct mbuf * m,u_int * pktcnt,int flags)851 ctl_send_list(struct socket *so, struct mbuf *m, u_int *pktcnt, int flags)
852 {
853 int error = 0;
854 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
855 struct kctl *kctl;
856 const bool update_tc = SOCK_DOM(so) == PF_INET || SOCK_DOM(so) == PF_INET6;
857
858 if (kcb == NULL) { /* sanity check */
859 m_freem_list(m);
860 return ENOTCONN;
861 }
862
863 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
864 ctl_kcb_increment_use_count(kcb, mtx_held);
865
866 if ((kctl = kcb->kctl) == NULL) {
867 error = EINVAL;
868 goto done;
869 }
870
871 if (kctl->send_list != NULL) {
872 struct mbuf *nxt;
873
874 for (nxt = m; update_tc && nxt != NULL; nxt = nxt->m_nextpkt) {
875 so_tc_update_stats(nxt, so, m_get_service_class(nxt));
876 }
877
878 socket_unlock(so, 0);
879 error = (*kctl->send_list)(kctl->kctlref, kcb->sac.sc_unit,
880 kcb->userdata, m, flags);
881 socket_lock(so, 0);
882 } else {
883 *pktcnt = 0;
884 while (m != NULL && error == 0) {
885 struct mbuf *nextpkt = m->m_nextpkt;
886
887 m->m_nextpkt = NULL;
888
889 if (update_tc) {
890 so_tc_update_stats(m, so, m_get_service_class(m));
891 }
892 socket_unlock(so, 0);
893 error = (*kctl->send)(kctl->kctlref, kcb->sac.sc_unit,
894 kcb->userdata, m, flags);
895 socket_lock(so, 0);
896 m = nextpkt;
897 if (error == 0) {
898 *pktcnt += 1;
899 }
900 }
901 if (m != NULL) {
902 m_freem_list(m);
903 }
904 }
905 done:
906 if (error != 0) {
907 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_send_list_fail);
908 }
909 ctl_kcb_decrement_use_count(kcb);
910
911 return error;
912 }
913
914 static errno_t
ctl_rcvbspace(struct socket * so,size_t datasize,u_int32_t kctlflags,u_int32_t flags)915 ctl_rcvbspace(struct socket *so, size_t datasize,
916 u_int32_t kctlflags, u_int32_t flags)
917 {
918 struct sockbuf *sb = &so->so_rcv;
919 u_int32_t space = sbspace(sb);
920 errno_t error;
921
922 if ((kctlflags & CTL_FLAG_REG_CRIT) == 0) {
923 if ((u_int32_t) space >= datasize) {
924 error = 0;
925 } else {
926 error = ENOBUFS;
927 }
928 } else if ((flags & CTL_DATA_CRIT) == 0) {
929 /*
930 * Reserve 25% for critical messages
931 */
932 if (space < (sb->sb_hiwat >> 2) ||
933 space < datasize) {
934 error = ENOBUFS;
935 } else {
936 error = 0;
937 }
938 } else {
939 size_t autorcvbuf_max;
940
941 /*
942 * Allow overcommit of 25%
943 */
944 autorcvbuf_max = min(sb->sb_idealsize + (sb->sb_idealsize >> 2),
945 ctl_autorcvbuf_max);
946
947 if ((u_int32_t) space >= datasize) {
948 error = 0;
949 } else if (tcp_cansbgrow(sb) &&
950 sb->sb_hiwat < autorcvbuf_max) {
951 /*
952 * Grow with a little bit of leeway
953 */
954 size_t grow = datasize - space + _MSIZE;
955 u_int32_t cc = (u_int32_t)MIN(MIN((sb->sb_hiwat + grow), autorcvbuf_max), UINT32_MAX);
956
957 if (sbreserve(sb, cc) == 1) {
958 if (sb->sb_hiwat > ctl_autorcvbuf_high) {
959 ctl_autorcvbuf_high = sb->sb_hiwat;
960 }
961
962 /*
963 * A final check
964 */
965 if ((u_int32_t) sbspace(sb) >= datasize) {
966 error = 0;
967 } else {
968 error = ENOBUFS;
969 }
970
971 if (ctl_debug) {
972 printf("%s - grown to %d error %d\n",
973 __func__, sb->sb_hiwat, error);
974 }
975 } else {
976 error = ENOBUFS;
977 }
978 } else {
979 error = ENOBUFS;
980 }
981 }
982 return error;
983 }
984
985 errno_t
ctl_enqueuembuf(kern_ctl_ref kctlref,u_int32_t unit,struct mbuf * m,u_int32_t flags)986 ctl_enqueuembuf(kern_ctl_ref kctlref, u_int32_t unit, struct mbuf *m,
987 u_int32_t flags)
988 {
989 struct socket *so;
990 errno_t error = 0;
991 int len = m->m_pkthdr.len;
992 u_int32_t kctlflags;
993
994 so = kcb_find_socket(kctlref, unit, &kctlflags);
995 if (so == NULL) {
996 return EINVAL;
997 }
998
999 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
1000 error = ENOBUFS;
1001 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1002 goto bye;
1003 }
1004 if ((flags & CTL_DATA_EOR)) {
1005 m->m_flags |= M_EOR;
1006 }
1007
1008 so_recv_data_stat(so, m, 0);
1009 if (sbappend_nodrop(&so->so_rcv, m) != 0) {
1010 if ((flags & CTL_DATA_NOWAKEUP) == 0) {
1011 sorwakeup(so);
1012 }
1013 } else {
1014 error = ENOBUFS;
1015 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1016 }
1017 bye:
1018 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT)) {
1019 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
1020 __func__, error, len,
1021 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
1022 }
1023
1024 socket_unlock(so, 1);
1025 if (error != 0) {
1026 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
1027 }
1028
1029 return error;
1030 }
1031
1032 /*
1033 * Compute space occupied by mbuf like sbappendrecord
1034 */
1035 static int
m_space(struct mbuf * m)1036 m_space(struct mbuf *m)
1037 {
1038 int space = 0;
1039 struct mbuf *nxt;
1040
1041 for (nxt = m; nxt != NULL; nxt = nxt->m_next) {
1042 space += nxt->m_len;
1043 }
1044
1045 return space;
1046 }
1047
1048 errno_t
ctl_enqueuembuf_list(void * kctlref,u_int32_t unit,struct mbuf * m_list,u_int32_t flags,struct mbuf ** m_remain)1049 ctl_enqueuembuf_list(void *kctlref, u_int32_t unit, struct mbuf *m_list,
1050 u_int32_t flags, struct mbuf **m_remain)
1051 {
1052 struct socket *so = NULL;
1053 errno_t error = 0;
1054 struct mbuf *m, *nextpkt;
1055 int needwakeup = 0;
1056 int len = 0;
1057 u_int32_t kctlflags;
1058
1059 /*
1060 * Need to point the beginning of the list in case of early exit
1061 */
1062 m = m_list;
1063
1064 /*
1065 * kcb_find_socket takes the socket lock with a reference
1066 */
1067 so = kcb_find_socket(kctlref, unit, &kctlflags);
1068 if (so == NULL) {
1069 error = EINVAL;
1070 goto done;
1071 }
1072
1073 if (kctlflags & CTL_FLAG_REG_SOCK_STREAM) {
1074 error = EOPNOTSUPP;
1075 goto done;
1076 }
1077 if (flags & CTL_DATA_EOR) {
1078 error = EINVAL;
1079 goto done;
1080 }
1081
1082 for (m = m_list; m != NULL; m = nextpkt) {
1083 nextpkt = m->m_nextpkt;
1084
1085 if (m->m_pkthdr.len == 0 && ctl_debug) {
1086 printf("%s: %llx m_pkthdr.len is 0",
1087 __func__, (uint64_t)VM_KERNEL_ADDRPERM(m));
1088 }
1089
1090 /*
1091 * The mbuf is either appended or freed by sbappendrecord()
1092 * so it's not reliable from a data standpoint
1093 */
1094 len = m_space(m);
1095 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
1096 error = ENOBUFS;
1097 OSIncrementAtomic64(
1098 (SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1099 break;
1100 } else {
1101 /*
1102 * Unlink from the list, m is on its own
1103 */
1104 m->m_nextpkt = NULL;
1105 so_recv_data_stat(so, m, 0);
1106 if (sbappendrecord_nodrop(&so->so_rcv, m) != 0) {
1107 needwakeup = 1;
1108 } else {
1109 /*
1110 * We free or return the remaining
1111 * mbufs in the list
1112 */
1113 m = nextpkt;
1114 error = ENOBUFS;
1115 OSIncrementAtomic64(
1116 (SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1117 break;
1118 }
1119 }
1120 }
1121 if (needwakeup && (flags & CTL_DATA_NOWAKEUP) == 0) {
1122 sorwakeup(so);
1123 }
1124
1125 done:
1126 if (so != NULL) {
1127 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT)) {
1128 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
1129 __func__, error, len,
1130 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
1131 }
1132
1133 socket_unlock(so, 1);
1134 }
1135 if (m_remain) {
1136 *m_remain = m;
1137
1138 if (m != NULL && socket_debug && so != NULL &&
1139 (so->so_options & SO_DEBUG)) {
1140 struct mbuf *n;
1141
1142 printf("%s m_list %llx\n", __func__,
1143 (uint64_t) VM_KERNEL_ADDRPERM(m_list));
1144 for (n = m; n != NULL; n = n->m_nextpkt) {
1145 printf(" remain %llx m_next %llx\n",
1146 (uint64_t) VM_KERNEL_ADDRPERM(n),
1147 (uint64_t) VM_KERNEL_ADDRPERM(n->m_next));
1148 }
1149 }
1150 } else {
1151 if (m != NULL) {
1152 m_freem_list(m);
1153 }
1154 }
1155 if (error != 0) {
1156 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
1157 }
1158 return error;
1159 }
1160
1161 errno_t
ctl_enqueuedata(void * kctlref,u_int32_t unit,void * data,size_t len,u_int32_t flags)1162 ctl_enqueuedata(void *kctlref, u_int32_t unit, void *data, size_t len,
1163 u_int32_t flags)
1164 {
1165 struct socket *so;
1166 struct mbuf *m;
1167 errno_t error = 0;
1168 unsigned int num_needed;
1169 struct mbuf *n;
1170 size_t curlen = 0;
1171 u_int32_t kctlflags;
1172
1173 so = kcb_find_socket(kctlref, unit, &kctlflags);
1174 if (so == NULL) {
1175 return EINVAL;
1176 }
1177
1178 if (ctl_rcvbspace(so, len, kctlflags, flags) != 0) {
1179 error = ENOBUFS;
1180 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1181 goto bye;
1182 }
1183
1184 num_needed = 1;
1185 m = m_allocpacket_internal(&num_needed, len, NULL, M_NOWAIT, 1, 0);
1186 if (m == NULL) {
1187 kctlstat.kcs_enqdata_mb_alloc_fail++;
1188 if (ctl_debug) {
1189 printf("%s: m_allocpacket_internal(%lu) failed\n",
1190 __func__, len);
1191 }
1192 error = ENOMEM;
1193 goto bye;
1194 }
1195
1196 for (n = m; n != NULL; n = n->m_next) {
1197 size_t mlen = mbuf_maxlen(n);
1198
1199 if (mlen + curlen > len) {
1200 mlen = len - curlen;
1201 }
1202 n->m_len = (int32_t)mlen;
1203 bcopy((char *)data + curlen, n->m_data, mlen);
1204 curlen += mlen;
1205 }
1206 mbuf_pkthdr_setlen(m, curlen);
1207
1208 if ((flags & CTL_DATA_EOR)) {
1209 m->m_flags |= M_EOR;
1210 }
1211 so_recv_data_stat(so, m, 0);
1212 /*
1213 * No need to call the "nodrop" variant of sbappend
1214 * because the mbuf is local to the scope of the function
1215 */
1216 if (sbappend(&so->so_rcv, m) != 0) {
1217 if ((flags & CTL_DATA_NOWAKEUP) == 0) {
1218 sorwakeup(so);
1219 }
1220 } else {
1221 kctlstat.kcs_enqdata_sbappend_fail++;
1222 error = ENOBUFS;
1223 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fullsock);
1224 }
1225
1226 bye:
1227 if (ctl_debug && error != 0 && (flags & CTL_DATA_CRIT)) {
1228 printf("%s - crit data err %d len %d hiwat %d cc: %d\n",
1229 __func__, error, (int)len,
1230 so->so_rcv.sb_hiwat, so->so_rcv.sb_cc);
1231 }
1232
1233 socket_unlock(so, 1);
1234 if (error != 0) {
1235 OSIncrementAtomic64((SInt64 *)&kctlstat.kcs_enqueue_fail);
1236 }
1237 return error;
1238 }
1239
1240 errno_t
ctl_getenqueuepacketcount(kern_ctl_ref kctlref,u_int32_t unit,u_int32_t * pcnt)1241 ctl_getenqueuepacketcount(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *pcnt)
1242 {
1243 struct socket *so;
1244 u_int32_t cnt;
1245 struct mbuf *m1;
1246
1247 if (pcnt == NULL) {
1248 return EINVAL;
1249 }
1250
1251 so = kcb_find_socket(kctlref, unit, NULL);
1252 if (so == NULL) {
1253 return EINVAL;
1254 }
1255
1256 cnt = 0;
1257 m1 = so->so_rcv.sb_mb;
1258 while (m1 != NULL) {
1259 if (m1->m_type == MT_DATA ||
1260 m1->m_type == MT_HEADER ||
1261 m1->m_type == MT_OOBDATA) {
1262 cnt += 1;
1263 }
1264 m1 = m1->m_nextpkt;
1265 }
1266 *pcnt = cnt;
1267
1268 socket_unlock(so, 1);
1269
1270 return 0;
1271 }
1272
1273 errno_t
ctl_getenqueuespace(kern_ctl_ref kctlref,u_int32_t unit,size_t * space)1274 ctl_getenqueuespace(kern_ctl_ref kctlref, u_int32_t unit, size_t *space)
1275 {
1276 struct socket *so;
1277 long avail;
1278
1279 if (space == NULL) {
1280 return EINVAL;
1281 }
1282
1283 so = kcb_find_socket(kctlref, unit, NULL);
1284 if (so == NULL) {
1285 return EINVAL;
1286 }
1287
1288 avail = sbspace(&so->so_rcv);
1289 *space = (avail < 0) ? 0 : avail;
1290 socket_unlock(so, 1);
1291
1292 return 0;
1293 }
1294
1295 errno_t
ctl_getenqueuereadable(kern_ctl_ref kctlref,u_int32_t unit,u_int32_t * difference)1296 ctl_getenqueuereadable(kern_ctl_ref kctlref, u_int32_t unit,
1297 u_int32_t *difference)
1298 {
1299 struct socket *so;
1300
1301 if (difference == NULL) {
1302 return EINVAL;
1303 }
1304
1305 so = kcb_find_socket(kctlref, unit, NULL);
1306 if (so == NULL) {
1307 return EINVAL;
1308 }
1309
1310 if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat) {
1311 *difference = 0;
1312 } else {
1313 *difference = (so->so_rcv.sb_lowat - so->so_rcv.sb_cc);
1314 }
1315 socket_unlock(so, 1);
1316
1317 return 0;
1318 }
1319
1320 static int
ctl_ctloutput(struct socket * so,struct sockopt * sopt)1321 ctl_ctloutput(struct socket *so, struct sockopt *sopt)
1322 {
1323 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
1324 struct kctl *kctl;
1325 int error = 0;
1326 void *data = NULL;
1327 size_t data_len = 0;
1328 size_t len;
1329
1330 if (sopt->sopt_level != SYSPROTO_CONTROL) {
1331 return EINVAL;
1332 }
1333
1334 if (kcb == NULL) { /* sanity check */
1335 return ENOTCONN;
1336 }
1337
1338 if ((kctl = kcb->kctl) == NULL) {
1339 return EINVAL;
1340 }
1341
1342 lck_mtx_t *mtx_held = socket_getlock(so, PR_F_WILLUNLOCK);
1343 ctl_kcb_increment_use_count(kcb, mtx_held);
1344
1345 switch (sopt->sopt_dir) {
1346 case SOPT_SET:
1347 if (kctl->setopt == NULL) {
1348 error = ENOTSUP;
1349 goto out;
1350 }
1351 if (sopt->sopt_valsize != 0) {
1352 data_len = sopt->sopt_valsize;
1353 data = kalloc_data(data_len, Z_WAITOK | Z_ZERO);
1354 if (data == NULL) {
1355 data_len = 0;
1356 error = ENOMEM;
1357 goto out;
1358 }
1359 error = sooptcopyin(sopt, data,
1360 sopt->sopt_valsize, sopt->sopt_valsize);
1361 }
1362 if (error == 0) {
1363 socket_unlock(so, 0);
1364 error = (*kctl->setopt)(kctl->kctlref,
1365 kcb->sac.sc_unit, kcb->userdata, sopt->sopt_name,
1366 data, sopt->sopt_valsize);
1367 socket_lock(so, 0);
1368 }
1369
1370 kfree_data(data, data_len);
1371 break;
1372
1373 case SOPT_GET:
1374 if (kctl->getopt == NULL) {
1375 error = ENOTSUP;
1376 goto out;
1377 }
1378
1379 if (sopt->sopt_valsize && sopt->sopt_val) {
1380 data_len = sopt->sopt_valsize;
1381 data = kalloc_data(data_len, Z_WAITOK | Z_ZERO);
1382 if (data == NULL) {
1383 data_len = 0;
1384 error = ENOMEM;
1385 goto out;
1386 }
1387 /*
1388 * 4108337 - copy user data in case the
1389 * kernel control needs it
1390 */
1391 error = sooptcopyin(sopt, data,
1392 sopt->sopt_valsize, sopt->sopt_valsize);
1393 }
1394
1395 if (error == 0) {
1396 len = sopt->sopt_valsize;
1397 socket_unlock(so, 0);
1398 error = (*kctl->getopt)(kctl->kctlref, kcb->sac.sc_unit,
1399 kcb->userdata, sopt->sopt_name,
1400 data, &len);
1401 if (data != NULL && len > sopt->sopt_valsize) {
1402 panic_plain("ctl_ctloutput: ctl %s returned "
1403 "len (%lu) > sopt_valsize (%lu)\n",
1404 kcb->kctl->name, len,
1405 sopt->sopt_valsize);
1406 }
1407 socket_lock(so, 0);
1408 if (error == 0) {
1409 if (data != NULL) {
1410 error = sooptcopyout(sopt, data, len);
1411 } else {
1412 sopt->sopt_valsize = len;
1413 }
1414 }
1415 }
1416
1417 kfree_data(data, data_len);
1418 break;
1419 }
1420
1421 out:
1422 ctl_kcb_decrement_use_count(kcb);
1423 return error;
1424 }
1425
1426 static int
ctl_ioctl(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp,struct proc * p)1427 ctl_ioctl(struct socket *so, u_long cmd, caddr_t data,
1428 struct ifnet *ifp, struct proc *p)
1429 {
1430 #pragma unused(so, ifp, p)
1431 int error = ENOTSUP;
1432
1433 switch (cmd) {
1434 /* get the number of controllers */
1435 case CTLIOCGCOUNT: {
1436 struct kctl *kctl;
1437 u_int32_t n = 0;
1438
1439 lck_mtx_lock(&ctl_mtx);
1440 TAILQ_FOREACH(kctl, &ctl_head, next)
1441 n++;
1442 lck_mtx_unlock(&ctl_mtx);
1443
1444 bcopy(&n, data, sizeof(n));
1445 error = 0;
1446 break;
1447 }
1448 case CTLIOCGINFO: {
1449 struct ctl_info ctl_info;
1450 struct kctl *kctl = 0;
1451 size_t name_len;
1452
1453 bcopy(data, &ctl_info, sizeof(ctl_info));
1454 name_len = strnlen(ctl_info.ctl_name, MAX_KCTL_NAME);
1455
1456 if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME) {
1457 error = EINVAL;
1458 break;
1459 }
1460 lck_mtx_lock(&ctl_mtx);
1461 kctl = ctl_find_by_name(ctl_info.ctl_name);
1462 lck_mtx_unlock(&ctl_mtx);
1463 if (kctl == 0) {
1464 error = ENOENT;
1465 break;
1466 }
1467 ctl_info.ctl_id = kctl->id;
1468 bcopy(&ctl_info, data, sizeof(ctl_info));
1469 error = 0;
1470 break;
1471 }
1472
1473 /* add controls to get list of NKEs */
1474 }
1475
1476 return error;
1477 }
1478
1479 static void
kctl_tbl_grow(void)1480 kctl_tbl_grow(void)
1481 {
1482 struct kctl **new_table;
1483 uintptr_t new_size;
1484
1485 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1486
1487 if (kctl_tbl_growing) {
1488 /* Another thread is allocating */
1489 kctl_tbl_growing_waiting++;
1490
1491 do {
1492 (void) msleep((caddr_t) &kctl_tbl_growing, &ctl_mtx,
1493 PSOCK | PCATCH, "kctl_tbl_growing", 0);
1494 } while (kctl_tbl_growing);
1495 kctl_tbl_growing_waiting--;
1496 }
1497 /* Another thread grew the table */
1498 if (kctl_table != NULL && kctl_tbl_count < kctl_tbl_size) {
1499 return;
1500 }
1501
1502 /* Verify we have a sane size */
1503 if (kctl_tbl_size + KCTL_TBL_INC >= UINT16_MAX) {
1504 kctlstat.kcs_tbl_size_too_big++;
1505 if (ctl_debug) {
1506 printf("%s kctl_tbl_size %lu too big\n",
1507 __func__, kctl_tbl_size);
1508 }
1509 return;
1510 }
1511 kctl_tbl_growing = 1;
1512
1513 new_size = kctl_tbl_size + KCTL_TBL_INC;
1514
1515 lck_mtx_unlock(&ctl_mtx);
1516 new_table = kalloc_type(struct kctl *, new_size, Z_WAITOK | Z_ZERO);
1517 lck_mtx_lock(&ctl_mtx);
1518
1519 if (new_table != NULL) {
1520 if (kctl_table != NULL) {
1521 bcopy(kctl_table, new_table,
1522 kctl_tbl_size * sizeof(struct kctl *));
1523
1524 kfree_type(struct kctl *, kctl_tbl_size, kctl_table);
1525 }
1526 kctl_table = new_table;
1527 kctl_tbl_size = new_size;
1528 }
1529
1530 kctl_tbl_growing = 0;
1531
1532 if (kctl_tbl_growing_waiting) {
1533 wakeup(&kctl_tbl_growing);
1534 }
1535 }
1536
1537 #define KCTLREF_INDEX_MASK 0x0000FFFF
1538 #define KCTLREF_GENCNT_MASK 0xFFFF0000
1539 #define KCTLREF_GENCNT_SHIFT 16
1540
1541 static kern_ctl_ref
kctl_make_ref(struct kctl * kctl)1542 kctl_make_ref(struct kctl *kctl)
1543 {
1544 uintptr_t i;
1545
1546 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1547
1548 if (kctl_tbl_count >= kctl_tbl_size) {
1549 kctl_tbl_grow();
1550 }
1551
1552 kctl->kctlref = NULL;
1553 for (i = 0; i < kctl_tbl_size; i++) {
1554 if (kctl_table[i] == NULL) {
1555 uintptr_t ref;
1556
1557 /*
1558 * Reference is index plus one
1559 */
1560 kctl_ref_gencnt += 1;
1561
1562 /*
1563 * Add generation count as salt to reference to prevent
1564 * use after deregister
1565 */
1566 ref = ((kctl_ref_gencnt << KCTLREF_GENCNT_SHIFT) &
1567 KCTLREF_GENCNT_MASK) +
1568 ((i + 1) & KCTLREF_INDEX_MASK);
1569
1570 kctl->kctlref = (void *)(ref);
1571 kctl_table[i] = kctl;
1572 kctl_tbl_count++;
1573 break;
1574 }
1575 }
1576
1577 if (kctl->kctlref == NULL) {
1578 panic("%s no space in table", __func__);
1579 }
1580
1581 if (ctl_debug > 0) {
1582 printf("%s %p for %p\n",
1583 __func__, kctl->kctlref, kctl);
1584 }
1585
1586 return kctl->kctlref;
1587 }
1588
1589 static void
kctl_delete_ref(kern_ctl_ref kctlref)1590 kctl_delete_ref(kern_ctl_ref kctlref)
1591 {
1592 /*
1593 * Reference is index plus one
1594 */
1595 uintptr_t i = (((uintptr_t)kctlref) & KCTLREF_INDEX_MASK) - 1;
1596
1597 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1598
1599 if (i < kctl_tbl_size) {
1600 struct kctl *kctl = kctl_table[i];
1601
1602 if (kctl->kctlref == kctlref) {
1603 kctl_table[i] = NULL;
1604 kctl_tbl_count--;
1605 } else {
1606 kctlstat.kcs_bad_kctlref++;
1607 }
1608 } else {
1609 kctlstat.kcs_bad_kctlref++;
1610 }
1611 }
1612
1613 static struct kctl *
kctl_from_ref(kern_ctl_ref kctlref)1614 kctl_from_ref(kern_ctl_ref kctlref)
1615 {
1616 /*
1617 * Reference is index plus one
1618 */
1619 uintptr_t i = (((uintptr_t)kctlref) & KCTLREF_INDEX_MASK) - 1;
1620 struct kctl *kctl = NULL;
1621
1622 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1623
1624 if (i >= kctl_tbl_size) {
1625 kctlstat.kcs_bad_kctlref++;
1626 return NULL;
1627 }
1628 kctl = kctl_table[i];
1629 if (kctl->kctlref != kctlref) {
1630 kctlstat.kcs_bad_kctlref++;
1631 return NULL;
1632 }
1633 return kctl;
1634 }
1635
1636 /*
1637 * Register/unregister a NKE
1638 */
1639 errno_t
ctl_register(struct kern_ctl_reg * userkctl,kern_ctl_ref * kctlref)1640 ctl_register(struct kern_ctl_reg *userkctl, kern_ctl_ref *kctlref)
1641 {
1642 struct kctl *kctl = NULL;
1643 struct kctl *kctl_next = NULL;
1644 u_int32_t id = 1;
1645 size_t name_len;
1646 int is_extended = 0;
1647 int is_setup = 0;
1648
1649 if (userkctl == NULL) { /* sanity check */
1650 return EINVAL;
1651 }
1652 if (userkctl->ctl_connect == NULL) {
1653 return EINVAL;
1654 }
1655 name_len = strlen(userkctl->ctl_name);
1656 if (name_len == 0 || name_len + 1 > MAX_KCTL_NAME) {
1657 return EINVAL;
1658 }
1659
1660 kctl = kalloc_type(struct kctl, Z_WAITOK | Z_ZERO | Z_NOFAIL);
1661
1662 lck_mtx_lock(&ctl_mtx);
1663
1664 if (kctl_make_ref(kctl) == NULL) {
1665 lck_mtx_unlock(&ctl_mtx);
1666 kfree_type(struct kctl, kctl);
1667 return ENOMEM;
1668 }
1669
1670 /*
1671 * Kernel Control IDs
1672 *
1673 * CTL_FLAG_REG_ID_UNIT indicates the control ID and unit number are
1674 * static. If they do not exist, add them to the list in order. If the
1675 * flag is not set, we must find a new unique value. We assume the
1676 * list is in order. We find the last item in the list and add one. If
1677 * this leads to wrapping the id around, we start at the front of the
1678 * list and look for a gap.
1679 */
1680
1681 if ((userkctl->ctl_flags & CTL_FLAG_REG_ID_UNIT) == 0) {
1682 /* Must dynamically assign an unused ID */
1683
1684 /* Verify the same name isn't already registered */
1685 if (ctl_find_by_name(userkctl->ctl_name) != NULL) {
1686 kctl_delete_ref(kctl->kctlref);
1687 lck_mtx_unlock(&ctl_mtx);
1688 kfree_type(struct kctl, kctl);
1689 return EEXIST;
1690 }
1691
1692 /* Start with 1 in case the list is empty */
1693 id = 1;
1694 kctl_next = TAILQ_LAST(&ctl_head, kctl_list);
1695
1696 if (kctl_next != NULL) {
1697 /* List was not empty, add one to the last item */
1698 id = kctl_next->id + 1;
1699 kctl_next = NULL;
1700
1701 /*
1702 * If this wrapped the id number, start looking at
1703 * the front of the list for an unused id.
1704 */
1705 if (id == 0) {
1706 /* Find the next unused ID */
1707 id = 1;
1708
1709 TAILQ_FOREACH(kctl_next, &ctl_head, next) {
1710 if (kctl_next->id > id) {
1711 /* We found a gap */
1712 break;
1713 }
1714
1715 id = kctl_next->id + 1;
1716 }
1717 }
1718 }
1719
1720 userkctl->ctl_id = id;
1721 kctl->id = id;
1722 kctl->reg_unit = -1;
1723 } else {
1724 TAILQ_FOREACH(kctl_next, &ctl_head, next) {
1725 if (kctl_next->id > userkctl->ctl_id) {
1726 break;
1727 }
1728 }
1729
1730 if (ctl_find_by_id_unit(userkctl->ctl_id, userkctl->ctl_unit)) {
1731 kctl_delete_ref(kctl->kctlref);
1732 lck_mtx_unlock(&ctl_mtx);
1733 kfree_type(struct kctl, kctl);
1734 return EEXIST;
1735 }
1736 kctl->id = userkctl->ctl_id;
1737 kctl->reg_unit = userkctl->ctl_unit;
1738 }
1739
1740 is_extended = (userkctl->ctl_flags & CTL_FLAG_REG_EXTENDED);
1741 is_setup = (userkctl->ctl_flags & CTL_FLAG_REG_SETUP);
1742
1743 strlcpy(kctl->name, userkctl->ctl_name, MAX_KCTL_NAME);
1744 kctl->flags = userkctl->ctl_flags;
1745
1746 /*
1747 * Let the caller know the default send and receive sizes
1748 */
1749 if (userkctl->ctl_sendsize == 0) {
1750 kctl->sendbufsize = CTL_SENDSIZE;
1751 userkctl->ctl_sendsize = kctl->sendbufsize;
1752 } else {
1753 kctl->sendbufsize = userkctl->ctl_sendsize;
1754 }
1755 if (userkctl->ctl_recvsize == 0) {
1756 kctl->recvbufsize = CTL_RECVSIZE;
1757 userkctl->ctl_recvsize = kctl->recvbufsize;
1758 } else {
1759 kctl->recvbufsize = userkctl->ctl_recvsize;
1760 }
1761
1762 if (is_setup) {
1763 kctl->setup = userkctl->ctl_setup;
1764 }
1765 kctl->bind = userkctl->ctl_bind;
1766 kctl->connect = userkctl->ctl_connect;
1767 kctl->disconnect = userkctl->ctl_disconnect;
1768 kctl->send = userkctl->ctl_send;
1769 kctl->setopt = userkctl->ctl_setopt;
1770 kctl->getopt = userkctl->ctl_getopt;
1771 if (is_extended) {
1772 kctl->rcvd = userkctl->ctl_rcvd;
1773 kctl->send_list = userkctl->ctl_send_list;
1774 }
1775
1776 TAILQ_INIT(&kctl->kcb_head);
1777
1778 if (kctl_next) {
1779 TAILQ_INSERT_BEFORE(kctl_next, kctl, next);
1780 } else {
1781 TAILQ_INSERT_TAIL(&ctl_head, kctl, next);
1782 }
1783
1784 kctlstat.kcs_reg_count++;
1785 kctlstat.kcs_gencnt++;
1786
1787 lck_mtx_unlock(&ctl_mtx);
1788
1789 *kctlref = kctl->kctlref;
1790
1791 ctl_post_msg(KEV_CTL_REGISTERED, kctl->id);
1792 return 0;
1793 }
1794
1795 errno_t
ctl_deregister(void * kctlref)1796 ctl_deregister(void *kctlref)
1797 {
1798 struct kctl *kctl;
1799
1800 lck_mtx_lock(&ctl_mtx);
1801 if ((kctl = kctl_from_ref(kctlref)) == NULL) {
1802 kctlstat.kcs_bad_kctlref++;
1803 lck_mtx_unlock(&ctl_mtx);
1804 if (ctl_debug != 0) {
1805 printf("%s invalid kctlref %p\n",
1806 __func__, kctlref);
1807 }
1808 return EINVAL;
1809 }
1810
1811 if (!TAILQ_EMPTY(&kctl->kcb_head)) {
1812 lck_mtx_unlock(&ctl_mtx);
1813 return EBUSY;
1814 }
1815
1816 TAILQ_REMOVE(&ctl_head, kctl, next);
1817
1818 kctlstat.kcs_reg_count--;
1819 kctlstat.kcs_gencnt++;
1820
1821 kctl_delete_ref(kctl->kctlref);
1822 lck_mtx_unlock(&ctl_mtx);
1823
1824 ctl_post_msg(KEV_CTL_DEREGISTERED, kctl->id);
1825 kfree_type(struct kctl, kctl);
1826 return 0;
1827 }
1828
1829 /*
1830 * Must be called with global ctl_mtx lock taked
1831 */
1832 static struct kctl *
ctl_find_by_name(const char * name)1833 ctl_find_by_name(const char *name)
1834 {
1835 struct kctl *kctl;
1836
1837 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1838
1839 TAILQ_FOREACH(kctl, &ctl_head, next)
1840 if (strncmp(kctl->name, name, sizeof(kctl->name)) == 0) {
1841 return kctl;
1842 }
1843
1844 return NULL;
1845 }
1846
1847 u_int32_t
ctl_id_by_name(const char * name)1848 ctl_id_by_name(const char *name)
1849 {
1850 u_int32_t ctl_id = 0;
1851 struct kctl *kctl;
1852
1853 lck_mtx_lock(&ctl_mtx);
1854 kctl = ctl_find_by_name(name);
1855 if (kctl) {
1856 ctl_id = kctl->id;
1857 }
1858 lck_mtx_unlock(&ctl_mtx);
1859
1860 return ctl_id;
1861 }
1862
1863 errno_t
ctl_name_by_id(u_int32_t id,char * out_name,size_t maxsize)1864 ctl_name_by_id(u_int32_t id, char *out_name, size_t maxsize)
1865 {
1866 int found = 0;
1867 struct kctl *kctl;
1868
1869 lck_mtx_lock(&ctl_mtx);
1870 TAILQ_FOREACH(kctl, &ctl_head, next) {
1871 if (kctl->id == id) {
1872 break;
1873 }
1874 }
1875
1876 if (kctl) {
1877 if (maxsize > MAX_KCTL_NAME) {
1878 maxsize = MAX_KCTL_NAME;
1879 }
1880 strlcpy(out_name, kctl->name, maxsize);
1881 found = 1;
1882 }
1883 lck_mtx_unlock(&ctl_mtx);
1884
1885 return found ? 0 : ENOENT;
1886 }
1887
1888 /*
1889 * Must be called with global ctl_mtx lock taked
1890 *
1891 */
1892 static struct kctl *
ctl_find_by_id_unit(u_int32_t id,u_int32_t unit)1893 ctl_find_by_id_unit(u_int32_t id, u_int32_t unit)
1894 {
1895 struct kctl *kctl;
1896
1897 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1898
1899 TAILQ_FOREACH(kctl, &ctl_head, next) {
1900 if (kctl->id == id && (kctl->flags & CTL_FLAG_REG_ID_UNIT) == 0) {
1901 return kctl;
1902 } else if (kctl->id == id && kctl->reg_unit == unit) {
1903 return kctl;
1904 }
1905 }
1906 return NULL;
1907 }
1908
1909 /*
1910 * Must be called with kernel controller lock taken
1911 */
1912 static struct ctl_cb *
kcb_find(struct kctl * kctl,u_int32_t unit)1913 kcb_find(struct kctl *kctl, u_int32_t unit)
1914 {
1915 struct ctl_cb *kcb;
1916
1917 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_OWNED);
1918
1919 TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
1920 if (kcb->sac.sc_unit == unit) {
1921 return kcb;
1922 }
1923
1924 return NULL;
1925 }
1926
1927 static struct socket *
kcb_find_socket(kern_ctl_ref kctlref,u_int32_t unit,u_int32_t * kctlflags)1928 kcb_find_socket(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *kctlflags)
1929 {
1930 struct socket *so = NULL;
1931 struct ctl_cb *kcb;
1932 void *lr_saved;
1933 struct kctl *kctl;
1934 int i;
1935
1936 lr_saved = __builtin_return_address(0);
1937
1938 lck_mtx_lock(&ctl_mtx);
1939 /*
1940 * First validate the kctlref
1941 */
1942 if ((kctl = kctl_from_ref(kctlref)) == NULL) {
1943 kctlstat.kcs_bad_kctlref++;
1944 lck_mtx_unlock(&ctl_mtx);
1945 if (ctl_debug != 0) {
1946 printf("%s invalid kctlref %p\n",
1947 __func__, kctlref);
1948 }
1949 return NULL;
1950 }
1951
1952 kcb = kcb_find(kctl, unit);
1953 if (kcb == NULL || kcb->kctl != kctl || (so = kcb->so) == NULL) {
1954 lck_mtx_unlock(&ctl_mtx);
1955 return NULL;
1956 }
1957 /*
1958 * This prevents the socket from being closed
1959 */
1960 kcb->usecount++;
1961 /*
1962 * Respect lock ordering: socket before ctl_mtx
1963 */
1964 lck_mtx_unlock(&ctl_mtx);
1965
1966 socket_lock(so, 1);
1967 /*
1968 * The socket lock history is more useful if we store
1969 * the address of the caller.
1970 */
1971 i = (so->next_lock_lr + SO_LCKDBG_MAX - 1) % SO_LCKDBG_MAX;
1972 so->lock_lr[i] = lr_saved;
1973
1974 lck_mtx_lock(&ctl_mtx);
1975
1976 if ((kctl = kctl_from_ref(kctlref)) == NULL || kcb->kctl == NULL) {
1977 lck_mtx_unlock(&ctl_mtx);
1978 socket_unlock(so, 1);
1979 so = NULL;
1980 lck_mtx_lock(&ctl_mtx);
1981 } else if (kctlflags != NULL) {
1982 *kctlflags = kctl->flags;
1983 }
1984
1985 kcb->usecount--;
1986 if (kcb->usecount == 0 && kcb->require_clearing_count != 0) {
1987 wakeup((event_t)&kcb->usecount);
1988 }
1989
1990 lck_mtx_unlock(&ctl_mtx);
1991
1992 return so;
1993 }
1994
1995 static void
ctl_post_msg(u_int32_t event_code,u_int32_t id)1996 ctl_post_msg(u_int32_t event_code, u_int32_t id)
1997 {
1998 struct ctl_event_data ctl_ev_data;
1999 struct kev_msg ev_msg;
2000
2001 lck_mtx_assert(&ctl_mtx, LCK_MTX_ASSERT_NOTOWNED);
2002
2003 bzero(&ev_msg, sizeof(struct kev_msg));
2004 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2005
2006 ev_msg.kev_class = KEV_SYSTEM_CLASS;
2007 ev_msg.kev_subclass = KEV_CTL_SUBCLASS;
2008 ev_msg.event_code = event_code;
2009
2010 /* common nke subclass data */
2011 bzero(&ctl_ev_data, sizeof(ctl_ev_data));
2012 ctl_ev_data.ctl_id = id;
2013 ev_msg.dv[0].data_ptr = &ctl_ev_data;
2014 ev_msg.dv[0].data_length = sizeof(ctl_ev_data);
2015
2016 ev_msg.dv[1].data_length = 0;
2017
2018 kev_post_msg(&ev_msg);
2019 }
2020
2021 static int
ctl_lock(struct socket * so,int refcount,void * lr)2022 ctl_lock(struct socket *so, int refcount, void *lr)
2023 {
2024 void *lr_saved;
2025
2026 if (lr == NULL) {
2027 lr_saved = __builtin_return_address(0);
2028 } else {
2029 lr_saved = lr;
2030 }
2031
2032 if (so->so_pcb != NULL) {
2033 lck_mtx_lock(&((struct ctl_cb *)so->so_pcb)->mtx);
2034 } else {
2035 panic("ctl_lock: so=%p NO PCB! lr=%p lrh= %s",
2036 so, lr_saved, solockhistory_nr(so));
2037 /* NOTREACHED */
2038 }
2039
2040 if (so->so_usecount < 0) {
2041 panic("ctl_lock: so=%p so_pcb=%p lr=%p ref=%x lrh= %s",
2042 so, so->so_pcb, lr_saved, so->so_usecount,
2043 solockhistory_nr(so));
2044 /* NOTREACHED */
2045 }
2046
2047 if (refcount) {
2048 so->so_usecount++;
2049 }
2050
2051 so->lock_lr[so->next_lock_lr] = lr_saved;
2052 so->next_lock_lr = (so->next_lock_lr + 1) % SO_LCKDBG_MAX;
2053 return 0;
2054 }
2055
2056 static int
ctl_unlock(struct socket * so,int refcount,void * lr)2057 ctl_unlock(struct socket *so, int refcount, void *lr)
2058 {
2059 void *lr_saved;
2060 lck_mtx_t *mutex_held;
2061
2062 if (lr == NULL) {
2063 lr_saved = __builtin_return_address(0);
2064 } else {
2065 lr_saved = lr;
2066 }
2067
2068 #if (MORE_KCTLLOCK_DEBUG && (DEVELOPMENT || DEBUG))
2069 printf("ctl_unlock: so=%llx sopcb=%x lock=%llx ref=%u lr=%llx\n",
2070 (uint64_t)VM_KERNEL_ADDRPERM(so),
2071 (uint64_t)VM_KERNEL_ADDRPERM(so->so_pcb,
2072 (uint64_t)VM_KERNEL_ADDRPERM(&((struct ctl_cb *)so->so_pcb)->mtx),
2073 so->so_usecount, (uint64_t)VM_KERNEL_ADDRPERM(lr_saved));
2074 #endif /* (MORE_KCTLLOCK_DEBUG && (DEVELOPMENT || DEBUG)) */
2075 if (refcount) {
2076 so->so_usecount--;
2077 }
2078
2079 if (so->so_usecount < 0) {
2080 panic("ctl_unlock: so=%p usecount=%x lrh= %s",
2081 so, so->so_usecount, solockhistory_nr(so));
2082 /* NOTREACHED */
2083 }
2084 if (so->so_pcb == NULL) {
2085 panic("ctl_unlock: so=%p NO PCB usecount=%x lr=%p lrh= %s",
2086 so, so->so_usecount, (void *)lr_saved,
2087 solockhistory_nr(so));
2088 /* NOTREACHED */
2089 }
2090 mutex_held = &((struct ctl_cb *)so->so_pcb)->mtx;
2091
2092 lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
2093 so->unlock_lr[so->next_unlock_lr] = lr_saved;
2094 so->next_unlock_lr = (so->next_unlock_lr + 1) % SO_LCKDBG_MAX;
2095 lck_mtx_unlock(mutex_held);
2096
2097 if (so->so_usecount == 0) {
2098 ctl_sofreelastref(so);
2099 }
2100
2101 return 0;
2102 }
2103
2104 static lck_mtx_t *
2105 ctl_getlock(struct socket *so, int flags)
2106 {
2107 #pragma unused(flags)
2108 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
2109
2110 if (so->so_pcb) {
2111 if (so->so_usecount < 0) {
2112 panic("ctl_getlock: so=%p usecount=%x lrh= %s",
2113 so, so->so_usecount, solockhistory_nr(so));
2114 }
2115 return &kcb->mtx;
2116 } else {
2117 panic("ctl_getlock: so=%p NULL NO so_pcb %s",
2118 so, solockhistory_nr(so));
2119 return so->so_proto->pr_domain->dom_mtx;
2120 }
2121 }
2122
2123 __private_extern__ int
2124 kctl_reg_list SYSCTL_HANDLER_ARGS
2125 {
2126 #pragma unused(oidp, arg1, arg2)
2127 int error = 0;
2128 u_int64_t i, n;
2129 struct xsystmgen xsg;
2130 void *buf = NULL;
2131 struct kctl *kctl;
2132 size_t item_size = ROUNDUP64(sizeof(struct xkctl_reg));
2133
2134 buf = kalloc_data(item_size, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2135
2136 lck_mtx_lock(&ctl_mtx);
2137
2138 n = kctlstat.kcs_reg_count;
2139
2140 if (req->oldptr == USER_ADDR_NULL) {
2141 req->oldidx = (size_t)(n + n / 8) * sizeof(struct xkctl_reg);
2142 goto done;
2143 }
2144 if (req->newptr != USER_ADDR_NULL) {
2145 error = EPERM;
2146 goto done;
2147 }
2148 bzero(&xsg, sizeof(xsg));
2149 xsg.xg_len = sizeof(xsg);
2150 xsg.xg_count = n;
2151 xsg.xg_gen = kctlstat.kcs_gencnt;
2152 xsg.xg_sogen = so_gencnt;
2153 error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
2154 if (error) {
2155 goto done;
2156 }
2157 /*
2158 * We are done if there is no pcb
2159 */
2160 if (n == 0) {
2161 goto done;
2162 }
2163
2164 for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
2165 i < n && kctl != NULL;
2166 i++, kctl = TAILQ_NEXT(kctl, next)) {
2167 struct xkctl_reg *xkr = (struct xkctl_reg *)buf;
2168 struct ctl_cb *kcb;
2169 u_int32_t pcbcount = 0;
2170
2171 TAILQ_FOREACH(kcb, &kctl->kcb_head, next)
2172 pcbcount++;
2173
2174 bzero(buf, item_size);
2175
2176 xkr->xkr_len = sizeof(struct xkctl_reg);
2177 xkr->xkr_kind = XSO_KCREG;
2178 xkr->xkr_id = kctl->id;
2179 xkr->xkr_reg_unit = kctl->reg_unit;
2180 xkr->xkr_flags = kctl->flags;
2181 xkr->xkr_kctlref = (uint64_t)(kctl->kctlref);
2182 xkr->xkr_recvbufsize = kctl->recvbufsize;
2183 xkr->xkr_sendbufsize = kctl->sendbufsize;
2184 xkr->xkr_lastunit = kctl->lastunit;
2185 xkr->xkr_pcbcount = pcbcount;
2186 xkr->xkr_connect = (uint64_t)VM_KERNEL_UNSLIDE(kctl->connect);
2187 xkr->xkr_disconnect =
2188 (uint64_t)VM_KERNEL_UNSLIDE(kctl->disconnect);
2189 xkr->xkr_send = (uint64_t)VM_KERNEL_UNSLIDE(kctl->send);
2190 xkr->xkr_send_list =
2191 (uint64_t)VM_KERNEL_UNSLIDE(kctl->send_list);
2192 xkr->xkr_setopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->setopt);
2193 xkr->xkr_getopt = (uint64_t)VM_KERNEL_UNSLIDE(kctl->getopt);
2194 xkr->xkr_rcvd = (uint64_t)VM_KERNEL_UNSLIDE(kctl->rcvd);
2195 strlcpy(xkr->xkr_name, kctl->name, sizeof(xkr->xkr_name));
2196
2197 error = SYSCTL_OUT(req, buf, item_size);
2198 }
2199
2200 if (error == 0) {
2201 /*
2202 * Give the user an updated idea of our state.
2203 * If the generation differs from what we told
2204 * her before, she knows that something happened
2205 * while we were processing this request, and it
2206 * might be necessary to retry.
2207 */
2208 bzero(&xsg, sizeof(xsg));
2209 xsg.xg_len = sizeof(xsg);
2210 xsg.xg_count = n;
2211 xsg.xg_gen = kctlstat.kcs_gencnt;
2212 xsg.xg_sogen = so_gencnt;
2213 error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
2214 if (error) {
2215 goto done;
2216 }
2217 }
2218
2219 done:
2220 lck_mtx_unlock(&ctl_mtx);
2221
2222 kfree_data(buf, item_size);
2223
2224 return error;
2225 }
2226
2227 __private_extern__ int
2228 kctl_pcblist SYSCTL_HANDLER_ARGS
2229 {
2230 #pragma unused(oidp, arg1, arg2)
2231 int error = 0;
2232 u_int64_t n, i;
2233 struct xsystmgen xsg;
2234 void *buf = NULL;
2235 struct kctl *kctl;
2236 size_t item_size = ROUNDUP64(sizeof(struct xkctlpcb)) +
2237 ROUNDUP64(sizeof(struct xsocket_n)) +
2238 2 * ROUNDUP64(sizeof(struct xsockbuf_n)) +
2239 ROUNDUP64(sizeof(struct xsockstat_n));
2240
2241 buf = kalloc_data(item_size, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2242
2243 lck_mtx_lock(&ctl_mtx);
2244
2245 n = kctlstat.kcs_pcbcount;
2246
2247 if (req->oldptr == USER_ADDR_NULL) {
2248 req->oldidx = (size_t)(n + n / 8) * item_size;
2249 goto done;
2250 }
2251 if (req->newptr != USER_ADDR_NULL) {
2252 error = EPERM;
2253 goto done;
2254 }
2255 bzero(&xsg, sizeof(xsg));
2256 xsg.xg_len = sizeof(xsg);
2257 xsg.xg_count = n;
2258 xsg.xg_gen = kctlstat.kcs_gencnt;
2259 xsg.xg_sogen = so_gencnt;
2260 error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
2261 if (error) {
2262 goto done;
2263 }
2264 /*
2265 * We are done if there is no pcb
2266 */
2267 if (n == 0) {
2268 goto done;
2269 }
2270
2271 for (i = 0, kctl = TAILQ_FIRST(&ctl_head);
2272 i < n && kctl != NULL;
2273 kctl = TAILQ_NEXT(kctl, next)) {
2274 struct ctl_cb *kcb;
2275
2276 for (kcb = TAILQ_FIRST(&kctl->kcb_head);
2277 i < n && kcb != NULL;
2278 i++, kcb = TAILQ_NEXT(kcb, next)) {
2279 struct xkctlpcb *xk = (struct xkctlpcb *)buf;
2280 struct xsocket_n *xso = (struct xsocket_n *)
2281 ADVANCE64(xk, sizeof(*xk));
2282 struct xsockbuf_n *xsbrcv = (struct xsockbuf_n *)
2283 ADVANCE64(xso, sizeof(*xso));
2284 struct xsockbuf_n *xsbsnd = (struct xsockbuf_n *)
2285 ADVANCE64(xsbrcv, sizeof(*xsbrcv));
2286 struct xsockstat_n *xsostats = (struct xsockstat_n *)
2287 ADVANCE64(xsbsnd, sizeof(*xsbsnd));
2288
2289 bzero(buf, item_size);
2290
2291 xk->xkp_len = sizeof(struct xkctlpcb);
2292 xk->xkp_kind = XSO_KCB;
2293 xk->xkp_unit = kcb->sac.sc_unit;
2294 xk->xkp_kctpcb = (uint64_t)VM_KERNEL_ADDRPERM(kcb);
2295 xk->xkp_kctlref = (uint64_t)VM_KERNEL_ADDRPERM(kctl);
2296 xk->xkp_kctlid = kctl->id;
2297 strlcpy(xk->xkp_kctlname, kctl->name,
2298 sizeof(xk->xkp_kctlname));
2299
2300 sotoxsocket_n(kcb->so, xso);
2301 sbtoxsockbuf_n(kcb->so ?
2302 &kcb->so->so_rcv : NULL, xsbrcv);
2303 sbtoxsockbuf_n(kcb->so ?
2304 &kcb->so->so_snd : NULL, xsbsnd);
2305 sbtoxsockstat_n(kcb->so, xsostats);
2306
2307 error = SYSCTL_OUT(req, buf, item_size);
2308 }
2309 }
2310
2311 if (error == 0) {
2312 /*
2313 * Give the user an updated idea of our state.
2314 * If the generation differs from what we told
2315 * her before, she knows that something happened
2316 * while we were processing this request, and it
2317 * might be necessary to retry.
2318 */
2319 bzero(&xsg, sizeof(xsg));
2320 xsg.xg_len = sizeof(xsg);
2321 xsg.xg_count = n;
2322 xsg.xg_gen = kctlstat.kcs_gencnt;
2323 xsg.xg_sogen = so_gencnt;
2324 error = SYSCTL_OUT(req, &xsg, sizeof(xsg));
2325 if (error) {
2326 goto done;
2327 }
2328 }
2329
2330 done:
2331 lck_mtx_unlock(&ctl_mtx);
2332
2333 kfree_data(buf, item_size);
2334 return error;
2335 }
2336
2337 int
2338 kctl_getstat SYSCTL_HANDLER_ARGS
2339 {
2340 #pragma unused(oidp, arg1, arg2)
2341 int error = 0;
2342
2343 lck_mtx_lock(&ctl_mtx);
2344
2345 if (req->newptr != USER_ADDR_NULL) {
2346 error = EPERM;
2347 goto done;
2348 }
2349 if (req->oldptr == USER_ADDR_NULL) {
2350 req->oldidx = sizeof(struct kctlstat);
2351 goto done;
2352 }
2353
2354 error = SYSCTL_OUT(req, &kctlstat,
2355 MIN(sizeof(struct kctlstat), req->oldlen));
2356 done:
2357 lck_mtx_unlock(&ctl_mtx);
2358 return error;
2359 }
2360
2361 void
2362 kctl_fill_socketinfo(struct socket *so, struct socket_info *si)
2363 {
2364 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb;
2365 struct kern_ctl_info *kcsi =
2366 &si->soi_proto.pri_kern_ctl;
2367 struct kctl *kctl = kcb->kctl;
2368
2369 si->soi_kind = SOCKINFO_KERN_CTL;
2370
2371 if (kctl == 0) {
2372 return;
2373 }
2374
2375 kcsi->kcsi_id = kctl->id;
2376 kcsi->kcsi_reg_unit = kctl->reg_unit;
2377 kcsi->kcsi_flags = kctl->flags;
2378 kcsi->kcsi_recvbufsize = kctl->recvbufsize;
2379 kcsi->kcsi_sendbufsize = kctl->sendbufsize;
2380 kcsi->kcsi_unit = kcb->sac.sc_unit;
2381 strlcpy(kcsi->kcsi_name, kctl->name, MAX_KCTL_NAME);
2382 }
2383