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