2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1989, 1993
30 * The Regents of the University of California. All rights reserved.
32 * This code is derived from software contributed to Berkeley by
33 * Mike Karels at Berkeley Software Design, Inc.
35 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
36 * project, to make these variables more userfriendly.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
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.
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
66 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
70 #include <sys/param.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>
80 #include <security/audit/audit.h>
81 #include <pexpert/pexpert.h>
84 #include <security/mac_framework.h>
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
;
93 * Conditionally allow dtrace to see these functions for debugging purposes.
101 #define STATIC static
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
);
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
);
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
,
134 struct sysctl_oid_list sysctl__children
; /* root list */
137 * Initialization of the MIB tree.
139 * Order by number in each list.
143 sysctl_register_oid(struct sysctl_oid
*new_oidp
)
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
;
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).
157 if (!(new_oidp
->oid_kind
& CTLFLAG_OID2
)) {
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.
162 MALLOC(oidp
, struct sysctl_oid
*, sizeof(*oidp
), M_TEMP
, M_WAITOK
| M_ZERO
);
164 return; /* reject: no memory */
167 * Copy the structure only through the oid_fmt field, which
168 * is the last field in a non-OID2 OID structure.
170 * Note: We may want to set the oid_descr to the
171 * oid_name (or "") at some future date.
173 memcpy(oidp
, new_oidp
, offsetof(struct sysctl_oid
, oid_descr
));
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 */
182 return; /* rejects unknown version */
186 /* Get the write lock to modify the geometry */
187 lck_rw_lock_exclusive(sysctl_geometry_lock
);
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.
194 if (oidp
->oid_number
== OID_AUTO
) {
195 /* First, find the highest oid in the parent list >OID_AUTO_START-1 */
197 SLIST_FOREACH(p
, parent
, oid_link
) {
198 if (p
->oid_number
> n
) {
202 oidp
->oid_number
= n
+ 1;
204 * Reflect the number in an llocated OID into the template
205 * of the caller for sysctl_unregister_oid() compares.
207 if (oidp
!= new_oidp
) {
208 new_oidp
->oid_number
= oidp
->oid_number
;
214 * Insert the oid into the parent's list in order.
217 SLIST_FOREACH(p
, parent
, oid_link
) {
218 if (oidp
->oid_number
< p
->oid_number
) {
224 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
226 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
229 /* Release the write lock */
230 lck_rw_unlock_exclusive(sysctl_geometry_lock
);
234 sysctl_unregister_oid(struct sysctl_oid
*oidp
)
236 struct sysctl_oid
*removed_oidp
= NULL
; /* OID removed from tree */
237 struct sysctl_oid
*old_oidp
= NULL
; /* OID compatibility copy */
239 /* Get the write lock to modify the geometry */
240 lck_rw_lock_exclusive(sysctl_geometry_lock
);
242 if (!(oidp
->oid_kind
& CTLFLAG_OID2
)) {
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.
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
)))) {
254 if (old_oidp
!= NULL
) {
255 SLIST_REMOVE(old_oidp
->oid_parent
, old_oidp
, sysctl_oid
, oid_link
);
256 removed_oidp
= old_oidp
;
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
);
267 /* XXX: Can't happen; probably tree coruption.*/
268 break; /* rejects unknown version */
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.
279 * Note: oidp could be NULL if it wasn't found.
281 while (removed_oidp
&& removed_oidp
->oid_refcnt
) {
282 lck_rw_sleep(sysctl_geometry_lock
, LCK_SLEEP_EXCLUSIVE
, &removed_oidp
->oid_refcnt
, THREAD_UNINT
);
285 /* Release the write lock */
286 lck_rw_unlock_exclusive(sysctl_geometry_lock
);
288 /* If it was allocated, free it after dropping the lock */
289 if (old_oidp
!= NULL
) {
290 FREE(old_oidp
, M_TEMP
);
295 * Bulk-register all the oids in a linker_set.
298 sysctl_register_set(const char *set
)
300 struct sysctl_oid
**oidpp
, *oidp
;
302 LINKER_SET_FOREACH(oidpp
, struct sysctl_oid
**, set
) {
304 if (!(oidp
->oid_kind
& CTLFLAG_NOAUTO
)) {
305 sysctl_register_oid(oidp
);
311 sysctl_unregister_set(const char *set
)
313 struct sysctl_oid
**oidpp
, *oidp
;
315 LINKER_SET_FOREACH(oidpp
, struct sysctl_oid
**, set
) {
317 if (!(oidp
->oid_kind
& CTLFLAG_NOAUTO
)) {
318 sysctl_unregister_oid(oidp
);
324 * Exported in BSDKernel.exports, kept for binary compatibility
326 #if defined(__x86_64__)
328 sysctl_register_fixed(void)
334 * Register the kernel's oids on startup.
338 sysctl_early_init(void)
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.
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
);
351 sysctl_register_set("__sysctl_set");
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.).
363 sysctl_io_number(struct sysctl_req
*req
, long long bigValue
, size_t valueSize
, void *pValue
, int *changed
)
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
379 /* 32 bit value expected or 32 bit buffer offered */
380 if (((valueSize
== sizeof(int)) ||
381 ((req
->oldlen
== sizeof(int)) && (valueSize
== sizeof(long long))))
383 smallValue
= (int)bigValue
;
384 if ((long long)smallValue
!= bigValue
) {
387 error
= SYSCTL_OUT(req
, &smallValue
, sizeof(smallValue
));
389 /* any other case is either size-equal or a bug */
390 error
= SYSCTL_OUT(req
, &bigValue
, valueSize
);
392 /* error or nothing to set */
393 if (error
|| !req
->newptr
) {
397 /* set request for constant */
398 if (pValue
== NULL
) {
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
));
407 *(long long *)pValue
= (long long)smallValue
;
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
));
413 smallValue
= (int)bigValue
;
414 if ((long long)smallValue
!= bigValue
) {
417 *(int *)pValue
= smallValue
;
420 /* sizes match, just copy in */
421 error
= SYSCTL_IN(req
, pValue
, valueSize
);
423 if (!error
&& changed
) {
430 sysctl_io_string(struct sysctl_req
*req
, char *pValue
, size_t valueSize
, int trunc
, int *changed
)
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);
448 error
= SYSCTL_OUT(req
, &c
, 1);
451 /* Copy string out */
452 error
= SYSCTL_OUT(req
, pValue
, strlen(pValue
) + 1);
455 /* error or no new value */
456 if (error
|| !req
->newptr
) {
460 /* attempt to set read-only value */
461 if (valueSize
== 0) {
465 /* make sure there's room for the new string */
466 if (req
->newlen
>= valueSize
) {
470 /* copy the string in and force NUL termination */
471 error
= SYSCTL_IN(req
, pValue
, req
->newlen
);
472 pValue
[req
->newlen
] = '\0';
474 if (!error
&& changed
) {
481 sysctl_io_opaque(struct sysctl_req
*req
, void *pValue
, size_t valueSize
, int *changed
)
490 error
= SYSCTL_OUT(req
, pValue
, valueSize
);
492 /* error or nothing to set */
493 if (error
|| !req
->newptr
) {
497 error
= SYSCTL_IN(req
, pValue
, valueSize
);
499 if (!error
&& changed
) {
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.
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.
524 * sysctl_sysctl_debug_dump_node
526 * Description: Dump debug information for a given sysctl_oid_list at the
527 * given oid depth out to the kernel log, via printf
529 * Parameters: l sysctl_oid_list pointer
530 * i current node depth
534 * Implicit: kernel log, modified
536 * Locks: Assumes sysctl_geometry_lock is held prior to calling
538 * Notes: This function may call itself recursively to resolve Node
539 * values, which potentially have an inferioer sysctl_oid_list
541 * This function is only callable indirectly via the function
542 * sysctl_sysctl_debug()
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.
549 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
552 struct sysctl_oid
*oidp
;
554 SLIST_FOREACH(oidp
, l
, oid_link
) {
555 for (k
= 0; k
< i
; k
++) {
559 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
562 oidp
->oid_kind
& CTLFLAG_LOCKED
? 'L':' ',
563 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
564 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
566 if (oidp
->oid_handler
) {
570 switch (oidp
->oid_kind
& CTLTYPE
) {
573 if (!oidp
->oid_handler
) {
574 sysctl_sysctl_debug_dump_node(
575 oidp
->oid_arg1
, i
+ 2);
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");
588 * sysctl_sysctl_debug
590 * Description: This function implements the "sysctl.debug" portion of the
591 * OID space for sysctl.
595 * Parameters: __unused
599 * Implicit: kernel log, modified
601 * Locks: Acquires and then releases a read lock on the
602 * sysctl_geometry_lock
605 sysctl_sysctl_debug(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
606 __unused
int arg2
, __unused
struct sysctl_req
*req
)
608 lck_rw_lock_shared(sysctl_geometry_lock
);
609 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
610 lck_rw_done(sysctl_geometry_lock
);
614 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
615 0, 0, sysctl_sysctl_debug
, "-", "");
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"
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
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
640 * Implict: Contents of user request buffer, modified
642 * Locks: Acquires and then releases a read lock on the
643 * sysctl_geometry_lock
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.
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
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.
664 sysctl_sysctl_name(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
665 struct sysctl_req
*req
)
667 int *name
= (int *) arg1
;
668 u_int namelen
= arg2
;
670 struct sysctl_oid
*oid
;
671 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
672 char tempbuf
[10] = {};
674 lck_rw_lock_shared(sysctl_geometry_lock
);
677 snprintf(tempbuf
, sizeof(tempbuf
), "%d", *name
);
679 error
= SYSCTL_OUT(req
, ".", 1);
682 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
685 lck_rw_done(sysctl_geometry_lock
);
693 SLIST_FOREACH(oid
, lsp
, oid_link
) {
694 if (oid
->oid_number
!= *name
) {
699 error
= SYSCTL_OUT(req
, ".", 1);
702 error
= SYSCTL_OUT(req
, oid
->oid_name
,
703 strlen(oid
->oid_name
));
706 lck_rw_done(sysctl_geometry_lock
);
713 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
717 if (oid
->oid_handler
) {
721 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
726 lck_rw_done(sysctl_geometry_lock
);
727 return SYSCTL_OUT(req
, "", 1);
730 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_name
, "");
733 * sysctl_sysctl_next_ls
735 * Description: For a given OID name value, return the next consecutive OID
736 * name value within the geometry tree
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
743 * len Pointer to receive new OID
744 * length value of storage written
745 * level OID tree depth (used to compute
747 * oidpp Pointer to OID list entry
748 * pointer; used to walk the list
749 * forward across recursion
751 * Returns: 0 Returning a new entry
752 * 1 End of geometry list reached
754 * Implicit: *next Modified to contain the new OID
755 * *len Modified to contain new length
757 * Locks: Assumes sysctl_geometry_lock is held prior to calling
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
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
)
768 struct sysctl_oid
*oidp
;
771 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
772 *next
= oidp
->oid_number
;
776 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
779 if (oidp
->oid_handler
) {
780 /* We really should call the handler here...*/
783 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
785 if (!SLIST_FIRST(lsp
)) {
786 /* This node had no children - skip it! */
790 if (!sysctl_sysctl_next_ls(lsp
, 0, 0, next
+ 1,
791 len
, level
+ 1, oidpp
)) {
797 if (oidp
->oid_number
< *name
) {
801 if (oidp
->oid_number
> *name
) {
802 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
805 if (oidp
->oid_handler
) {
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
)) {
815 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
819 if (oidp
->oid_handler
) {
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
)) {
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"
844 * Parameters: oidp __unused
845 * arg1 Pointer to start OID name
846 * arg2 Start OID name length
847 * req Pointer to user request buffer
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
856 * Implict: Contents of user request buffer, modified
858 * Locks: Acquires and then releases a read lock on the
859 * sysctl_geometry_lock
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.
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.
874 sysctl_sysctl_next(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
875 struct sysctl_req
*req
)
877 int *name
= (int *) arg1
;
878 u_int namelen
= arg2
;
880 struct sysctl_oid
*oid
;
881 struct sysctl_oid_list
*lsp
= &sysctl__children
;
882 int newoid
[CTL_MAXNAME
] = {};
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
);
890 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof(int));
894 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_next
, "");
899 * Description: Support function for use by sysctl_sysctl_name2oid(); looks
900 * up an OID name given a string name.
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")
908 * ENOENT Entry not found
910 * Implicit: *oid Modified to contain OID value
911 * *len Modified to contain OID length
913 * Locks: Assumes sysctl_geometry_lock is held prior to calling
916 name2oid(char *name
, int *oid
, u_int
*len
)
919 struct sysctl_oid
*oidp
;
920 struct sysctl_oid_list
*lsp
= &sysctl__children
;
927 p
= name
+ strlen(name
) - 1;
934 for (p
= name
; *p
&& *p
!= '.'; p
++) {
942 oidp
= SLIST_FIRST(lsp
);
944 while (oidp
&& *len
< CTL_MAXNAME
) {
945 if (strcmp(name
, oidp
->oid_name
)) {
946 oidp
= SLIST_NEXT(oidp
, oid_link
);
949 *oid
++ = oidp
->oid_number
;
956 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
960 if (oidp
->oid_handler
) {
964 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
965 oidp
= SLIST_FIRST(lsp
);
966 *p
= i
; /* restore */
968 for (p
= name
; *p
&& *p
!= '.'; p
++) {
980 * sysctl_sysctl_name2oid
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
988 * Parameters: oidp __unused
991 * req Request structure
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
1001 * Implicit: *req Contents of request, modified
1003 * Locks: Acquires and then releases a read lock on the
1004 * sysctl_geometry_lock
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.
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.
1019 sysctl_sysctl_name2oid(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
1020 __unused
int arg2
, struct sysctl_req
*req
)
1023 int error
, oid
[CTL_MAXNAME
] = {};
1024 u_int len
= 0; /* set by name2oid() */
1026 if (req
->newlen
< 1) {
1029 if (req
->newlen
>= MAXPATHLEN
) { /* XXX arbitrary, undocumented */
1030 return ENAMETOOLONG
;
1033 MALLOC(p
, char *, req
->newlen
+ 1, M_TEMP
, M_WAITOK
);
1038 error
= SYSCTL_IN(req
, p
, req
->newlen
);
1044 p
[req
->newlen
] = '\0';
1047 * Note: We acquire and release the geometry lock here to
1048 * avoid making name2oid needlessly complex.
1050 lck_rw_lock_shared(sysctl_geometry_lock
);
1051 error
= name2oid(p
, oid
, &len
);
1052 lck_rw_done(sysctl_geometry_lock
);
1060 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
1064 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_KERN
| CTLFLAG_LOCKED
, 0, 0,
1065 sysctl_sysctl_name2oid
, "I", "");
1068 * sysctl_sysctl_oidfmt
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
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
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
1088 * Implict: Contents of user request buffer, modified
1090 * Locks: Acquires and then releases a read lock on the
1091 * sysctl_geometry_lock
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.
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.
1105 sysctl_sysctl_oidfmt(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1106 struct sysctl_req
*req
)
1108 int *name
= (int *) arg1
;
1109 int error
= ENOENT
; /* default error: not found */
1110 u_int namelen
= arg2
;
1112 struct sysctl_oid
*oid
;
1113 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1115 lck_rw_lock_shared(sysctl_geometry_lock
);
1116 oid
= SLIST_FIRST(lsp
);
1119 while (oid
&& indx
< CTL_MAXNAME
) {
1120 if (oid
->oid_number
== name
[indx
]) {
1122 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1123 if (oid
->oid_handler
) {
1126 if (indx
== namelen
) {
1129 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
1130 oid
= SLIST_FIRST(lsp
);
1132 if (indx
!= namelen
) {
1139 oid
= SLIST_NEXT(oid
, oid_link
);
1146 if (!oid
->oid_fmt
) {
1149 error
= SYSCTL_OUT(req
,
1150 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
1152 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
1153 strlen(oid
->oid_fmt
) + 1);
1156 lck_rw_done(sysctl_geometry_lock
);
1160 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_oidfmt
, "");
1164 * Default "handler" functions.
1168 * Handle an int, signed or unsigned.
1170 * a variable: point arg1 at it.
1171 * a constant: pass it in arg2.
1175 sysctl_handle_int(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1176 struct sysctl_req
*req
)
1178 return sysctl_io_number(req
, arg1
? *(int*)arg1
: arg2
, sizeof(int), arg1
, NULL
);
1182 * Handle a long, signed or unsigned. arg1 points to it.
1186 sysctl_handle_long(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1187 __unused
int arg2
, struct sysctl_req
*req
)
1192 return sysctl_io_number(req
, *(long*)arg1
, sizeof(long), arg1
, NULL
);
1196 * Handle a quad, signed or unsigned. arg1 points to it.
1200 sysctl_handle_quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1201 __unused
int arg2
, struct sysctl_req
*req
)
1206 return sysctl_io_number(req
, *(long long*)arg1
, sizeof(long long), arg1
, NULL
);
1210 * Expose an int value as a quad.
1212 * This interface allows us to support interfaces defined
1213 * as using quad values while the implementation is still
1217 sysctl_handle_int2quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1218 __unused
int arg2
, struct sysctl_req
*req
)
1227 val
= (long long)*(int *)arg1
;
1228 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
1230 if (error
|| !req
->newptr
) {
1234 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
1237 * Value must be representable; check by
1238 * casting and then casting back.
1241 if ((long long)newval
!= val
) {
1244 *(int *)arg1
= newval
;
1251 * Handle our generic '\0' terminated 'C' string.
1253 * a variable string: point arg1 at it, arg2 is max length.
1254 * a constant string: point arg1 at it, arg2 is zero.
1258 sysctl_handle_string( __unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1259 struct sysctl_req
*req
)
1261 return sysctl_io_string(req
, arg1
, arg2
, 0, NULL
);
1265 * Handle any kind of opaque data.
1266 * arg1 points to it, arg2 is the size.
1270 sysctl_handle_opaque(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1271 struct sysctl_req
*req
)
1273 return sysctl_io_opaque(req
, arg1
, arg2
, NULL
);
1277 * Transfer functions to/from kernel space.
1280 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
1286 if (i
> req
->oldlen
- req
->oldidx
) {
1287 i
= req
->oldlen
- req
->oldidx
;
1290 bcopy((const void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
1294 if (req
->oldptr
&& i
!= l
) {
1301 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
1306 if (req
->newlen
- req
->newidx
< l
) {
1309 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
1315 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
1318 struct sysctl_req req
;
1321 * Construct request.
1323 bzero(&req
, sizeof req
);
1326 req
.oldlen
= *oldlenp
;
1329 req
.oldptr
= CAST_USER_ADDR_T(old
);
1332 req
.newlen
= newlen
;
1333 req
.newptr
= CAST_USER_ADDR_T(new);
1335 req
.oldfunc
= sysctl_old_kernel
;
1336 req
.newfunc
= sysctl_new_kernel
;
1339 /* make the request */
1340 error
= sysctl_root(TRUE
, FALSE
, NULL
, 0, name
, namelen
, &req
);
1342 if (error
&& error
!= ENOMEM
) {
1347 *oldlenp
= req
.oldidx
;
1354 * Transfer function to/from user space.
1357 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
1363 if (req
->oldlen
- req
->oldidx
< l
) {
1367 if (i
> req
->oldlen
- req
->oldidx
) {
1368 i
= req
->oldlen
- req
->oldidx
;
1371 error
= copyout((const void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
1378 if (req
->oldptr
&& i
< l
) {
1385 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
1392 if (req
->newlen
- req
->newidx
< l
) {
1395 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
1401 * Traverse our tree, and find the right node, execute whatever it points
1402 * at, and return the resulting error code.
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
)
1410 struct sysctl_oid
*oid
;
1411 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1412 sysctl_handler_t oid_handler
= NULL
;
1414 boolean_t unlocked_node_found
= FALSE
;
1415 boolean_t namestring_started
= FALSE
;
1417 /* Get the read lock on the geometry */
1418 lck_rw_lock_shared(sysctl_geometry_lock
);
1420 if (string_is_canonical
) {
1421 /* namestring is actually canonical, name/namelen needs to be populated */
1422 error
= name2oid(namestring
, name
, &namelen
);
1428 oid
= SLIST_FIRST(lsp
);
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
;
1441 if (strlcat(namestring
, oid
->oid_name
, namestringlen
) >= namestringlen
) {
1442 error
= ENAMETOOLONG
;
1445 namestring_started
= TRUE
;
1449 if (!(oid
->oid_kind
& CTLFLAG_LOCKED
)) {
1450 unlocked_node_found
= TRUE
;
1452 if (oid
->oid_kind
& CTLFLAG_NOLOCK
) {
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
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.
1467 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1468 if (oid
->oid_handler
) {
1471 if (indx
== namelen
) {
1476 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
1477 oid
= SLIST_FIRST(lsp
);
1479 if (indx
!= namelen
) {
1486 oid
= SLIST_NEXT(oid
, oid_link
);
1494 * indx is the index of the first remaining OID name,
1495 * for sysctls that take them as arguments
1497 if (!from_kernel
&& !string_is_canonical
&& (indx
< namelen
)) {
1501 for (indx2
= indx
; indx2
< namelen
; indx2
++) {
1502 snprintf(tempbuf
, sizeof(tempbuf
), "%d", name
[indx2
]);
1504 if (namestring_started
) {
1505 if (strlcat(namestring
, ".", namestringlen
) >= namestringlen
) {
1506 error
= ENAMETOOLONG
;
1511 if (strlcat(namestring
, tempbuf
, namestringlen
) >= namestringlen
) {
1512 error
= ENAMETOOLONG
;
1515 namestring_started
= TRUE
;
1519 /* If writing isn't allowed */
1520 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
1521 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
1527 * If we're inside the kernel, the OID must be marked as kernel-valid.
1529 if (from_kernel
&& !(oid
->oid_kind
& CTLFLAG_KERN
)) {
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.
1542 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
1543 req
->newptr
&& req
->p
&&
1544 (error
= proc_suser(req
->p
))) {
1549 * sysctl_unregister_oid() may change the handler value, so grab it
1552 oid_handler
= oid
->oid_handler
;
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...
1564 OSAddAtomic(1, &oid
->oid_refcnt
);
1566 lck_rw_done(sysctl_geometry_lock
);
1570 error
= mac_system_check_sysctlbyname(kauth_cred_get(),
1585 * ...however, we still have to grab the mutex for those calls which
1586 * may be into code whose reentrancy is protected by it.
1588 if (unlocked_node_found
) {
1589 lck_mtx_lock(sysctl_unlocked_node_lock
);
1593 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1594 i
= oid_handler(oid
, name
+ indx
, namelen
- indx
, req
);
1596 i
= oid_handler(oid
, oid
->oid_arg1
, oid
->oid_arg2
, req
);
1600 if (unlocked_node_found
) {
1601 lck_mtx_unlock(sysctl_unlocked_node_lock
);
1605 /* only used from another CONFIG_MACF block */
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.
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"
1623 lck_rw_lock_shared(sysctl_geometry_lock
);
1624 if (OSAddAtomic(-1, &oid
->oid_refcnt
) == 1) {
1625 wakeup(&oid
->oid_refcnt
);
1629 lck_rw_done(sysctl_geometry_lock
);
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
)
1637 bzero(req
, sizeof(*req
));
1641 req
->oldlen
= oldlen
;
1645 req
->newlen
= newlen
;
1649 req
->oldfunc
= sysctl_old_user
;
1650 req
->newfunc
= sysctl_new_user
;
1657 sysctl(proc_t p
, struct sysctl_args
*uap
, __unused
int32_t *retval
)
1660 size_t oldlen
= 0, newlen
;
1661 int name
[CTL_MAXNAME
];
1662 struct sysctl_req req
;
1664 size_t namestringlen
= MAXPATHLEN
;
1667 * all top-level sysctl names are non-terminal
1669 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2) {
1672 error
= copyin(uap
->name
, &name
[0], uap
->namelen
* sizeof(int));
1677 AUDIT_ARG(ctlname
, name
, uap
->namelen
);
1679 if (uap
->newlen
> SIZE_T_MAX
) {
1682 newlen
= (size_t)uap
->newlen
;
1684 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1685 uint64_t oldlen64
= fuulong(uap
->oldlenp
);
1688 * If more than 4G, clamp to 4G
1690 if (oldlen64
> SIZE_T_MAX
) {
1691 oldlen
= SIZE_T_MAX
;
1693 oldlen
= (size_t)oldlen64
;
1697 sysctl_create_user_req(&req
, p
, uap
->old
, oldlen
, uap
->new, newlen
);
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" */
1708 MALLOC(namestring
, char *, namestringlen
, M_TEMP
, M_WAITOK
);
1714 error
= userland_sysctl(FALSE
, namestring
, namestringlen
, name
, uap
->namelen
, &req
, &oldlen
);
1716 FREE(namestring
, M_TEMP
);
1718 if ((error
) && (error
!= ENOMEM
)) {
1723 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1724 error
= suulong(uap
->oldlenp
, oldlen
);
1731 sysctlbyname(proc_t p
, struct sysctlbyname_args
*uap
, __unused
int32_t *retval
)
1734 size_t oldlen
= 0, newlen
;
1737 struct sysctl_req req
;
1738 int oid
[CTL_MAXNAME
];
1740 if (uap
->namelen
>= MAXPATHLEN
) { /* XXX arbitrary, undocumented */
1741 return ENAMETOOLONG
;
1743 namelen
= (size_t)uap
->namelen
;
1745 MALLOC(name
, char *, namelen
+ 1, M_TEMP
, M_WAITOK
);
1750 error
= copyin(uap
->name
, name
, namelen
);
1755 name
[namelen
] = '\0';
1758 * AUDIT_ARG(ctlname, name, uap->namelen);
1761 if (uap
->newlen
> SIZE_T_MAX
) {
1765 newlen
= (size_t)uap
->newlen
;
1767 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1768 uint64_t oldlen64
= fuulong(uap
->oldlenp
);
1771 * If more than 4G, clamp to 4G
1773 if (oldlen64
> SIZE_T_MAX
) {
1774 oldlen
= SIZE_T_MAX
;
1776 oldlen
= (size_t)oldlen64
;
1780 sysctl_create_user_req(&req
, p
, uap
->old
, oldlen
, uap
->new, newlen
);
1782 error
= userland_sysctl(TRUE
, name
, namelen
+ 1, oid
, CTL_MAXNAME
, &req
, &oldlen
);
1786 if ((error
) && (error
!= ENOMEM
)) {
1790 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1791 error
= suulong(uap
->oldlenp
, oldlen
);
1798 * This is used from various compatibility syscalls too. That's why name
1799 * must be in kernel space.
1802 userland_sysctl(boolean_t string_is_canonical
,
1803 char *namestring
, size_t namestringlen
,
1804 int *name
, u_int namelen
, struct sysctl_req
*req
,
1808 struct sysctl_req req2
;
1811 /* if EAGAIN, reset output cursor */
1813 if (!string_is_canonical
) {
1814 namestring
[0] = '\0';
1817 error
= sysctl_root(FALSE
, string_is_canonical
, namestring
, namestringlen
, name
, namelen
, &req2
);
1818 } while (error
== EAGAIN
);
1820 if (error
&& error
!= ENOMEM
) {
1825 if (req2
.oldptr
&& req2
.oldidx
> req2
.oldlen
) {
1826 *retval
= req2
.oldlen
;
1828 *retval
= req2
.oldidx
;
1835 * Kernel versions of the userland sysctl helper functions.
1837 * These allow sysctl to be used in the same fashion in both
1838 * userland and the kernel.
1840 * Note that some sysctl handlers use copyin/copyout, which
1841 * may not work correctly.
1843 * The "sysctlbyname" KPI for use by kexts is aliased to this function.
1847 kernel_sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1849 int oid
[CTL_MAXNAME
];
1850 int name2mib_oid
[2];
1854 /* look up the OID with magic service node */
1855 name2mib_oid
[0] = 0;
1856 name2mib_oid
[1] = 3;
1858 oidlen
= sizeof(oid
);
1859 error
= kernel_sysctl(current_proc(), name2mib_oid
, 2, oid
, &oidlen
, __DECONST(void *, name
), strlen(name
));
1860 oidlen
/= sizeof(int);
1862 /* now use the OID */
1864 error
= kernel_sysctl(current_proc(), oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);