]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/kern/kern_newsysctl.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_newsysctl.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2019 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 * Copyright (c) 1982, 1986, 1989, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * This code is derived from software contributed to Berkeley by
33 * Mike Karels at Berkeley Software Design, Inc.
34 *
35 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
36 * project, to make these variables more userfriendly.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
67 */
68
69
70#include <sys/param.h>
71#include <sys/buf.h>
72#include <sys/kernel.h>
73#include <sys/sysctl.h>
74#include <sys/malloc.h>
75#include <sys/proc_internal.h>
76#include <sys/kauth.h>
77#include <sys/systm.h>
78#include <sys/sysproto.h>
79
80#include <security/audit/audit.h>
81#include <pexpert/pexpert.h>
82
83#if CONFIG_MACF
84#include <security/mac_framework.h>
85#endif
86
87#if defined(HAS_APPLE_PAC)
88#include <ptrauth.h>
89#endif /* defined(HAS_APPLE_PAC) */
90
91lck_grp_t * sysctl_lock_group = NULL;
92lck_rw_t * sysctl_geometry_lock = NULL;
93lck_mtx_t * sysctl_unlocked_node_lock = NULL;
94
95/*
96 * Conditionally allow dtrace to see these functions for debugging purposes.
97 */
98#ifdef STATIC
99#undef STATIC
100#endif
101#if 0
102#define STATIC
103#else
104#define STATIC static
105#endif
106
107/* forward declarations of static functions */
108STATIC void sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i);
109STATIC int sysctl_sysctl_debug(struct sysctl_oid *oidp, void *arg1,
110 int arg2, struct sysctl_req *req);
111STATIC int sysctl_sysctl_name(struct sysctl_oid *oidp, void *arg1,
112 int arg2, struct sysctl_req *req);
113STATIC int sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp,
114 int *name, u_int namelen, int *next, int *len, int level,
115 struct sysctl_oid **oidpp);
116STATIC int sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l);
117STATIC int sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l);
118STATIC int name2oid(char *name, int *oid, u_int *len);
119STATIC int sysctl_sysctl_name2oid(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
120STATIC int sysctl_sysctl_next(struct sysctl_oid *oidp, void *arg1, int arg2,
121 struct sysctl_req *req);
122STATIC int sysctl_sysctl_oidfmt(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
123STATIC int sysctl_old_user(struct sysctl_req *req, const void *p, size_t l);
124STATIC int sysctl_new_user(struct sysctl_req *req, void *p, size_t l);
125
126STATIC void sysctl_create_user_req(struct sysctl_req *req, struct proc *p, user_addr_t oldp,
127 size_t oldlen, user_addr_t newp, size_t newlen);
128STATIC int sysctl_root(boolean_t from_kernel, boolean_t string_is_canonical, char *namestring, size_t namestringlen, int *name, u_int namelen, struct sysctl_req *req);
129
130int kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen);
131int kernel_sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
132int userland_sysctl(boolean_t string_is_canonical,
133 char *namestring, size_t namestringlen,
134 int *name, u_int namelen, struct sysctl_req *req,
135 size_t *retval);
136
137struct sysctl_oid_list sysctl__children; /* root list */
138
139/*
140 * Initialization of the MIB tree.
141 *
142 * Order by number in each list.
143 */
144
145void
146sysctl_register_oid(struct sysctl_oid *new_oidp)
147{
148 struct sysctl_oid *oidp = NULL;
149 struct sysctl_oid_list *parent = new_oidp->oid_parent;
150 struct sysctl_oid *p;
151 struct sysctl_oid *q;
152 int n;
153
154 /*
155 * The OID can be old-style (needs copy), new style without an earlier
156 * version (also needs copy), or new style with a matching version (no
157 * copy needed). Later versions are rejected (presumably, the OID
158 * structure was changed for a necessary reason).
159 */
160 if (!(new_oidp->oid_kind & CTLFLAG_OID2)) {
161 /*
162 * XXX: M_TEMP is perhaps not the most apropriate zone, as it
163 * XXX: will subject us to use-after-free by other consumers.
164 */
165 MALLOC(oidp, struct sysctl_oid *, sizeof(*oidp), M_TEMP, M_WAITOK | M_ZERO);
166 if (oidp == NULL) {
167 return; /* reject: no memory */
168 }
169 /*
170 * Copy the structure only through the oid_fmt field, which
171 * is the last field in a non-OID2 OID structure.
172 *
173 * Note: We may want to set the oid_descr to the
174 * oid_name (or "") at some future date.
175 */
176 memcpy(oidp, new_oidp, offsetof(struct sysctl_oid, oid_descr));
177 } else {
178 /* It's a later version; handle the versions we know about */
179 switch (new_oidp->oid_version) {
180 case SYSCTL_OID_VERSION:
181 /* current version */
182 oidp = new_oidp;
183 break;
184 default:
185 return; /* rejects unknown version */
186 }
187 }
188
189 /* Get the write lock to modify the geometry */
190 lck_rw_lock_exclusive(sysctl_geometry_lock);
191
192 /*
193 * If this oid has a number OID_AUTO, give it a number which
194 * is greater than any current oid. Make sure it is at least
195 * OID_AUTO_START to leave space for pre-assigned oid numbers.
196 */
197 if (oidp->oid_number == OID_AUTO) {
198 /* First, find the highest oid in the parent list >OID_AUTO_START-1 */
199 n = OID_AUTO_START;
200 SLIST_FOREACH(p, parent, oid_link) {
201 if (p->oid_number > n) {
202 n = p->oid_number;
203 }
204 }
205 oidp->oid_number = n + 1;
206 /*
207 * Reflect the number in an llocated OID into the template
208 * of the caller for sysctl_unregister_oid() compares.
209 */
210 if (oidp != new_oidp) {
211 new_oidp->oid_number = oidp->oid_number;
212 }
213 }
214
215#if defined(HAS_APPLE_PAC)
216 if (oidp->oid_handler) {
217 /*
218 * Dereference function-pointer-signed oid_handler to prevent an
219 * attacker with the ability to observe the result of the
220 * auth_and_resign below from trying all possible inputs until an auth
221 * succeeds.
222 */
223 if (__builtin_expect(!*(uintptr_t*)ptrauth_auth_data((void*)
224 oidp->oid_handler, ptrauth_key_function_pointer, 0), 0)) {
225 /*
226 * This is necessary to force the dereference but will never
227 * actually be reached, dereferencing an invalidly signed pointer
228 * will trap before getting here (and the codegen is nicer than
229 * with a panic).
230 */
231 __builtin_trap();
232 }
233 /*
234 * Sign oid_handler address-discriminated upon installation to make it
235 * harder to replace with an arbitrary function pointer.
236 */
237 oidp->oid_handler = ptrauth_auth_and_resign(oidp->oid_handler,
238 ptrauth_key_function_pointer, 0, ptrauth_key_function_pointer,
239 ptrauth_blend_discriminator(&oidp->oid_handler,
240 ptrauth_string_discriminator("oid_handler")));
241 }
242#endif /* defined(HAS_APPLE_PAC) */
243
244 /*
245 * Insert the oid into the parent's list in order.
246 */
247 q = NULL;
248 SLIST_FOREACH(p, parent, oid_link) {
249 if (oidp->oid_number == p->oid_number) {
250 panic("attempting to register a sysctl at previously registered slot : %d", oidp->oid_number);
251 } else if (oidp->oid_number < p->oid_number) {
252 break;
253 }
254 q = p;
255 }
256 if (q) {
257 SLIST_INSERT_AFTER(q, oidp, oid_link);
258 } else {
259 SLIST_INSERT_HEAD(parent, oidp, oid_link);
260 }
261
262 /* Release the write lock */
263 lck_rw_unlock_exclusive(sysctl_geometry_lock);
264}
265
266void
267sysctl_unregister_oid(struct sysctl_oid *oidp)
268{
269 struct sysctl_oid *removed_oidp = NULL; /* OID removed from tree */
270 struct sysctl_oid *old_oidp = NULL; /* OID compatibility copy */
271
272 /* Get the write lock to modify the geometry */
273 lck_rw_lock_exclusive(sysctl_geometry_lock);
274
275 if (!(oidp->oid_kind & CTLFLAG_OID2)) {
276 /*
277 * We're using a copy so we can get the new fields in an
278 * old structure, so we have to iterate to compare the
279 * partial structure; when we find a match, we remove it
280 * normally and free the memory.
281 */
282 SLIST_FOREACH(old_oidp, oidp->oid_parent, oid_link) {
283 if (!memcmp(&oidp->oid_number, &old_oidp->oid_number, (offsetof(struct sysctl_oid, oid_descr) - offsetof(struct sysctl_oid, oid_number)))) {
284 break;
285 }
286 }
287 if (old_oidp != NULL) {
288 SLIST_REMOVE(old_oidp->oid_parent, old_oidp, sysctl_oid, oid_link);
289 removed_oidp = old_oidp;
290 }
291 } else {
292 /* It's a later version; handle the versions we know about */
293 switch (oidp->oid_version) {
294 case SYSCTL_OID_VERSION:
295 /* We can just remove the OID directly... */
296 SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link);
297 removed_oidp = oidp;
298 break;
299 default:
300 /* XXX: Can't happen; probably tree coruption.*/
301 break; /* rejects unknown version */
302 }
303 }
304
305#if defined(HAS_APPLE_PAC)
306 if (removed_oidp && removed_oidp->oid_handler && old_oidp == NULL) {
307 /*
308 * Revert address-discriminated signing performed by
309 * sysctl_register_oid() (in case this oid is registered again).
310 */
311 removed_oidp->oid_handler = ptrauth_auth_function(removed_oidp->oid_handler,
312 ptrauth_key_function_pointer,
313 ptrauth_blend_discriminator(&removed_oidp->oid_handler,
314 ptrauth_string_discriminator("oid_handler")));
315 /*
316 * Dereference the function-pointer-signed result to prevent an
317 * attacker with the ability to observe the result of the
318 * auth_and_resign above from trying all possible inputs until an auth
319 * succeeds.
320 */
321 if (__builtin_expect(!*(uintptr_t*)ptrauth_auth_data((void*)
322 removed_oidp->oid_handler, ptrauth_key_function_pointer, 0), 0)) {
323 /*
324 * This is necessary to force the dereference but will never
325 * actually be reached, dereferencing an invalidly signed pointer
326 * will trap before getting here (and the codegen is nicer than
327 * with a panic).
328 */
329 __builtin_trap();
330 }
331 }
332#endif /* defined(HAS_APPLE_PAC) */
333
334 /*
335 * We've removed it from the list at this point, but we don't want
336 * to return to the caller until all handler references have drained
337 * out. Doing things in this order prevent other people coming in
338 * and starting new operations against the OID node we want removed.
339 *
340 * Note: oidp could be NULL if it wasn't found.
341 */
342 while (removed_oidp && removed_oidp->oid_refcnt) {
343 lck_rw_sleep(sysctl_geometry_lock, LCK_SLEEP_EXCLUSIVE, &removed_oidp->oid_refcnt, THREAD_UNINT);
344 }
345
346 /* Release the write lock */
347 lck_rw_unlock_exclusive(sysctl_geometry_lock);
348
349 /* If it was allocated, free it after dropping the lock */
350 if (old_oidp != NULL) {
351 FREE(old_oidp, M_TEMP);
352 }
353}
354
355/*
356 * Bulk-register all the oids in a linker_set.
357 */
358void
359sysctl_register_set(const char *set)
360{
361 struct sysctl_oid **oidpp, *oidp;
362
363 LINKER_SET_FOREACH(oidpp, struct sysctl_oid **, set) {
364 oidp = *oidpp;
365 if (!(oidp->oid_kind & CTLFLAG_NOAUTO)) {
366 sysctl_register_oid(oidp);
367 }
368 }
369}
370
371void
372sysctl_unregister_set(const char *set)
373{
374 struct sysctl_oid **oidpp, *oidp;
375
376 LINKER_SET_FOREACH(oidpp, struct sysctl_oid **, set) {
377 oidp = *oidpp;
378 if (!(oidp->oid_kind & CTLFLAG_NOAUTO)) {
379 sysctl_unregister_oid(oidp);
380 }
381 }
382}
383
384/*
385 * Exported in BSDKernel.exports, kept for binary compatibility
386 */
387#if defined(__x86_64__)
388void
389sysctl_register_fixed(void)
390{
391}
392#endif
393
394/*
395 * Register the kernel's oids on startup.
396 */
397
398void
399sysctl_early_init(void)
400{
401 /*
402 * Initialize the geometry lock for reading/modifying the
403 * sysctl tree. This is done here because IOKit registers
404 * some sysctl's before bsd_init() would otherwise perform
405 * subsystem initialization.
406 */
407
408 sysctl_lock_group = lck_grp_alloc_init("sysctl", NULL);
409 sysctl_geometry_lock = lck_rw_alloc_init(sysctl_lock_group, NULL);
410 sysctl_unlocked_node_lock = lck_mtx_alloc_init(sysctl_lock_group, NULL);
411
412 sysctl_register_set("__sysctl_set");
413 sysctl_load_devicetree_entries();
414}
415
416/*
417 * New handler interface
418 * If the sysctl caller (user mode or kernel mode) is interested in the
419 * value (req->oldptr != NULL), we copy the data (bigValue etc.) out,
420 * if the caller wants to set the value (req->newptr), we copy
421 * the data in (*pValue etc.).
422 */
423
424int
425sysctl_io_number(struct sysctl_req *req, long long bigValue, size_t valueSize, void *pValue, int *changed)
426{
427 int smallValue;
428 int error;
429
430 if (changed) {
431 *changed = 0;
432 }
433
434 /*
435 * Handle the various combinations of caller buffer size and
436 * data value size. We are generous in the case where the
437 * caller has specified a 32-bit buffer but the value is 64-bit
438 * sized.
439 */
440
441 /* 32 bit value expected or 32 bit buffer offered */
442 if (((valueSize == sizeof(int)) ||
443 ((req->oldlen == sizeof(int)) && (valueSize == sizeof(long long))))
444 && (req->oldptr)) {
445 smallValue = (int)bigValue;
446 if ((long long)smallValue != bigValue) {
447 return ERANGE;
448 }
449 error = SYSCTL_OUT(req, &smallValue, sizeof(smallValue));
450 } else {
451 /* any other case is either size-equal or a bug */
452 error = SYSCTL_OUT(req, &bigValue, valueSize);
453 }
454 /* error or nothing to set */
455 if (error || !req->newptr) {
456 return error;
457 }
458
459 /* set request for constant */
460 if (pValue == NULL) {
461 return EPERM;
462 }
463
464 /* set request needs to convert? */
465 if ((req->newlen == sizeof(int)) && (valueSize == sizeof(long long))) {
466 /* new value is 32 bits, upconvert to 64 bits */
467 error = SYSCTL_IN(req, &smallValue, sizeof(smallValue));
468 if (!error) {
469 *(long long *)pValue = (long long)smallValue;
470 }
471 } else if ((req->newlen == sizeof(long long)) && (valueSize == sizeof(int))) {
472 /* new value is 64 bits, downconvert to 32 bits and range check */
473 error = SYSCTL_IN(req, &bigValue, sizeof(bigValue));
474 if (!error) {
475 smallValue = (int)bigValue;
476 if ((long long)smallValue != bigValue) {
477 return ERANGE;
478 }
479 *(int *)pValue = smallValue;
480 }
481 } else {
482 /* sizes match, just copy in */
483 error = SYSCTL_IN(req, pValue, valueSize);
484 }
485 if (!error && changed) {
486 *changed = 1;
487 }
488 return error;
489}
490
491int
492sysctl_io_string(struct sysctl_req *req, char *pValue, size_t valueSize, int trunc, int *changed)
493{
494 int error;
495
496 if (changed) {
497 *changed = 0;
498 }
499
500 if (trunc && req->oldptr && req->oldlen && (req->oldlen < strlen(pValue) + 1)) {
501 /* If trunc != 0, if you give it a too small (but larger than
502 * 0 bytes) buffer, instead of returning ENOMEM, it truncates the
503 * returned string to the buffer size. This preserves the semantics
504 * of some library routines implemented via sysctl, which truncate
505 * their returned data, rather than simply returning an error. The
506 * returned string is always nul (ascii '\0') terminated. */
507 error = SYSCTL_OUT(req, pValue, req->oldlen - 1);
508 if (!error) {
509 char c = '\0';
510 error = SYSCTL_OUT(req, &c, 1);
511 }
512 } else {
513 /* Copy string out */
514 error = SYSCTL_OUT(req, pValue, strlen(pValue) + 1);
515 }
516
517 /* error or no new value */
518 if (error || !req->newptr) {
519 return error;
520 }
521
522 /* attempt to set read-only value */
523 if (valueSize == 0) {
524 return EPERM;
525 }
526
527 /* make sure there's room for the new string */
528 if (req->newlen >= valueSize) {
529 return EINVAL;
530 }
531
532 /* copy the string in and force nul termination */
533 error = SYSCTL_IN(req, pValue, req->newlen);
534 pValue[req->newlen] = '\0';
535
536 if (!error && changed) {
537 *changed = 1;
538 }
539 return error;
540}
541
542int
543sysctl_io_opaque(struct sysctl_req *req, void *pValue, size_t valueSize, int *changed)
544{
545 int error;
546
547 if (changed) {
548 *changed = 0;
549 }
550
551 /* Copy blob out */
552 error = SYSCTL_OUT(req, pValue, valueSize);
553
554 /* error or nothing to set */
555 if (error || !req->newptr) {
556 return error;
557 }
558
559 error = SYSCTL_IN(req, pValue, valueSize);
560
561 if (!error && changed) {
562 *changed = 1;
563 }
564 return error;
565}
566
567/*
568 * "Staff-functions"
569 *
570 * These functions implement a presently undocumented interface
571 * used by the sysctl program to walk the tree, and get the type
572 * so it can print the value.
573 * This interface is under work and consideration, and should probably
574 * be killed with a big axe by the first person who can find the time.
575 * (be aware though, that the proper interface isn't as obvious as it
576 * may seem, there are various conflicting requirements.
577 *
578 * {0,0} printf the entire MIB-tree.
579 * {0,1,...} return the name of the "..." OID.
580 * {0,2,...} return the next OID.
581 * {0,3} return the OID of the name in "new"
582 * {0,4,...} return the kind & format info for the "..." OID.
583 */
584
585/*
586 * sysctl_sysctl_debug_dump_node
587 *
588 * Description: Dump debug information for a given sysctl_oid_list at the
589 * given oid depth out to the kernel log, via printf
590 *
591 * Parameters: l sysctl_oid_list pointer
592 * i current node depth
593 *
594 * Returns: (void)
595 *
596 * Implicit: kernel log, modified
597 *
598 * Locks: Assumes sysctl_geometry_lock is held prior to calling
599 *
600 * Notes: This function may call itself recursively to resolve Node
601 * values, which potentially have an inferioer sysctl_oid_list
602 *
603 * This function is only callable indirectly via the function
604 * sysctl_sysctl_debug()
605 *
606 * Bugs: The node depth indentation does not work; this may be an
607 * artifact of leading space removal by the log daemon itself
608 * or some intermediate routine.
609 */
610STATIC void
611sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
612{
613 int k;
614 struct sysctl_oid *oidp;
615
616 SLIST_FOREACH(oidp, l, oid_link) {
617 for (k = 0; k < i; k++) {
618 printf(" ");
619 }
620
621 printf("%d %s ", oidp->oid_number, oidp->oid_name);
622
623 printf("%c%c%c",
624 oidp->oid_kind & CTLFLAG_LOCKED ? 'L':' ',
625 oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
626 oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
627
628 if (oidp->oid_handler) {
629 printf(" *Handler");
630 }
631
632 switch (oidp->oid_kind & CTLTYPE) {
633 case CTLTYPE_NODE:
634 printf(" Node\n");
635 if (!oidp->oid_handler) {
636 sysctl_sysctl_debug_dump_node(
637 oidp->oid_arg1, i + 2);
638 }
639 break;
640 case CTLTYPE_INT: printf(" Int\n"); break;
641 case CTLTYPE_STRING: printf(" String\n"); break;
642 case CTLTYPE_QUAD: printf(" Quad\n"); break;
643 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
644 default: printf("\n");
645 }
646 }
647}
648
649/*
650 * sysctl_sysctl_debug
651 *
652 * Description: This function implements the "sysctl.debug" portion of the
653 * OID space for sysctl.
654 *
655 * OID: 0, 0
656 *
657 * Parameters: __unused
658 *
659 * Returns: ENOENT
660 *
661 * Implicit: kernel log, modified
662 *
663 * Locks: Acquires and then releases a read lock on the
664 * sysctl_geometry_lock
665 */
666STATIC int
667sysctl_sysctl_debug(__unused struct sysctl_oid *oidp, __unused void *arg1,
668 __unused int arg2, __unused struct sysctl_req *req)
669{
670 lck_rw_lock_shared(sysctl_geometry_lock);
671 sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
672 lck_rw_done(sysctl_geometry_lock);
673 return ENOENT;
674}
675
676SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED,
677 0, 0, sysctl_sysctl_debug, "-", "");
678
679/*
680 * sysctl_sysctl_name
681 *
682 * Description: Convert an OID into a string name; this is used by the user
683 * space sysctl() command line utility; this is done in a purely
684 * advisory capacity (e.g. to provide node names for "sysctl -A"
685 * output).
686 *
687 * OID: 0, 1
688 *
689 * Parameters: oidp __unused
690 * arg1 A pointer to the OID name list
691 * integer array, beginning at
692 * adjusted option base 2
693 * arg2 The number of elements which
694 * remain in the name array
695 *
696 * Returns: 0 Success
697 * SYSCTL_OUT:EPERM Permission denied
698 * SYSCTL_OUT:EFAULT Bad user supplied buffer
699 * SYSCTL_OUT:??? Return value from user function
700 * for SYSCTL_PROC leaf node
701 *
702 * Implict: Contents of user request buffer, modified
703 *
704 * Locks: Acquires and then releases a read lock on the
705 * sysctl_geometry_lock
706 *
707 * Notes: SPI (System Programming Interface); this is subject to change
708 * and may not be relied upon by third party applications; use
709 * a subprocess to communicate with the "sysctl" command line
710 * command instead, if you believe you need this functionality.
711 * Preferrably, use sysctlbyname() instead.
712 *
713 * Setting of the NULL termination of the output string is
714 * delayed until after the geometry lock is dropped. If there
715 * are no Entries remaining in the OID name list when this
716 * function is called, it will still write out the termination
717 * byte.
718 *
719 * This function differs from other sysctl functions in that
720 * it can not take an output buffer length of 0 to determine the
721 * space which will be required. It is suggested that the buffer
722 * length be PATH_MAX, and that authors of new sysctl's refrain
723 * from exceeding this string length.
724 */
725STATIC int
726sysctl_sysctl_name(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
727 struct sysctl_req *req)
728{
729 int *name = (int *) arg1;
730 u_int namelen = arg2;
731 int error = 0;
732 struct sysctl_oid *oid;
733 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
734 char tempbuf[10] = {};
735
736 lck_rw_lock_shared(sysctl_geometry_lock);
737 while (namelen) {
738 if (!lsp) {
739 snprintf(tempbuf, sizeof(tempbuf), "%d", *name);
740 if (req->oldidx) {
741 error = SYSCTL_OUT(req, ".", 1);
742 }
743 if (!error) {
744 error = SYSCTL_OUT(req, tempbuf, strlen(tempbuf));
745 }
746 if (error) {
747 lck_rw_done(sysctl_geometry_lock);
748 return error;
749 }
750 namelen--;
751 name++;
752 continue;
753 }
754 lsp2 = 0;
755 SLIST_FOREACH(oid, lsp, oid_link) {
756 if (oid->oid_number != *name) {
757 continue;
758 }
759
760 if (req->oldidx) {
761 error = SYSCTL_OUT(req, ".", 1);
762 }
763 if (!error) {
764 error = SYSCTL_OUT(req, oid->oid_name,
765 strlen(oid->oid_name));
766 }
767 if (error) {
768 lck_rw_done(sysctl_geometry_lock);
769 return error;
770 }
771
772 namelen--;
773 name++;
774
775 if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
776 break;
777 }
778
779 if (oid->oid_handler) {
780 break;
781 }
782
783 lsp2 = (struct sysctl_oid_list *)oid->oid_arg1;
784 break;
785 }
786 lsp = lsp2;
787 }
788 lck_rw_done(sysctl_geometry_lock);
789 return SYSCTL_OUT(req, "", 1);
790}
791
792SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD | CTLFLAG_LOCKED, sysctl_sysctl_name, "");
793
794/*
795 * sysctl_sysctl_next_ls
796 *
797 * Description: For a given OID name value, return the next consecutive OID
798 * name value within the geometry tree
799 *
800 * Parameters: lsp The OID list to look in
801 * name The OID name to start from
802 * namelen The length of the OID name
803 * next Pointer to new oid storage to
804 * fill in
805 * len Pointer to receive new OID
806 * length value of storage written
807 * level OID tree depth (used to compute
808 * len value)
809 * oidpp Pointer to OID list entry
810 * pointer; used to walk the list
811 * forward across recursion
812 *
813 * Returns: 0 Returning a new entry
814 * 1 End of geometry list reached
815 *
816 * Implicit: *next Modified to contain the new OID
817 * *len Modified to contain new length
818 *
819 * Locks: Assumes sysctl_geometry_lock is held prior to calling
820 *
821 * Notes: This function will not return OID values that have special
822 * handlers, since we can not tell wheter these handlers consume
823 * elements from the OID space as parameters. For this reason,
824 * we STRONGLY discourage these types of handlers
825 */
826STATIC int
827sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
828 int *next, int *len, int level, struct sysctl_oid **oidpp)
829{
830 struct sysctl_oid *oidp;
831
832 *len = level;
833 SLIST_FOREACH(oidp, lsp, oid_link) {
834 *next = oidp->oid_number;
835 *oidpp = oidp;
836
837 if (!namelen) {
838 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
839 return 0;
840 }
841 if (oidp->oid_handler) {
842 /* We really should call the handler here...*/
843 return 0;
844 }
845 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
846
847 if (!SLIST_FIRST(lsp)) {
848 /* This node had no children - skip it! */
849 continue;
850 }
851
852 if (!sysctl_sysctl_next_ls(lsp, 0, 0, next + 1,
853 len, level + 1, oidpp)) {
854 return 0;
855 }
856 goto next;
857 }
858
859 if (oidp->oid_number < *name) {
860 continue;
861 }
862
863 if (oidp->oid_number > *name) {
864 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
865 return 0;
866 }
867 if (oidp->oid_handler) {
868 return 0;
869 }
870 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
871 if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1,
872 next + 1, len, level + 1, oidpp)) {
873 return 0;
874 }
875 goto next;
876 }
877 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
878 continue;
879 }
880
881 if (oidp->oid_handler) {
882 continue;
883 }
884
885 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
886 if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1, next + 1,
887 len, level + 1, oidpp)) {
888 return 0;
889 }
890next:
891 namelen = 1;
892 *len = level;
893 }
894 return 1;
895}
896
897/*
898 * sysctl_sysctl_next
899 *
900 * Description: This is an iterator function designed to iterate the oid tree
901 * and provide a list of OIDs for use by the user space "sysctl"
902 * command line tool
903 *
904 * OID: 0, 2
905 *
906 * Parameters: oidp __unused
907 * arg1 Pointer to start OID name
908 * arg2 Start OID name length
909 * req Pointer to user request buffer
910 *
911 * Returns: 0 Success
912 * ENOENT Reached end of OID space
913 * SYSCTL_OUT:EPERM Permission denied
914 * SYSCTL_OUT:EFAULT Bad user supplied buffer
915 * SYSCTL_OUT:??? Return value from user function
916 * for SYSCTL_PROC leaf node
917 *
918 * Implict: Contents of user request buffer, modified
919 *
920 * Locks: Acquires and then releases a read lock on the
921 * sysctl_geometry_lock
922 *
923 * Notes: SPI (System Programming Interface); this is subject to change
924 * and may not be relied upon by third party applications; use
925 * a subprocess to communicate with the "sysctl" command line
926 * command instead, if you believe you need this functionality.
927 * Preferrably, use sysctlbyname() instead.
928 *
929 * This function differs from other sysctl functions in that
930 * it can not take an output buffer length of 0 to determine the
931 * space which will be required. It is suggested that the buffer
932 * length be PATH_MAX, and that authors of new sysctl's refrain
933 * from exceeding this string length.
934 */
935STATIC int
936sysctl_sysctl_next(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
937 struct sysctl_req *req)
938{
939 int *name = (int *) arg1;
940 u_int namelen = arg2;
941 int i, j, error;
942 struct sysctl_oid *oid;
943 struct sysctl_oid_list *lsp = &sysctl__children;
944 int newoid[CTL_MAXNAME] = {};
945
946 lck_rw_lock_shared(sysctl_geometry_lock);
947 i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
948 lck_rw_done(sysctl_geometry_lock);
949 if (i) {
950 return ENOENT;
951 }
952 error = SYSCTL_OUT(req, newoid, j * sizeof(int));
953 return error;
954}
955
956SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_LOCKED, sysctl_sysctl_next, "");
957
958/*
959 * name2oid
960 *
961 * Description: Support function for use by sysctl_sysctl_name2oid(); looks
962 * up an OID name given a string name.
963 *
964 * Parameters: name NULL terminated string name
965 * oid Pointer to receive OID name
966 * len Pointer to receive OID length
967 * pointer value (see "Notes")
968 *
969 * Returns: 0 Success
970 * ENOENT Entry not found
971 *
972 * Implicit: *oid Modified to contain OID value
973 * *len Modified to contain OID length
974 *
975 * Locks: Assumes sysctl_geometry_lock is held prior to calling
976 */
977STATIC int
978name2oid(char *name, int *oid, u_int *len)
979{
980 int i;
981 struct sysctl_oid *oidp;
982 struct sysctl_oid_list *lsp = &sysctl__children;
983 char *p;
984
985 if (!*name) {
986 return ENOENT;
987 }
988
989 p = name + strlen(name) - 1;
990 if (*p == '.') {
991 *p = '\0';
992 }
993
994 *len = 0;
995
996 for (p = name; *p && *p != '.'; p++) {
997 ;
998 }
999 i = *p;
1000 if (i == '.') {
1001 *p = '\0';
1002 }
1003
1004 oidp = SLIST_FIRST(lsp);
1005
1006 while (oidp && *len < CTL_MAXNAME) {
1007 if (strcmp(name, oidp->oid_name)) {
1008 oidp = SLIST_NEXT(oidp, oid_link);
1009 continue;
1010 }
1011 *oid++ = oidp->oid_number;
1012 (*len)++;
1013
1014 if (!i) {
1015 return 0;
1016 }
1017
1018 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
1019 break;
1020 }
1021
1022 if (oidp->oid_handler) {
1023 break;
1024 }
1025
1026 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
1027 oidp = SLIST_FIRST(lsp);
1028 *p = i; /* restore */
1029 name = p + 1;
1030 for (p = name; *p && *p != '.'; p++) {
1031 ;
1032 }
1033 i = *p;
1034 if (i == '.') {
1035 *p = '\0';
1036 }
1037 }
1038 return ENOENT;
1039}
1040
1041/*
1042 * sysctl_sysctl_name2oid
1043 *
1044 * Description: Translate a string name to an OID name value; this is used by
1045 * the sysctlbyname() function as well as by the "sysctl" command
1046 * line command.
1047 *
1048 * OID: 0, 3
1049 *
1050 * Parameters: oidp __unused
1051 * arg1 __unused
1052 * arg2 __unused
1053 * req Request structure
1054 *
1055 * Returns: ENOENT Input length too short
1056 * ENAMETOOLONG Input length too long
1057 * ENOMEM Could not allocate work area
1058 * SYSCTL_IN/OUT:EPERM Permission denied
1059 * SYSCTL_IN/OUT:EFAULT Bad user supplied buffer
1060 * SYSCTL_IN/OUT:??? Return value from user function
1061 * name2oid:ENOENT Not found
1062 *
1063 * Implicit: *req Contents of request, modified
1064 *
1065 * Locks: Acquires and then releases a read lock on the
1066 * sysctl_geometry_lock
1067 *
1068 * Notes: SPI (System Programming Interface); this is subject to change
1069 * and may not be relied upon by third party applications; use
1070 * a subprocess to communicate with the "sysctl" command line
1071 * command instead, if you believe you need this functionality.
1072 * Preferrably, use sysctlbyname() instead.
1073 *
1074 * This function differs from other sysctl functions in that
1075 * it can not take an output buffer length of 0 to determine the
1076 * space which will be required. It is suggested that the buffer
1077 * length be PATH_MAX, and that authors of new sysctl's refrain
1078 * from exceeding this string length.
1079 */
1080STATIC int
1081sysctl_sysctl_name2oid(__unused struct sysctl_oid *oidp, __unused void *arg1,
1082 __unused int arg2, struct sysctl_req *req)
1083{
1084 char *p;
1085 int error, oid[CTL_MAXNAME] = {};
1086 u_int len = 0; /* set by name2oid() */
1087
1088 if (req->newlen < 1) {
1089 return ENOENT;
1090 }
1091 if (req->newlen >= MAXPATHLEN) { /* XXX arbitrary, undocumented */
1092 return ENAMETOOLONG;
1093 }
1094
1095 MALLOC(p, char *, req->newlen + 1, M_TEMP, M_WAITOK);
1096 if (!p) {
1097 return ENOMEM;
1098 }
1099
1100 error = SYSCTL_IN(req, p, req->newlen);
1101 if (error) {
1102 FREE(p, M_TEMP);
1103 return error;
1104 }
1105
1106 p[req->newlen] = '\0';
1107
1108 /*
1109 * Note: We acquire and release the geometry lock here to
1110 * avoid making name2oid needlessly complex.
1111 */
1112 lck_rw_lock_shared(sysctl_geometry_lock);
1113 error = name2oid(p, oid, &len);
1114 lck_rw_done(sysctl_geometry_lock);
1115
1116 FREE(p, M_TEMP);
1117
1118 if (error) {
1119 return error;
1120 }
1121
1122 error = SYSCTL_OUT(req, oid, len * sizeof *oid);
1123 return error;
1124}
1125
1126SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_KERN | CTLFLAG_LOCKED, 0, 0,
1127 sysctl_sysctl_name2oid, "I", "");
1128
1129/*
1130 * sysctl_sysctl_oidfmt
1131 *
1132 * Description: For a given OID name, determine the format of the data which
1133 * is associated with it. This is used by the "sysctl" command
1134 * line command.
1135 *
1136 * OID: 0, 4
1137 *
1138 * Parameters: oidp __unused
1139 * arg1 The OID name to look up
1140 * arg2 The length of the OID name
1141 * req Pointer to user request buffer
1142 *
1143 * Returns: 0 Success
1144 * EISDIR Malformed request
1145 * ENOENT No such OID name
1146 * SYSCTL_OUT:EPERM Permission denied
1147 * SYSCTL_OUT:EFAULT Bad user supplied buffer
1148 * SYSCTL_OUT:??? Return value from user function
1149 *
1150 * Implict: Contents of user request buffer, modified
1151 *
1152 * Locks: Acquires and then releases a read lock on the
1153 * sysctl_geometry_lock
1154 *
1155 * Notes: SPI (System Programming Interface); this is subject to change
1156 * and may not be relied upon by third party applications; use
1157 * a subprocess to communicate with the "sysctl" command line
1158 * command instead, if you believe you need this functionality.
1159 *
1160 * This function differs from other sysctl functions in that
1161 * it can not take an output buffer length of 0 to determine the
1162 * space which will be required. It is suggested that the buffer
1163 * length be PATH_MAX, and that authors of new sysctl's refrain
1164 * from exceeding this string length.
1165 */
1166STATIC int
1167sysctl_sysctl_oidfmt(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
1168 struct sysctl_req *req)
1169{
1170 int *name = (int *) arg1;
1171 int error = ENOENT; /* default error: not found */
1172 u_int namelen = arg2;
1173 u_int indx;
1174 struct sysctl_oid *oid;
1175 struct sysctl_oid_list *lsp = &sysctl__children;
1176
1177 lck_rw_lock_shared(sysctl_geometry_lock);
1178 oid = SLIST_FIRST(lsp);
1179
1180 indx = 0;
1181 while (oid && indx < CTL_MAXNAME) {
1182 if (oid->oid_number == name[indx]) {
1183 indx++;
1184 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1185 if (oid->oid_handler) {
1186 goto found;
1187 }
1188 if (indx == namelen) {
1189 goto found;
1190 }
1191 lsp = (struct sysctl_oid_list *)oid->oid_arg1;
1192 oid = SLIST_FIRST(lsp);
1193 } else {
1194 if (indx != namelen) {
1195 error = EISDIR;
1196 goto err;
1197 }
1198 goto found;
1199 }
1200 } else {
1201 oid = SLIST_NEXT(oid, oid_link);
1202 }
1203 }
1204 /* Not found */
1205 goto err;
1206
1207found:
1208 if (!oid->oid_fmt) {
1209 goto err;
1210 }
1211 error = SYSCTL_OUT(req,
1212 &oid->oid_kind, sizeof(oid->oid_kind));
1213 if (!error) {
1214 error = SYSCTL_OUT(req, oid->oid_fmt,
1215 strlen(oid->oid_fmt) + 1);
1216 }
1217err:
1218 lck_rw_done(sysctl_geometry_lock);
1219 return error;
1220}
1221
1222SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD | CTLFLAG_LOCKED, sysctl_sysctl_oidfmt, "");
1223
1224
1225/*
1226 * Default "handler" functions.
1227 */
1228
1229/*
1230 * Handle an int, signed or unsigned.
1231 * Two cases:
1232 * a variable: point arg1 at it.
1233 * a constant: pass it in arg2.
1234 */
1235
1236int
1237sysctl_handle_int(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
1238 struct sysctl_req *req)
1239{
1240 return sysctl_io_number(req, arg1? *(int*)arg1: arg2, sizeof(int), arg1, NULL);
1241}
1242
1243/*
1244 * Handle a long, signed or unsigned. arg1 points to it.
1245 */
1246
1247int
1248sysctl_handle_long(__unused struct sysctl_oid *oidp, void *arg1,
1249 __unused int arg2, struct sysctl_req *req)
1250{
1251 if (!arg1) {
1252 return EINVAL;
1253 }
1254 return sysctl_io_number(req, *(long*)arg1, sizeof(long), arg1, NULL);
1255}
1256
1257/*
1258 * Handle a quad, signed or unsigned. arg1 points to it.
1259 */
1260
1261int
1262sysctl_handle_quad(__unused struct sysctl_oid *oidp, void *arg1,
1263 __unused int arg2, struct sysctl_req *req)
1264{
1265 if (!arg1) {
1266 return EINVAL;
1267 }
1268 return sysctl_io_number(req, *(long long*)arg1, sizeof(long long), arg1, NULL);
1269}
1270
1271/*
1272 * Expose an int value as a quad.
1273 *
1274 * This interface allows us to support interfaces defined
1275 * as using quad values while the implementation is still
1276 * using ints.
1277 */
1278int
1279sysctl_handle_int2quad(__unused struct sysctl_oid *oidp, void *arg1,
1280 __unused int arg2, struct sysctl_req *req)
1281{
1282 int error = 0;
1283 long long val;
1284 int newval;
1285
1286 if (!arg1) {
1287 return EINVAL;
1288 }
1289 val = (long long)*(int *)arg1;
1290 error = SYSCTL_OUT(req, &val, sizeof(long long));
1291
1292 if (error || !req->newptr) {
1293 return error;
1294 }
1295
1296 error = SYSCTL_IN(req, &val, sizeof(long long));
1297 if (!error) {
1298 /*
1299 * Value must be representable; check by
1300 * casting and then casting back.
1301 */
1302 newval = (int)val;
1303 if ((long long)newval != val) {
1304 error = ERANGE;
1305 } else {
1306 *(int *)arg1 = newval;
1307 }
1308 }
1309 return error;
1310}
1311
1312/*
1313 * Handle our generic '\0' terminated 'C' string.
1314 * Two cases:
1315 * a variable string: point arg1 at it, arg2 is max length.
1316 * a constant string: point arg1 at it, arg2 is zero.
1317 */
1318
1319int
1320sysctl_handle_string( __unused struct sysctl_oid *oidp, void *arg1, int arg2,
1321 struct sysctl_req *req)
1322{
1323 return sysctl_io_string(req, arg1, arg2, 0, NULL);
1324}
1325
1326/*
1327 * Handle any kind of opaque data.
1328 * arg1 points to it, arg2 is the size.
1329 */
1330
1331int
1332sysctl_handle_opaque(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
1333 struct sysctl_req *req)
1334{
1335 return sysctl_io_opaque(req, arg1, arg2, NULL);
1336}
1337
1338/*
1339 * Transfer functions to/from kernel space.
1340 */
1341STATIC int
1342sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
1343{
1344 size_t i = 0;
1345
1346 if (req->oldptr) {
1347 i = l;
1348 if (i > req->oldlen - req->oldidx) {
1349 i = req->oldlen - req->oldidx;
1350 }
1351 if (i > 0) {
1352 bcopy((const void*)p, CAST_DOWN(char *, (req->oldptr + req->oldidx)), i);
1353 }
1354 }
1355 req->oldidx += l;
1356 if (req->oldptr && i != l) {
1357 return ENOMEM;
1358 }
1359 return 0;
1360}
1361
1362STATIC int
1363sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
1364{
1365 if (!req->newptr) {
1366 return 0;
1367 }
1368 if (req->newlen - req->newidx < l) {
1369 return EINVAL;
1370 }
1371 bcopy(CAST_DOWN(char *, (req->newptr + req->newidx)), p, l);
1372 req->newidx += l;
1373 return 0;
1374}
1375
1376int
1377kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen)
1378{
1379 int error = 0;
1380 struct sysctl_req req;
1381
1382 /*
1383 * Construct request.
1384 */
1385 bzero(&req, sizeof req);
1386 req.p = p;
1387 if (oldlenp) {
1388 req.oldlen = *oldlenp;
1389 }
1390 if (old) {
1391 req.oldptr = CAST_USER_ADDR_T(old);
1392 }
1393 if (newlen) {
1394 req.newlen = newlen;
1395 req.newptr = CAST_USER_ADDR_T(new);
1396 }
1397 req.oldfunc = sysctl_old_kernel;
1398 req.newfunc = sysctl_new_kernel;
1399 req.lock = 1;
1400
1401 /* make the request */
1402 error = sysctl_root(TRUE, FALSE, NULL, 0, name, namelen, &req);
1403
1404 if (error && error != ENOMEM) {
1405 return error;
1406 }
1407
1408 if (oldlenp) {
1409 *oldlenp = req.oldidx;
1410 }
1411
1412 return error;
1413}
1414
1415/*
1416 * Transfer function to/from user space.
1417 */
1418STATIC int
1419sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
1420{
1421 int error = 0;
1422 size_t i = 0;
1423
1424 if (req->oldptr) {
1425 if (req->oldlen - req->oldidx < l) {
1426 return ENOMEM;
1427 }
1428 i = l;
1429 if (i > req->oldlen - req->oldidx) {
1430 i = req->oldlen - req->oldidx;
1431 }
1432 if (i > 0) {
1433 error = copyout((const void*)p, (req->oldptr + req->oldidx), i);
1434 }
1435 }
1436 req->oldidx += l;
1437 if (error) {
1438 return error;
1439 }
1440 if (req->oldptr && i < l) {
1441 return ENOMEM;
1442 }
1443 return 0;
1444}
1445
1446STATIC int
1447sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
1448{
1449 int error;
1450
1451 if (!req->newptr) {
1452 return 0;
1453 }
1454 if (req->newlen - req->newidx < l) {
1455 return EINVAL;
1456 }
1457 error = copyin((req->newptr + req->newidx), p, l);
1458 req->newidx += l;
1459 return error;
1460}
1461
1462/*
1463 * Traverse our tree, and find the right node, execute whatever it points
1464 * at, and return the resulting error code.
1465 */
1466
1467int
1468sysctl_root(boolean_t from_kernel, boolean_t string_is_canonical, char *namestring, size_t namestringlen, int *name, u_int namelen, struct sysctl_req *req)
1469{
1470 u_int indx;
1471 int i;
1472 struct sysctl_oid *oid;
1473 struct sysctl_oid_list *lsp = &sysctl__children;
1474 sysctl_handler_t oid_handler = NULL;
1475 int error;
1476 boolean_t unlocked_node_found = FALSE;
1477 boolean_t namestring_started = FALSE;
1478
1479 /* Get the read lock on the geometry */
1480 lck_rw_lock_shared(sysctl_geometry_lock);
1481
1482 if (string_is_canonical) {
1483 /* namestring is actually canonical, name/namelen needs to be populated */
1484 error = name2oid(namestring, name, &namelen);
1485 if (error) {
1486 goto err;
1487 }
1488 }
1489
1490 oid = SLIST_FIRST(lsp);
1491
1492 indx = 0;
1493 while (oid && indx < CTL_MAXNAME) {
1494 if (oid->oid_number == name[indx]) {
1495 if (!from_kernel && !string_is_canonical) {
1496 if (namestring_started) {
1497 if (strlcat(namestring, ".", namestringlen) >= namestringlen) {
1498 error = ENAMETOOLONG;
1499 goto err;
1500 }
1501 }
1502
1503 if (strlcat(namestring, oid->oid_name, namestringlen) >= namestringlen) {
1504 error = ENAMETOOLONG;
1505 goto err;
1506 }
1507 namestring_started = TRUE;
1508 }
1509
1510 indx++;
1511 if (!(oid->oid_kind & CTLFLAG_LOCKED)) {
1512 unlocked_node_found = TRUE;
1513 }
1514 if (oid->oid_kind & CTLFLAG_NOLOCK) {
1515 req->lock = 0;
1516 }
1517 /*
1518 * For SYSCTL_PROC() functions which are for sysctl's
1519 * which have parameters at the end of their OID
1520 * space, you need to OR CTLTYPE_NODE into their
1521 * access value.
1522 *
1523 * NOTE: For binary backward compatibility ONLY! Do
1524 * NOT add new sysctl's that do this! Existing
1525 * sysctl's which do this will eventually have
1526 * compatibility code in user space, and this method
1527 * will become unsupported.
1528 */
1529 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1530 if (oid->oid_handler) {
1531 goto found;
1532 }
1533 if (indx == namelen) {
1534 error = ENOENT;
1535 goto err;
1536 }
1537
1538 lsp = (struct sysctl_oid_list *)oid->oid_arg1;
1539 oid = SLIST_FIRST(lsp);
1540 } else {
1541 if (indx != namelen) {
1542 error = EISDIR;
1543 goto err;
1544 }
1545 goto found;
1546 }
1547 } else {
1548 oid = SLIST_NEXT(oid, oid_link);
1549 }
1550 }
1551 error = ENOENT;
1552 goto err;
1553found:
1554
1555 /*
1556 * indx is the index of the first remaining OID name,
1557 * for sysctls that take them as arguments
1558 */
1559 if (!from_kernel && !string_is_canonical && (indx < namelen)) {
1560 char tempbuf[10];
1561 u_int indx2;
1562
1563 for (indx2 = indx; indx2 < namelen; indx2++) {
1564 snprintf(tempbuf, sizeof(tempbuf), "%d", name[indx2]);
1565
1566 if (namestring_started) {
1567 if (strlcat(namestring, ".", namestringlen) >= namestringlen) {
1568 error = ENAMETOOLONG;
1569 goto err;
1570 }
1571 }
1572
1573 if (strlcat(namestring, tempbuf, namestringlen) >= namestringlen) {
1574 error = ENAMETOOLONG;
1575 goto err;
1576 }
1577 namestring_started = TRUE;
1578 }
1579 }
1580
1581 /* If writing isn't allowed */
1582 if (req->newptr && (!(oid->oid_kind & CTLFLAG_WR) ||
1583 ((oid->oid_kind & CTLFLAG_SECURE) && securelevel > 0))) {
1584 error = (EPERM);
1585 goto err;
1586 }
1587
1588 /*
1589 * If we're inside the kernel, the OID must be marked as kernel-valid.
1590 */
1591 if (from_kernel && !(oid->oid_kind & CTLFLAG_KERN)) {
1592 error = (EPERM);
1593 goto err;
1594 }
1595
1596 /*
1597 * This is where legacy enforcement of permissions occurs. If the
1598 * flag does not say CTLFLAG_ANYBODY, then we prohibit anyone but
1599 * root from writing new values down. If local enforcement happens
1600 * at the leaf node, then it needs to be set as CTLFLAG_ANYBODY. In
1601 * addition, if the leaf node is set this way, then in order to do
1602 * specific enforcement, it has to be of type SYSCTL_PROC.
1603 */
1604 if (!(oid->oid_kind & CTLFLAG_ANYBODY) &&
1605 req->newptr && req->p &&
1606 (error = proc_suser(req->p))) {
1607 goto err;
1608 }
1609
1610 /*
1611 * sysctl_unregister_oid() may change the handler value, so grab it
1612 * under the lock.
1613 */
1614 oid_handler = oid->oid_handler;
1615 if (!oid_handler) {
1616 error = EINVAL;
1617 goto err;
1618 }
1619
1620 /*
1621 * Reference the OID and drop the geometry lock; this prevents the
1622 * OID from being deleted out from under the handler call, but does
1623 * not prevent other calls into handlers or calls to manage the
1624 * geometry elsewhere from blocking...
1625 */
1626 OSAddAtomic(1, &oid->oid_refcnt);
1627
1628 lck_rw_done(sysctl_geometry_lock);
1629
1630#if CONFIG_MACF
1631 if (!from_kernel) {
1632 error = mac_system_check_sysctlbyname(kauth_cred_get(),
1633 namestring,
1634 name,
1635 namelen,
1636 req->oldptr,
1637 req->oldlen,
1638 req->newptr,
1639 req->newlen);
1640 if (error) {
1641 goto dropref;
1642 }
1643 }
1644#endif
1645
1646 /*
1647 * ...however, we still have to grab the mutex for those calls which
1648 * may be into code whose reentrancy is protected by it.
1649 */
1650 if (unlocked_node_found) {
1651 lck_mtx_lock(sysctl_unlocked_node_lock);
1652 }
1653
1654#if defined(HAS_APPLE_PAC)
1655 /*
1656 * oid_handler is signed address-discriminated by sysctl_register_oid().
1657 */
1658 oid_handler = ptrauth_auth_function(oid_handler,
1659 ptrauth_key_function_pointer,
1660 ptrauth_blend_discriminator(&oid->oid_handler,
1661 ptrauth_string_discriminator("oid_handler")));
1662#endif /* defined(HAS_APPLE_PAC) */
1663
1664 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1665 i = oid_handler(oid, name + indx, namelen - indx, req);
1666 } else {
1667 i = oid_handler(oid, oid->oid_arg1, oid->oid_arg2, req);
1668 }
1669 error = i;
1670
1671 if (unlocked_node_found) {
1672 lck_mtx_unlock(sysctl_unlocked_node_lock);
1673 }
1674
1675#if CONFIG_MACF
1676 /* only used from another CONFIG_MACF block */
1677dropref:
1678#endif
1679
1680 /*
1681 * This is tricky... we re-grab the geometry lock in order to drop
1682 * the reference and wake on the address; since the geometry
1683 * lock is a reader/writer lock rather than a mutex, we have to
1684 * wake on all apparent 1->0 transitions. This abuses the drop
1685 * after the reference decrement in order to wake any lck_rw_sleep()
1686 * in progress in sysctl_unregister_oid() that slept because of a
1687 * non-zero reference count.
1688 *
1689 * Note: OSAddAtomic() is defined to return the previous value;
1690 * we use this and the fact that the lock itself is a
1691 * barrier to avoid waking every time through on "hot"
1692 * OIDs.
1693 */
1694 lck_rw_lock_shared(sysctl_geometry_lock);
1695 if (OSAddAtomic(-1, &oid->oid_refcnt) == 1) {
1696 wakeup(&oid->oid_refcnt);
1697 }
1698
1699err:
1700 lck_rw_done(sysctl_geometry_lock);
1701 return error;
1702}
1703
1704void
1705sysctl_create_user_req(struct sysctl_req *req, struct proc *p, user_addr_t oldp,
1706 size_t oldlen, user_addr_t newp, size_t newlen)
1707{
1708 bzero(req, sizeof(*req));
1709
1710 req->p = p;
1711
1712 req->oldlen = oldlen;
1713 req->oldptr = oldp;
1714
1715 if (newlen) {
1716 req->newlen = newlen;
1717 req->newptr = newp;
1718 }
1719
1720 req->oldfunc = sysctl_old_user;
1721 req->newfunc = sysctl_new_user;
1722 req->lock = 1;
1723
1724 return;
1725}
1726
1727int
1728sysctl(proc_t p, struct sysctl_args *uap, __unused int32_t *retval)
1729{
1730 int error, new_error;
1731 size_t oldlen = 0, newlen;
1732 int name[CTL_MAXNAME];
1733 struct sysctl_req req;
1734 char *namestring;
1735 size_t namestringlen = MAXPATHLEN;
1736
1737 /*
1738 * all top-level sysctl names are non-terminal
1739 */
1740 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) {
1741 return EINVAL;
1742 }
1743 error = copyin(uap->name, &name[0], uap->namelen * sizeof(int));
1744 if (error) {
1745 return error;
1746 }
1747
1748 AUDIT_ARG(ctlname, name, uap->namelen);
1749
1750 if (uap->newlen > SIZE_T_MAX) {
1751 return EINVAL;
1752 }
1753 newlen = (size_t)uap->newlen;
1754
1755 if (uap->oldlenp != USER_ADDR_NULL) {
1756 uint64_t oldlen64 = fuulong(uap->oldlenp);
1757
1758 /*
1759 * If more than 4G, clamp to 4G
1760 */
1761 if (oldlen64 > SIZE_T_MAX) {
1762 oldlen = SIZE_T_MAX;
1763 } else {
1764 oldlen = (size_t)oldlen64;
1765 }
1766 }
1767
1768 sysctl_create_user_req(&req, p, uap->old, oldlen, uap->new, newlen);
1769
1770 /* Guess that longest length for the passed-in MIB, if we can be more aggressive than MAXPATHLEN */
1771 if (uap->namelen == 2) {
1772 if (name[0] == CTL_KERN && name[1] < KERN_MAXID) {
1773 namestringlen = 32; /* "kern.speculative_reads_disabled" */
1774 } else if (name[0] == CTL_HW && name[1] < HW_MAXID) {
1775 namestringlen = 32; /* "hw.cachelinesize_compat" */
1776 }
1777 }
1778
1779 MALLOC(namestring, char *, namestringlen, M_TEMP, M_WAITOK);
1780 if (!namestring) {
1781 oldlen = 0;
1782 goto err;
1783 }
1784
1785 error = userland_sysctl(FALSE, namestring, namestringlen, name, uap->namelen, &req, &oldlen);
1786
1787 FREE(namestring, M_TEMP);
1788
1789 if ((error) && (error != ENOMEM)) {
1790 return error;
1791 }
1792
1793err:
1794 if (uap->oldlenp != USER_ADDR_NULL) {
1795 /*
1796 * Only overwrite the old error value on a new error
1797 */
1798 new_error = suulong(uap->oldlenp, oldlen);
1799
1800 if (new_error) {
1801 error = new_error;
1802 }
1803 }
1804
1805 return error;
1806}
1807
1808// sysctlbyname is also exported as KPI to kexts
1809// and the syscall name cannot conflict with it
1810int
1811sys_sysctlbyname(proc_t p, struct sysctlbyname_args *uap, __unused int32_t *retval)
1812{
1813 int error, new_error;
1814 size_t oldlen = 0, newlen;
1815 char *name;
1816 size_t namelen = 0;
1817 struct sysctl_req req;
1818 int oid[CTL_MAXNAME];
1819
1820 if (uap->namelen >= MAXPATHLEN) { /* XXX arbitrary, undocumented */
1821 return ENAMETOOLONG;
1822 }
1823 namelen = (size_t)uap->namelen;
1824
1825 MALLOC(name, char *, namelen + 1, M_TEMP, M_WAITOK);
1826 if (!name) {
1827 return ENOMEM;
1828 }
1829
1830 error = copyin(uap->name, name, namelen);
1831 if (error) {
1832 FREE(name, M_TEMP);
1833 return error;
1834 }
1835 name[namelen] = '\0';
1836
1837 /* XXX
1838 * AUDIT_ARG(ctlname, name, uap->namelen);
1839 */
1840
1841 if (uap->newlen > SIZE_T_MAX) {
1842 FREE(name, M_TEMP);
1843 return EINVAL;
1844 }
1845 newlen = (size_t)uap->newlen;
1846
1847 if (uap->oldlenp != USER_ADDR_NULL) {
1848 uint64_t oldlen64 = fuulong(uap->oldlenp);
1849
1850 /*
1851 * If more than 4G, clamp to 4G
1852 */
1853 if (oldlen64 > SIZE_T_MAX) {
1854 oldlen = SIZE_T_MAX;
1855 } else {
1856 oldlen = (size_t)oldlen64;
1857 }
1858 }
1859
1860 sysctl_create_user_req(&req, p, uap->old, oldlen, uap->new, newlen);
1861
1862 error = userland_sysctl(TRUE, name, namelen + 1, oid, CTL_MAXNAME, &req, &oldlen);
1863
1864 FREE(name, M_TEMP);
1865
1866 if ((error) && (error != ENOMEM)) {
1867 return error;
1868 }
1869
1870 if (uap->oldlenp != USER_ADDR_NULL) {
1871 /*
1872 * Only overwrite the old error value on a new error
1873 */
1874 new_error = suulong(uap->oldlenp, oldlen);
1875
1876 if (new_error) {
1877 error = new_error;
1878 }
1879 }
1880
1881 return error;
1882}
1883
1884/*
1885 * This is used from various compatibility syscalls too. That's why name
1886 * must be in kernel space.
1887 */
1888int
1889userland_sysctl(boolean_t string_is_canonical,
1890 char *namestring, size_t namestringlen,
1891 int *name, u_int namelen, struct sysctl_req *req,
1892 size_t *retval)
1893{
1894 int error = 0;
1895 struct sysctl_req req2;
1896
1897 do {
1898 /* if EAGAIN, reset output cursor */
1899 req2 = *req;
1900 if (!string_is_canonical) {
1901 namestring[0] = '\0';
1902 }
1903
1904 error = sysctl_root(FALSE, string_is_canonical, namestring, namestringlen, name, namelen, &req2);
1905 } while (error == EAGAIN);
1906
1907 if (error && error != ENOMEM) {
1908 return error;
1909 }
1910
1911 if (retval) {
1912 if (req2.oldptr && req2.oldidx > req2.oldlen) {
1913 *retval = req2.oldlen;
1914 } else {
1915 *retval = req2.oldidx;
1916 }
1917 }
1918 return error;
1919}
1920
1921/*
1922 * Kernel versions of the userland sysctl helper functions.
1923 *
1924 * These allow sysctl to be used in the same fashion in both
1925 * userland and the kernel.
1926 *
1927 * Note that some sysctl handlers use copyin/copyout, which
1928 * may not work correctly.
1929 *
1930 * The "sysctlbyname" KPI for use by kexts is aliased to this function.
1931 */
1932
1933int
1934kernel_sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1935{
1936 int oid[CTL_MAXNAME];
1937 int name2mib_oid[2];
1938 int error;
1939 size_t oidlen;
1940
1941 /* look up the OID with magic service node */
1942 name2mib_oid[0] = 0;
1943 name2mib_oid[1] = 3;
1944
1945 oidlen = sizeof(oid);
1946 error = kernel_sysctl(current_proc(), name2mib_oid, 2, oid, &oidlen, __DECONST(void *, name), strlen(name));
1947 oidlen /= sizeof(int);
1948
1949 /* now use the OID */
1950 if (error == 0) {
1951 error = kernel_sysctl(current_proc(), oid, oidlen, oldp, oldlenp, newp, newlen);
1952 }
1953 return error;
1954}