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