2 * Copyright (c) 2000-2019 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 <kern/counter.h>
71 #include <sys/param.h>
73 #include <sys/kernel.h>
74 #include <sys/sysctl.h>
75 #include <sys/malloc.h>
76 #include <sys/proc_internal.h>
77 #include <sys/kauth.h>
78 #include <sys/systm.h>
79 #include <sys/sysproto.h>
81 #include <os/atomic_private.h>
83 #include <security/audit/audit.h>
84 #include <pexpert/pexpert.h>
86 #include <IOKit/IOBSD.h>
89 #include <security/mac_framework.h>
92 #if defined(HAS_APPLE_PAC)
95 #endif /* defined(HAS_APPLE_PAC) */
97 static LCK_GRP_DECLARE(sysctl_lock_group
, "sysctl");
98 static LCK_RW_DECLARE(sysctl_geometry_lock
, &sysctl_lock_group
);
99 static LCK_MTX_DECLARE(sysctl_unlocked_node_lock
, &sysctl_lock_group
);
102 * Conditionally allow dtrace to see these functions for debugging purposes.
110 #define STATIC static
113 /* forward declarations of static functions */
114 STATIC
void sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
115 STATIC
int sysctl_sysctl_debug(struct sysctl_oid
*oidp
, void *arg1
,
116 int arg2
, struct sysctl_req
*req
);
117 STATIC
int sysctl_sysctl_name(struct sysctl_oid
*oidp
, void *arg1
,
118 int arg2
, struct sysctl_req
*req
);
119 STATIC
int sysctl_sysctl_next_ls(struct sysctl_oid_list
*lsp
,
120 int *name
, u_int namelen
, int *next
, int *len
, int level
,
121 struct sysctl_oid
**oidpp
);
122 STATIC
int sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
);
123 STATIC
int sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
);
124 STATIC
int name2oid(char *name
, int *oid
, size_t *len
);
125 STATIC
int sysctl_sysctl_name2oid(struct sysctl_oid
*oidp
, void *arg1
, int arg2
, struct sysctl_req
*req
);
126 STATIC
int sysctl_sysctl_next(struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
127 struct sysctl_req
*req
);
128 STATIC
int sysctl_sysctl_oidfmt(struct sysctl_oid
*oidp
, void *arg1
, int arg2
, struct sysctl_req
*req
);
129 STATIC
int sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
);
130 STATIC
int sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
);
132 STATIC
void sysctl_create_user_req(struct sysctl_req
*req
, struct proc
*p
, user_addr_t oldp
,
133 size_t oldlen
, user_addr_t newp
, size_t newlen
);
134 STATIC
int sysctl_root(boolean_t from_kernel
, boolean_t string_is_canonical
, char *namestring
, size_t namestringlen
, int *name
, size_t namelen
, struct sysctl_req
*req
);
136 int kernel_sysctl(struct proc
*p
, int *name
, size_t namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
);
137 int kernel_sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
138 int userland_sysctl(boolean_t string_is_canonical
,
139 char *namestring
, size_t namestringlen
,
140 int *name
, u_int namelen
, struct sysctl_req
*req
,
143 SECURITY_READ_ONLY_LATE(struct sysctl_oid_list
) sysctl__children
; /* root list */
144 __SYSCTL_EXTENSION_NODE();
147 * Initialization of the MIB tree.
149 * Order by number in each list.
153 sysctl_register_oid_locked(struct sysctl_oid
*new_oidp
,
154 struct sysctl_oid
*oidp
)
156 struct sysctl_oid_list
*parent
= new_oidp
->oid_parent
;
157 struct sysctl_oid_list
*parent_rw
= NULL
;
158 struct sysctl_oid
*p
, **prevp
;
160 p
= SLIST_FIRST(parent
);
161 if (p
&& p
->oid_number
== OID_MUTABLE_ANCHOR
) {
162 parent_rw
= p
->oid_arg1
;
165 if (oidp
->oid_number
== OID_AUTO
) {
166 int n
= OID_AUTO_START
;
169 * If this oid has a number OID_AUTO, give it a number which
170 * is greater than any current oid. Make sure it is at least
171 * OID_AUTO_START to leave space for pre-assigned oid numbers.
174 SLIST_FOREACH_PREVPTR(p
, prevp
, parent
, oid_link
) {
175 if (p
->oid_number
>= n
) {
176 n
= p
->oid_number
+ 1;
181 SLIST_FOREACH_PREVPTR(p
, prevp
, parent_rw
, oid_link
) {
182 if (p
->oid_number
>= n
) {
183 n
= p
->oid_number
+ 1;
189 * Reflect the number in an allocated OID into the template
190 * of the caller for sysctl_unregister_oid() compares.
192 oidp
->oid_number
= new_oidp
->oid_number
= n
;
195 * Insert the oid into the parent's list in order.
197 SLIST_FOREACH_PREVPTR(p
, prevp
, parent
, oid_link
) {
198 if (oidp
->oid_number
== p
->oid_number
) {
199 panic("attempting to register a sysctl at previously registered slot : %d",
201 } else if (oidp
->oid_number
< p
->oid_number
) {
207 SLIST_FOREACH_PREVPTR(p
, prevp
, parent_rw
, oid_link
) {
208 if (oidp
->oid_number
== p
->oid_number
) {
209 panic("attempting to register a sysctl at previously registered slot : %d",
211 } else if (oidp
->oid_number
< p
->oid_number
) {
218 #if defined(HAS_APPLE_PAC)
219 if (oidp
->oid_handler
) {
221 * Sign oid_handler address-discriminated upon installation to make it
222 * harder to replace with an arbitrary function pointer. Blend with
223 * a hash of oid_arg1 for robustness against memory corruption.
225 oidp
->oid_handler
= ptrauth_auth_and_resign(oidp
->oid_handler
,
226 ptrauth_key_function_pointer
,
227 ptrauth_function_pointer_type_discriminator(typeof(oidp
->oid_handler
)),
228 ptrauth_key_function_pointer
,
229 ptrauth_blend_discriminator(&oidp
->oid_handler
,
230 os_hash_kernel_pointer(oidp
->oid_arg1
)));
232 #endif /* defined(HAS_APPLE_PAC) */
234 SLIST_NEXT(oidp
, oid_link
) = *prevp
;
239 sysctl_register_oid(struct sysctl_oid
*new_oidp
)
241 struct sysctl_oid
*oidp
;
243 if (new_oidp
->oid_number
< OID_AUTO
) {
244 panic("trying to register a node %p with an invalid oid_number: %d",
245 new_oidp
, new_oidp
->oid_number
);
247 if (new_oidp
->oid_kind
& CTLFLAG_PERMANENT
) {
248 panic("Use sysctl_register_oid_early to register permanent nodes");
252 * The OID can be old-style (needs copy), new style without an earlier
253 * version (also needs copy), or new style with a matching version (no
254 * copy needed). Later versions are rejected (presumably, the OID
255 * structure was changed for a necessary reason).
257 if (!(new_oidp
->oid_kind
& CTLFLAG_OID2
)) {
260 * XXX: KHEAP_DEFAULT is perhaps not the most apropriate zone, as it
261 * XXX: will subject us to use-after-free by other consumers.
263 oidp
= kheap_alloc(KHEAP_DEFAULT
, sizeof(struct sysctl_oid
),
266 return; /* reject: no memory */
269 * Copy the structure only through the oid_fmt field, which
270 * is the last field in a non-OID2 OID structure.
272 * Note: We may want to set the oid_descr to the
273 * oid_name (or "") at some future date.
275 memcpy(oidp
, new_oidp
, offsetof(struct sysctl_oid
, oid_descr
));
277 panic("Old style sysctl without a version number isn't supported");
280 /* It's a later version; handle the versions we know about */
281 switch (new_oidp
->oid_version
) {
282 case SYSCTL_OID_VERSION
:
283 /* current version */
287 return; /* rejects unknown version */
291 lck_rw_lock_exclusive(&sysctl_geometry_lock
);
292 sysctl_register_oid_locked(new_oidp
, oidp
);
293 lck_rw_unlock_exclusive(&sysctl_geometry_lock
);
298 sysctl_register_oid_early(struct sysctl_oid
*oidp
)
300 assert((oidp
->oid_kind
& CTLFLAG_OID2
) &&
301 (oidp
->oid_kind
& CTLFLAG_PERMANENT
) &&
302 oidp
->oid_version
== SYSCTL_OID_VERSION
);
303 assert(startup_phase
< STARTUP_SUB_SYSCTL
);
306 * Clear the flag so that callers can use sysctl_register_oid_early
307 * again if they wish to register their node.
309 if (oidp
->oid_kind
& CTLFLAG_NOAUTO
) {
310 oidp
->oid_kind
&= ~CTLFLAG_NOAUTO
;
314 sysctl_register_oid_locked(oidp
, oidp
);
318 sysctl_unregister_oid(struct sysctl_oid
*oidp
)
320 struct sysctl_oid
*removed_oidp
= NULL
; /* OID removed from tree */
322 struct sysctl_oid
*old_oidp
= NULL
; /* OID compatibility copy */
324 struct sysctl_oid_list
*lsp
;
326 /* Get the write lock to modify the geometry */
327 lck_rw_lock_exclusive(&sysctl_geometry_lock
);
329 lsp
= oidp
->oid_parent
;
330 if (SLIST_FIRST(lsp
) && SLIST_FIRST(lsp
)->oid_number
== OID_MUTABLE_ANCHOR
) {
331 lsp
= SLIST_FIRST(lsp
)->oid_arg1
;
334 if (oidp
->oid_kind
& CTLFLAG_PERMANENT
) {
335 panic("Trying to unregister permanent sysctl %p", oidp
);
338 if (!(oidp
->oid_kind
& CTLFLAG_OID2
)) {
341 * We're using a copy so we can get the new fields in an
342 * old structure, so we have to iterate to compare the
343 * partial structure; when we find a match, we remove it
344 * normally and free the memory.
346 SLIST_FOREACH(old_oidp
, lsp
, oid_link
) {
347 if (!memcmp(&oidp
->oid_number
, &old_oidp
->oid_number
, (offsetof(struct sysctl_oid
, oid_descr
) - offsetof(struct sysctl_oid
, oid_number
)))) {
351 if (old_oidp
!= NULL
) {
352 SLIST_REMOVE(lsp
, old_oidp
, sysctl_oid
, oid_link
);
353 removed_oidp
= old_oidp
;
356 panic("Old style sysctl without a version number isn't supported");
359 /* It's a later version; handle the versions we know about */
360 switch (oidp
->oid_version
) {
361 case SYSCTL_OID_VERSION
:
362 /* We can just remove the OID directly... */
363 SLIST_REMOVE(lsp
, oidp
, sysctl_oid
, oid_link
);
367 /* XXX: Can't happen; probably tree coruption.*/
368 break; /* rejects unknown version */
372 #if defined(HAS_APPLE_PAC)
373 if (removed_oidp
&& removed_oidp
->oid_handler
) {
375 * Revert address-discriminated signing performed by
376 * sysctl_register_oid() (in case this oid is registered again).
378 removed_oidp
->oid_handler
= ptrauth_auth_and_resign(removed_oidp
->oid_handler
,
379 ptrauth_key_function_pointer
,
380 ptrauth_blend_discriminator(&removed_oidp
->oid_handler
,
381 os_hash_kernel_pointer(removed_oidp
->oid_arg1
)),
382 ptrauth_key_function_pointer
,
383 ptrauth_function_pointer_type_discriminator(typeof(removed_oidp
->oid_handler
)));
385 #endif /* defined(HAS_APPLE_PAC) */
388 * We've removed it from the list at this point, but we don't want
389 * to return to the caller until all handler references have drained
390 * out. Doing things in this order prevent other people coming in
391 * and starting new operations against the OID node we want removed.
393 * Note: oidp could be NULL if it wasn't found.
395 while (removed_oidp
&& removed_oidp
->oid_refcnt
) {
396 lck_rw_sleep(&sysctl_geometry_lock
, LCK_SLEEP_EXCLUSIVE
,
397 &removed_oidp
->oid_refcnt
, THREAD_UNINT
);
400 /* Release the write lock */
401 lck_rw_unlock_exclusive(&sysctl_geometry_lock
);
404 /* If it was allocated, free it after dropping the lock */
405 kheap_free(KHEAP_DEFAULT
, old_oidp
, sizeof(struct sysctl_oid
));
410 * Exported in BSDKernel.exports, kept for binary compatibility
412 #if defined(__x86_64__)
414 sysctl_register_fixed(void)
420 * New handler interface
421 * If the sysctl caller (user mode or kernel mode) is interested in the
422 * value (req->oldptr != NULL), we copy the data (bigValue etc.) out,
423 * if the caller wants to set the value (req->newptr), we copy
424 * the data in (*pValue etc.).
428 sysctl_io_number(struct sysctl_req
*req
, long long bigValue
, size_t valueSize
, void *pValue
, int *changed
)
438 * Handle the various combinations of caller buffer size and
439 * data value size. We are generous in the case where the
440 * caller has specified a 32-bit buffer but the value is 64-bit
444 /* 32 bit value expected or 32 bit buffer offered */
445 if (((valueSize
== sizeof(int)) ||
446 ((req
->oldlen
== sizeof(int)) && (valueSize
== sizeof(long long))))
448 smallValue
= (int)bigValue
;
449 if ((long long)smallValue
!= bigValue
) {
452 error
= SYSCTL_OUT(req
, &smallValue
, sizeof(smallValue
));
454 /* any other case is either size-equal or a bug */
455 error
= SYSCTL_OUT(req
, &bigValue
, valueSize
);
457 /* error or nothing to set */
458 if (error
|| !req
->newptr
) {
462 /* set request for constant */
463 if (pValue
== NULL
) {
467 /* set request needs to convert? */
468 if ((req
->newlen
== sizeof(int)) && (valueSize
== sizeof(long long))) {
469 /* new value is 32 bits, upconvert to 64 bits */
470 error
= SYSCTL_IN(req
, &smallValue
, sizeof(smallValue
));
472 *(long long *)pValue
= (long long)smallValue
;
474 } else if ((req
->newlen
== sizeof(long long)) && (valueSize
== sizeof(int))) {
475 /* new value is 64 bits, downconvert to 32 bits and range check */
476 error
= SYSCTL_IN(req
, &bigValue
, sizeof(bigValue
));
478 smallValue
= (int)bigValue
;
479 if ((long long)smallValue
!= bigValue
) {
482 *(int *)pValue
= smallValue
;
485 /* sizes match, just copy in */
486 error
= SYSCTL_IN(req
, pValue
, valueSize
);
488 if (!error
&& changed
) {
495 sysctl_io_string(struct sysctl_req
*req
, char *pValue
, size_t valueSize
, int trunc
, int *changed
)
498 size_t len
= strlen(pValue
) + 1;
504 if (trunc
&& req
->oldptr
&& req
->oldlen
&& (req
->oldlen
< len
)) {
505 /* If trunc != 0, if you give it a too small (but larger than
506 * 0 bytes) buffer, instead of returning ENOMEM, it truncates the
507 * returned string to the buffer size. This preserves the semantics
508 * of some library routines implemented via sysctl, which truncate
509 * their returned data, rather than simply returning an error. The
510 * returned string is always nul (ascii '\0') terminated. */
511 error
= SYSCTL_OUT(req
, pValue
, req
->oldlen
- 1);
514 error
= SYSCTL_OUT(req
, &c
, 1);
517 /* Copy string out */
518 error
= SYSCTL_OUT(req
, pValue
, len
);
521 /* error or no new value */
522 if (error
|| !req
->newptr
) {
526 /* attempt to set read-only value */
527 if (valueSize
== 0) {
531 /* make sure there's room for the new string */
532 if (req
->newlen
>= valueSize
) {
536 /* copy the string in and force nul termination */
537 error
= SYSCTL_IN(req
, pValue
, req
->newlen
);
538 pValue
[req
->newlen
] = '\0';
540 if (!error
&& changed
) {
547 sysctl_io_opaque(struct sysctl_req
*req
, void *pValue
, size_t valueSize
, int *changed
)
556 error
= SYSCTL_OUT(req
, pValue
, valueSize
);
558 /* error or nothing to set */
559 if (error
|| !req
->newptr
) {
563 error
= SYSCTL_IN(req
, pValue
, valueSize
);
565 if (!error
&& changed
) {
572 * SYSCTL_OID enumerators
574 * Because system OIDs are immutable, they are composed of 2 lists hanging from
575 * a first dummy OID_MUTABLE_ANCHOR node that has an immutable list hanging from
576 * its `oid_parent` field and a mutable list hanging from its oid_arg1 one.
578 * Those enumerators abstract away the implicit merging of those two lists in
579 * two possible order:
580 * - oid_number order (which will interleave both sorted lists)
581 * - system order which will list the immutable list first,
582 * and the mutable list second.
584 struct sysctl_oid_iterator
{
585 struct sysctl_oid
*a
;
586 struct sysctl_oid
*b
;
589 static struct sysctl_oid_iterator
590 sysctl_oid_iterator_begin(struct sysctl_oid_list
*l
)
592 struct sysctl_oid_iterator it
= { };
593 struct sysctl_oid
*a
= SLIST_FIRST(l
);
599 if (a
->oid_number
== OID_MUTABLE_ANCHOR
) {
600 it
.a
= SLIST_NEXT(a
, oid_link
);
601 it
.b
= SLIST_FIRST((struct sysctl_oid_list
*)a
->oid_arg1
);
608 static struct sysctl_oid
*
609 sysctl_oid_iterator_next_num_order(struct sysctl_oid_iterator
*it
)
611 struct sysctl_oid
*a
= it
->a
;
612 struct sysctl_oid
*b
= it
->b
;
614 if (a
== NULL
&& b
== NULL
) {
619 it
->b
= SLIST_NEXT(b
, oid_link
);
623 if (b
== NULL
|| a
->oid_number
<= b
->oid_number
) {
624 it
->a
= SLIST_NEXT(a
, oid_link
);
628 it
->b
= SLIST_NEXT(b
, oid_link
);
632 #define SYSCTL_OID_FOREACH_NUM_ORDER(oidp, l) \
633 for (struct sysctl_oid_iterator it = sysctl_oid_iterator_begin(l); \
634 ((oidp) = sysctl_oid_iterator_next_num_order(&it)); )
636 static struct sysctl_oid
*
637 sysctl_oid_iterator_next_system_order(struct sysctl_oid_iterator
*it
)
639 struct sysctl_oid
*a
= it
->a
;
640 struct sysctl_oid
*b
= it
->b
;
643 it
->a
= SLIST_NEXT(a
, oid_link
);
648 it
->b
= SLIST_NEXT(b
, oid_link
);
655 #define SYSCTL_OID_FOREACH_SYS_ORDER(oidp, l) \
656 for (struct sysctl_oid_iterator it = sysctl_oid_iterator_begin(l); \
657 ((oidp) = sysctl_oid_iterator_next_system_order(&it)); )
662 * These functions implement a presently undocumented interface
663 * used by the sysctl program to walk the tree, and get the type
664 * so it can print the value.
665 * This interface is under work and consideration, and should probably
666 * be killed with a big axe by the first person who can find the time.
667 * (be aware though, that the proper interface isn't as obvious as it
668 * may seem, there are various conflicting requirements.
670 * {0,0} printf the entire MIB-tree.
671 * {0,1,...} return the name of the "..." OID.
672 * {0,2,...} return the next OID.
673 * {0,3} return the OID of the name in "new"
674 * {0,4,...} return the kind & format info for the "..." OID.
678 * sysctl_sysctl_debug_dump_node
680 * Description: Dump debug information for a given sysctl_oid_list at the
681 * given oid depth out to the kernel log, via printf
683 * Parameters: l sysctl_oid_list pointer
684 * i current node depth
688 * Implicit: kernel log, modified
690 * Locks: Assumes sysctl_geometry_lock is held prior to calling
692 * Notes: This function may call itself recursively to resolve Node
693 * values, which potentially have an inferioer sysctl_oid_list
695 * This function is only callable indirectly via the function
696 * sysctl_sysctl_debug()
698 * Bugs: The node depth indentation does not work; this may be an
699 * artifact of leading space removal by the log daemon itself
700 * or some intermediate routine.
703 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
705 struct sysctl_oid
*oidp
;
706 struct sysctl_oid_list
*lp
;
709 SYSCTL_OID_FOREACH_SYS_ORDER(oidp
, l
) {
710 switch (oidp
->oid_kind
& CTLTYPE
) {
714 if (lp
&& SLIST_FIRST(lp
) &&
715 SLIST_FIRST(lp
)->oid_number
== OID_MUTABLE_ANCHOR
) {
737 printf("%*s%-3d[%c%c%c%c%c] %s %s\n", i
, "", oidp
->oid_number
,
738 oidp
->oid_kind
& CTLFLAG_LOCKED
? 'L':' ',
739 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
740 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ',
741 oidp
->oid_kind
& CTLFLAG_PERMANENT
? ' ':'*',
742 oidp
->oid_handler
? 'h' : ' ',
743 what
, oidp
->oid_name
);
745 if ((oidp
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
746 if (!oidp
->oid_handler
) {
747 sysctl_sysctl_debug_dump_node(lp
, i
+ 2);
754 * sysctl_sysctl_debug
756 * Description: This function implements the "sysctl.debug" portion of the
757 * OID space for sysctl.
761 * Parameters: __unused
765 * Implicit: kernel log, modified
767 * Locks: Acquires and then releases a read lock on the
768 * sysctl_geometry_lock
771 sysctl_sysctl_debug(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
772 __unused
int arg2
, __unused
struct sysctl_req
*req
)
774 lck_rw_lock_shared(&sysctl_geometry_lock
);
775 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
776 lck_rw_done(&sysctl_geometry_lock
);
780 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
781 0, 0, sysctl_sysctl_debug
, "-", "");
786 * Description: Convert an OID into a string name; this is used by the user
787 * space sysctl() command line utility; this is done in a purely
788 * advisory capacity (e.g. to provide node names for "sysctl -A"
793 * Parameters: oidp __unused
794 * arg1 A pointer to the OID name list
795 * integer array, beginning at
796 * adjusted option base 2
797 * arg2 The number of elements which
798 * remain in the name array
801 * SYSCTL_OUT:EPERM Permission denied
802 * SYSCTL_OUT:EFAULT Bad user supplied buffer
803 * SYSCTL_OUT:??? Return value from user function
804 * for SYSCTL_PROC leaf node
806 * Implict: Contents of user request buffer, modified
808 * Locks: Acquires and then releases a read lock on the
809 * sysctl_geometry_lock
811 * Notes: SPI (System Programming Interface); this is subject to change
812 * and may not be relied upon by third party applications; use
813 * a subprocess to communicate with the "sysctl" command line
814 * command instead, if you believe you need this functionality.
815 * Preferrably, use sysctlbyname() instead.
817 * Setting of the NULL termination of the output string is
818 * delayed until after the geometry lock is dropped. If there
819 * are no Entries remaining in the OID name list when this
820 * function is called, it will still write out the termination
823 * This function differs from other sysctl functions in that
824 * it can not take an output buffer length of 0 to determine the
825 * space which will be required. It is suggested that the buffer
826 * length be PATH_MAX, and that authors of new sysctl's refrain
827 * from exceeding this string length.
830 sysctl_sysctl_name(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
831 struct sysctl_req
*req
)
833 int *name
= (int *) arg1
;
834 u_int namelen
= arg2
;
836 struct sysctl_oid
*oid
;
837 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
838 char tempbuf
[10] = {};
840 lck_rw_lock_shared(&sysctl_geometry_lock
);
843 snprintf(tempbuf
, sizeof(tempbuf
), "%d", *name
);
845 error
= SYSCTL_OUT(req
, ".", 1);
848 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
851 lck_rw_done(&sysctl_geometry_lock
);
859 SYSCTL_OID_FOREACH_NUM_ORDER(oid
, lsp
) {
860 if (oid
->oid_number
!= *name
) {
865 error
= SYSCTL_OUT(req
, ".", 1);
868 error
= SYSCTL_OUT(req
, oid
->oid_name
,
869 strlen(oid
->oid_name
));
872 lck_rw_done(&sysctl_geometry_lock
);
879 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
883 if (oid
->oid_handler
) {
887 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
892 lck_rw_done(&sysctl_geometry_lock
);
893 return SYSCTL_OUT(req
, "", 1);
896 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_name
, "");
899 * sysctl_sysctl_next_ls
901 * Description: For a given OID name value, return the next consecutive OID
902 * name value within the geometry tree
904 * Parameters: lsp The OID list to look in
905 * name The OID name to start from
906 * namelen The length of the OID name
907 * next Pointer to new oid storage to
909 * len Pointer to receive new OID
910 * length value of storage written
911 * level OID tree depth (used to compute
913 * oidpp Pointer to OID list entry
914 * pointer; used to walk the list
915 * forward across recursion
917 * Returns: 0 Returning a new entry
918 * 1 End of geometry list reached
920 * Implicit: *next Modified to contain the new OID
921 * *len Modified to contain new length
923 * Locks: Assumes sysctl_geometry_lock is held prior to calling
925 * Notes: This function will not return OID values that have special
926 * handlers, since we can not tell wheter these handlers consume
927 * elements from the OID space as parameters. For this reason,
928 * we STRONGLY discourage these types of handlers
931 sysctl_sysctl_next_ls(struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
932 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
934 struct sysctl_oid
*oidp
;
937 SYSCTL_OID_FOREACH_NUM_ORDER(oidp
, lsp
) {
938 *next
= oidp
->oid_number
;
942 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
945 if (oidp
->oid_handler
) {
946 /* We really should call the handler here...*/
949 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
951 if (!SLIST_FIRST(lsp
)) {
952 /* This node had no children - skip it! */
956 if (!sysctl_sysctl_next_ls(lsp
, 0, 0, next
+ 1,
957 len
, level
+ 1, oidpp
)) {
963 if (oidp
->oid_number
< *name
) {
967 if (oidp
->oid_number
> *name
) {
968 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
971 if (oidp
->oid_handler
) {
974 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
975 if (!sysctl_sysctl_next_ls(lsp
, name
+ 1, namelen
- 1,
976 next
+ 1, len
, level
+ 1, oidpp
)) {
981 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
985 if (oidp
->oid_handler
) {
989 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
990 if (!sysctl_sysctl_next_ls(lsp
, name
+ 1, namelen
- 1, next
+ 1,
991 len
, level
+ 1, oidpp
)) {
1002 * sysctl_sysctl_next
1004 * Description: This is an iterator function designed to iterate the oid tree
1005 * and provide a list of OIDs for use by the user space "sysctl"
1010 * Parameters: oidp __unused
1011 * arg1 Pointer to start OID name
1012 * arg2 Start OID name length
1013 * req Pointer to user request buffer
1015 * Returns: 0 Success
1016 * ENOENT Reached end of OID space
1017 * SYSCTL_OUT:EPERM Permission denied
1018 * SYSCTL_OUT:EFAULT Bad user supplied buffer
1019 * SYSCTL_OUT:??? Return value from user function
1020 * for SYSCTL_PROC leaf node
1022 * Implict: Contents of user request buffer, modified
1024 * Locks: Acquires and then releases a read lock on the
1025 * sysctl_geometry_lock
1027 * Notes: SPI (System Programming Interface); this is subject to change
1028 * and may not be relied upon by third party applications; use
1029 * a subprocess to communicate with the "sysctl" command line
1030 * command instead, if you believe you need this functionality.
1031 * Preferrably, use sysctlbyname() instead.
1033 * This function differs from other sysctl functions in that
1034 * it can not take an output buffer length of 0 to determine the
1035 * space which will be required. It is suggested that the buffer
1036 * length be PATH_MAX, and that authors of new sysctl's refrain
1037 * from exceeding this string length.
1040 sysctl_sysctl_next(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1041 struct sysctl_req
*req
)
1043 int *name
= (int *) arg1
;
1044 u_int namelen
= arg2
;
1046 struct sysctl_oid
*oid
;
1047 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1048 int newoid
[CTL_MAXNAME
] = {};
1050 lck_rw_lock_shared(&sysctl_geometry_lock
);
1051 i
= sysctl_sysctl_next_ls(lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
1052 lck_rw_done(&sysctl_geometry_lock
);
1056 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof(int));
1060 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_next
, "");
1065 * Description: Support function for use by sysctl_sysctl_name2oid(); looks
1066 * up an OID name given a string name.
1068 * Parameters: name NULL terminated string name
1069 * oid Pointer to receive OID name
1070 * len Pointer to receive OID length
1071 * pointer value (see "Notes")
1073 * Returns: 0 Success
1074 * ENOENT Entry not found
1076 * Implicit: *oid Modified to contain OID value
1077 * *len Modified to contain OID length
1079 * Locks: Assumes sysctl_geometry_lock is held prior to calling
1082 name2oid(char *name
, int *oid
, size_t *len
)
1084 struct sysctl_oid_iterator it
;
1085 struct sysctl_oid
*oidp
;
1093 p
= name
+ strlen(name
) - 1;
1100 for (p
= name
; *p
&& *p
!= '.'; p
++) {
1108 it
= sysctl_oid_iterator_begin(&sysctl__children
);
1109 oidp
= sysctl_oid_iterator_next_system_order(&it
);
1111 while (oidp
&& *len
< CTL_MAXNAME
) {
1112 if (strcmp(name
, oidp
->oid_name
)) {
1113 oidp
= sysctl_oid_iterator_next_system_order(&it
);
1116 *oid
++ = oidp
->oid_number
;
1123 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
) {
1127 if (oidp
->oid_handler
) {
1131 it
= sysctl_oid_iterator_begin(oidp
->oid_arg1
);
1132 oidp
= sysctl_oid_iterator_next_system_order(&it
);
1134 *p
= i
; /* restore */
1136 for (p
= name
; *p
&& *p
!= '.'; p
++) {
1148 * sysctl_sysctl_name2oid
1150 * Description: Translate a string name to an OID name value; this is used by
1151 * the sysctlbyname() function as well as by the "sysctl" command
1156 * Parameters: oidp __unused
1159 * req Request structure
1161 * Returns: ENOENT Input length too short
1162 * ENAMETOOLONG Input length too long
1163 * ENOMEM Could not allocate work area
1164 * SYSCTL_IN/OUT:EPERM Permission denied
1165 * SYSCTL_IN/OUT:EFAULT Bad user supplied buffer
1166 * SYSCTL_IN/OUT:??? Return value from user function
1167 * name2oid:ENOENT Not found
1169 * Implicit: *req Contents of request, modified
1171 * Locks: Acquires and then releases a read lock on the
1172 * sysctl_geometry_lock
1174 * Notes: SPI (System Programming Interface); this is subject to change
1175 * and may not be relied upon by third party applications; use
1176 * a subprocess to communicate with the "sysctl" command line
1177 * command instead, if you believe you need this functionality.
1178 * Preferrably, use sysctlbyname() instead.
1180 * This function differs from other sysctl functions in that
1181 * it can not take an output buffer length of 0 to determine the
1182 * space which will be required. It is suggested that the buffer
1183 * length be PATH_MAX, and that authors of new sysctl's refrain
1184 * from exceeding this string length.
1187 sysctl_sysctl_name2oid(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
1188 __unused
int arg2
, struct sysctl_req
*req
)
1191 int error
, oid
[CTL_MAXNAME
] = {};
1192 size_t len
= 0; /* set by name2oid() */
1194 if (req
->newlen
< 1) {
1197 if (req
->newlen
>= MAXPATHLEN
) { /* XXX arbitrary, undocumented */
1198 return ENAMETOOLONG
;
1201 p
= kheap_alloc(KHEAP_TEMP
, req
->newlen
+ 1, Z_WAITOK
);
1206 error
= SYSCTL_IN(req
, p
, req
->newlen
);
1208 kheap_free(KHEAP_TEMP
, p
, req
->newlen
+ 1);
1212 p
[req
->newlen
] = '\0';
1215 * Note: We acquire and release the geometry lock here to
1216 * avoid making name2oid needlessly complex.
1218 lck_rw_lock_shared(&sysctl_geometry_lock
);
1219 error
= name2oid(p
, oid
, &len
);
1220 lck_rw_done(&sysctl_geometry_lock
);
1222 kheap_free(KHEAP_TEMP
, p
, req
->newlen
+ 1);
1228 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
1232 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_KERN
| CTLFLAG_LOCKED
, 0, 0,
1233 sysctl_sysctl_name2oid
, "I", "");
1236 * sysctl_sysctl_oidfmt
1238 * Description: For a given OID name, determine the format of the data which
1239 * is associated with it. This is used by the "sysctl" command
1244 * Parameters: oidp __unused
1245 * arg1 The OID name to look up
1246 * arg2 The length of the OID name
1247 * req Pointer to user request buffer
1249 * Returns: 0 Success
1250 * EISDIR Malformed request
1251 * ENOENT No such OID name
1252 * SYSCTL_OUT:EPERM Permission denied
1253 * SYSCTL_OUT:EFAULT Bad user supplied buffer
1254 * SYSCTL_OUT:??? Return value from user function
1256 * Implict: Contents of user request buffer, modified
1258 * Locks: Acquires and then releases a read lock on the
1259 * sysctl_geometry_lock
1261 * Notes: SPI (System Programming Interface); this is subject to change
1262 * and may not be relied upon by third party applications; use
1263 * a subprocess to communicate with the "sysctl" command line
1264 * command instead, if you believe you need this functionality.
1266 * This function differs from other sysctl functions in that
1267 * it can not take an output buffer length of 0 to determine the
1268 * space which will be required. It is suggested that the buffer
1269 * length be PATH_MAX, and that authors of new sysctl's refrain
1270 * from exceeding this string length.
1273 sysctl_sysctl_oidfmt(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1274 struct sysctl_req
*req
)
1276 int *name
= (int *) arg1
;
1277 int error
= ENOENT
; /* default error: not found */
1278 u_int namelen
= arg2
;
1280 struct sysctl_oid_iterator it
;
1281 struct sysctl_oid
*oid
;
1283 lck_rw_lock_shared(&sysctl_geometry_lock
);
1285 it
= sysctl_oid_iterator_begin(&sysctl__children
);
1286 oid
= sysctl_oid_iterator_next_system_order(&it
);
1289 while (oid
&& indx
< CTL_MAXNAME
) {
1290 if (oid
->oid_number
== name
[indx
]) {
1292 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1293 if (oid
->oid_handler
) {
1296 if (indx
== namelen
) {
1299 it
= sysctl_oid_iterator_begin(oid
->oid_arg1
);
1300 oid
= sysctl_oid_iterator_next_system_order(&it
);
1302 if (indx
!= namelen
) {
1309 oid
= sysctl_oid_iterator_next_system_order(&it
);
1316 if (!oid
->oid_fmt
) {
1319 error
= SYSCTL_OUT(req
,
1320 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
1322 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
1323 strlen(oid
->oid_fmt
) + 1);
1326 lck_rw_done(&sysctl_geometry_lock
);
1330 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_oidfmt
, "");
1334 * Default "handler" functions.
1338 * Handle an int, signed or unsigned.
1340 * a variable: point arg1 at it.
1341 * a constant: pass it in arg2.
1345 sysctl_handle_int(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1346 struct sysctl_req
*req
)
1348 return sysctl_io_number(req
, arg1
? *(int*)arg1
: arg2
, sizeof(int), arg1
, NULL
);
1352 * Handle a long, signed or unsigned. arg1 points to it.
1356 sysctl_handle_long(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1357 __unused
int arg2
, struct sysctl_req
*req
)
1362 return sysctl_io_number(req
, *(long*)arg1
, sizeof(long), arg1
, NULL
);
1366 * Handle a quad, signed or unsigned. arg1 points to it.
1370 sysctl_handle_quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1371 __unused
int arg2
, struct sysctl_req
*req
)
1376 return sysctl_io_number(req
, *(long long*)arg1
, sizeof(long long), arg1
, NULL
);
1380 * Expose an int value as a quad.
1382 * This interface allows us to support interfaces defined
1383 * as using quad values while the implementation is still
1387 sysctl_handle_int2quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1388 __unused
int arg2
, struct sysctl_req
*req
)
1397 val
= (long long)*(int *)arg1
;
1398 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
1400 if (error
|| !req
->newptr
) {
1404 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
1407 * Value must be representable; check by
1408 * casting and then casting back.
1411 if ((long long)newval
!= val
) {
1414 *(int *)arg1
= newval
;
1421 * Handle our generic '\0' terminated 'C' string.
1423 * a variable string: point arg1 at it, arg2 is max length.
1424 * a constant string: point arg1 at it, arg2 is zero.
1428 sysctl_handle_string( __unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1429 struct sysctl_req
*req
)
1431 return sysctl_io_string(req
, arg1
, arg2
, 0, NULL
);
1435 * Handle any kind of opaque data.
1436 * arg1 points to it, arg2 is the size.
1440 sysctl_handle_opaque(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1441 struct sysctl_req
*req
)
1443 return sysctl_io_opaque(req
, arg1
, arg2
, NULL
);
1447 * Transfer functions to/from kernel space.
1450 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
1456 if (i
> req
->oldlen
- req
->oldidx
) {
1457 i
= req
->oldlen
- req
->oldidx
;
1460 bcopy((const void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
1464 if (req
->oldptr
&& i
!= l
) {
1471 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
1476 if (req
->newlen
- req
->newidx
< l
) {
1479 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
1485 kernel_sysctl(struct proc
*p
, int *name
, size_t namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
1488 struct sysctl_req req
;
1491 * Construct request.
1493 bzero(&req
, sizeof req
);
1496 req
.oldlen
= *oldlenp
;
1499 req
.oldptr
= CAST_USER_ADDR_T(old
);
1502 req
.newlen
= newlen
;
1503 req
.newptr
= CAST_USER_ADDR_T(new);
1505 req
.oldfunc
= sysctl_old_kernel
;
1506 req
.newfunc
= sysctl_new_kernel
;
1509 /* make the request */
1510 error
= sysctl_root(TRUE
, FALSE
, NULL
, 0, name
, namelen
, &req
);
1512 if (error
&& error
!= ENOMEM
) {
1517 *oldlenp
= req
.oldidx
;
1524 * Transfer function to/from user space.
1527 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
1533 if (req
->oldlen
- req
->oldidx
< l
) {
1537 if (i
> req
->oldlen
- req
->oldidx
) {
1538 i
= req
->oldlen
- req
->oldidx
;
1541 error
= copyout((const void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
1548 if (req
->oldptr
&& i
< l
) {
1555 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
1562 if (req
->newlen
- req
->newidx
< l
) {
1565 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
1570 #define WRITE_EXPERIMENT_FACTORS_ENTITLEMENT "com.apple.private.write-kr-experiment-factors"
1572 * Is the current task allowed to write to experiment factors?
1573 * tasks with the WRITE_EXPERIMENT_FACTORS_ENTITLEMENT are always allowed to write these.
1574 * In the development / debug kernel we also allow root to write them.
1577 can_write_experiment_factors(__unused
struct sysctl_req
*req
)
1579 if (IOTaskHasEntitlement(current_task(), WRITE_EXPERIMENT_FACTORS_ENTITLEMENT
)) {
1582 #if DEBUG || DEVELOPMENT
1583 return !proc_suser(req
->p
);
1586 #endif /* DEBUG || DEVELOPMENT */
1590 * Traverse our tree, and find the right node, execute whatever it points
1591 * at, and return the resulting error code.
1595 sysctl_root(boolean_t from_kernel
, boolean_t string_is_canonical
,
1596 char *namestring
, size_t namestringlen
,
1597 int *name
, size_t namelen
, struct sysctl_req
*req
)
1601 struct sysctl_oid_iterator it
;
1602 struct sysctl_oid
*oid
;
1603 sysctl_handler_t oid_handler
= NULL
;
1605 boolean_t unlocked_node_found
= FALSE
;
1606 boolean_t namestring_started
= FALSE
;
1608 /* Get the read lock on the geometry */
1609 lck_rw_lock_shared(&sysctl_geometry_lock
);
1611 if (string_is_canonical
) {
1612 /* namestring is actually canonical, name/namelen needs to be populated */
1613 error
= name2oid(namestring
, name
, &namelen
);
1619 it
= sysctl_oid_iterator_begin(&sysctl__children
);
1620 oid
= sysctl_oid_iterator_next_system_order(&it
);
1623 while (oid
&& indx
< CTL_MAXNAME
) {
1624 if (oid
->oid_number
== name
[indx
]) {
1625 if (!from_kernel
&& !string_is_canonical
) {
1626 if (namestring_started
) {
1627 if (strlcat(namestring
, ".", namestringlen
) >= namestringlen
) {
1628 error
= ENAMETOOLONG
;
1633 if (strlcat(namestring
, oid
->oid_name
, namestringlen
) >= namestringlen
) {
1634 error
= ENAMETOOLONG
;
1637 namestring_started
= TRUE
;
1641 if (!(oid
->oid_kind
& CTLFLAG_LOCKED
)) {
1642 unlocked_node_found
= TRUE
;
1644 if (oid
->oid_kind
& CTLFLAG_NOLOCK
) {
1648 * For SYSCTL_PROC() functions which are for sysctl's
1649 * which have parameters at the end of their OID
1650 * space, you need to OR CTLTYPE_NODE into their
1653 * NOTE: For binary backward compatibility ONLY! Do
1654 * NOT add new sysctl's that do this! Existing
1655 * sysctl's which do this will eventually have
1656 * compatibility code in user space, and this method
1657 * will become unsupported.
1659 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1660 if (oid
->oid_handler
) {
1663 if (indx
== namelen
) {
1668 it
= sysctl_oid_iterator_begin(oid
->oid_arg1
);
1669 oid
= sysctl_oid_iterator_next_system_order(&it
);
1671 if (indx
!= namelen
) {
1678 oid
= sysctl_oid_iterator_next_system_order(&it
);
1686 * indx is the index of the first remaining OID name,
1687 * for sysctls that take them as arguments
1689 if (!from_kernel
&& !string_is_canonical
&& (indx
< namelen
)) {
1693 for (indx2
= indx
; indx2
< namelen
; indx2
++) {
1694 snprintf(tempbuf
, sizeof(tempbuf
), "%d", name
[indx2
]);
1696 if (namestring_started
) {
1697 if (strlcat(namestring
, ".", namestringlen
) >= namestringlen
) {
1698 error
= ENAMETOOLONG
;
1703 if (strlcat(namestring
, tempbuf
, namestringlen
) >= namestringlen
) {
1704 error
= ENAMETOOLONG
;
1707 namestring_started
= TRUE
;
1711 /* If writing isn't allowed */
1712 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
1713 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
1719 * If we're inside the kernel, the OID must be marked as kernel-valid.
1721 if (from_kernel
&& !(oid
->oid_kind
& CTLFLAG_KERN
)) {
1726 if (req
->newptr
&& req
->p
) {
1727 if (oid
->oid_kind
& CTLFLAG_EXPERIMENT
) {
1729 * Experiment factors have different permissions since they need to be
1730 * writable by procs with WRITE_EXPERIMENT_FACTORS_ENTITLEMENT.
1732 if (!can_write_experiment_factors(req
)) {
1738 * This is where legacy enforcement of permissions occurs. If the
1739 * flag does not say CTLFLAG_ANYBODY, then we prohibit anyone but
1740 * root from writing new values down. If local enforcement happens
1741 * at the leaf node, then it needs to be set as CTLFLAG_ANYBODY. In
1742 * addition, if the leaf node is set this way, then in order to do
1743 * specific enforcement, it has to be of type SYSCTL_PROC.
1745 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
1746 (error
= proc_suser(req
->p
))) {
1753 * sysctl_unregister_oid() may change the handler value, so grab it
1756 oid_handler
= oid
->oid_handler
;
1763 * Reference the OID and drop the geometry lock; this prevents the
1764 * OID from being deleted out from under the handler call, but does
1765 * not prevent other calls into handlers or calls to manage the
1766 * geometry elsewhere from blocking...
1768 if ((oid
->oid_kind
& CTLFLAG_PERMANENT
) == 0) {
1769 OSAddAtomic(1, &oid
->oid_refcnt
);
1772 lck_rw_done(&sysctl_geometry_lock
);
1776 error
= mac_system_check_sysctlbyname(kauth_cred_get(),
1791 * ...however, we still have to grab the mutex for those calls which
1792 * may be into code whose reentrancy is protected by it.
1794 if (unlocked_node_found
) {
1795 lck_mtx_lock(&sysctl_unlocked_node_lock
);
1798 #if defined(HAS_APPLE_PAC)
1800 * oid_handler is signed address-discriminated by sysctl_register_oid().
1802 oid_handler
= ptrauth_auth_and_resign(oid_handler
,
1803 ptrauth_key_function_pointer
,
1804 ptrauth_blend_discriminator(&oid
->oid_handler
,
1805 os_hash_kernel_pointer(oid
->oid_arg1
)),
1806 ptrauth_key_function_pointer
,
1807 ptrauth_function_pointer_type_discriminator(typeof(oid_handler
)));
1808 #endif /* defined(HAS_APPLE_PAC) */
1810 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1811 i
= oid_handler(oid
, name
+ indx
, (int)(namelen
- indx
), req
);
1813 i
= oid_handler(oid
, oid
->oid_arg1
, oid
->oid_arg2
, req
);
1817 if (unlocked_node_found
) {
1818 lck_mtx_unlock(&sysctl_unlocked_node_lock
);
1822 /* only used from another CONFIG_MACF block */
1827 * This is tricky... we re-grab the geometry lock in order to drop
1828 * the reference and wake on the address; since the geometry
1829 * lock is a reader/writer lock rather than a mutex, we have to
1830 * wake on all apparent 1->0 transitions. This abuses the drop
1831 * after the reference decrement in order to wake any lck_rw_sleep()
1832 * in progress in sysctl_unregister_oid() that slept because of a
1833 * non-zero reference count.
1835 * Note: OSAddAtomic() is defined to return the previous value;
1836 * we use this and the fact that the lock itself is a
1837 * barrier to avoid waking every time through on "hot"
1840 lck_rw_lock_shared(&sysctl_geometry_lock
);
1842 if ((oid
->oid_kind
& CTLFLAG_PERMANENT
) == 0) {
1843 if (OSAddAtomic(-1, &oid
->oid_refcnt
) == 1) {
1844 wakeup(&oid
->oid_refcnt
);
1849 lck_rw_done(&sysctl_geometry_lock
);
1854 sysctl_create_user_req(struct sysctl_req
*req
, struct proc
*p
, user_addr_t oldp
,
1855 size_t oldlen
, user_addr_t newp
, size_t newlen
)
1857 bzero(req
, sizeof(*req
));
1861 req
->oldlen
= oldlen
;
1865 req
->newlen
= newlen
;
1869 req
->oldfunc
= sysctl_old_user
;
1870 req
->newfunc
= sysctl_new_user
;
1877 sysctl(proc_t p
, struct sysctl_args
*uap
, __unused
int32_t *retval
)
1879 int error
, new_error
;
1880 size_t oldlen
= 0, newlen
;
1881 int name
[CTL_MAXNAME
];
1882 struct sysctl_req req
;
1884 size_t namestringlen
= MAXPATHLEN
;
1887 * all top-level sysctl names are non-terminal
1889 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2) {
1892 error
= copyin(uap
->name
, &name
[0], uap
->namelen
* sizeof(int));
1897 AUDIT_ARG(ctlname
, name
, uap
->namelen
);
1899 if (uap
->newlen
> SIZE_T_MAX
) {
1902 newlen
= (size_t)uap
->newlen
;
1904 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1905 uint64_t oldlen64
= fuulong(uap
->oldlenp
);
1908 * If more than 4G, clamp to 4G
1910 if (oldlen64
> SIZE_T_MAX
) {
1911 oldlen
= SIZE_T_MAX
;
1913 oldlen
= (size_t)oldlen64
;
1917 sysctl_create_user_req(&req
, p
, uap
->old
, oldlen
, uap
->new, newlen
);
1919 /* Guess that longest length for the passed-in MIB, if we can be more aggressive than MAXPATHLEN */
1920 if (uap
->namelen
== 2) {
1921 if (name
[0] == CTL_KERN
&& name
[1] < KERN_MAXID
) {
1922 namestringlen
= 32; /* "kern.speculative_reads_disabled" */
1923 } else if (name
[0] == CTL_HW
&& name
[1] < HW_MAXID
) {
1924 namestringlen
= 32; /* "hw.cachelinesize_compat" */
1928 namestring
= kheap_alloc(KHEAP_TEMP
, namestringlen
, Z_WAITOK
);
1934 error
= userland_sysctl(FALSE
, namestring
, namestringlen
, name
, uap
->namelen
, &req
, &oldlen
);
1936 kheap_free(KHEAP_TEMP
, namestring
, namestringlen
);
1938 if ((error
) && (error
!= ENOMEM
)) {
1943 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1945 * Only overwrite the old error value on a new error
1947 new_error
= suulong(uap
->oldlenp
, oldlen
);
1957 // sysctlbyname is also exported as KPI to kexts
1958 // and the syscall name cannot conflict with it
1960 sys_sysctlbyname(proc_t p
, struct sysctlbyname_args
*uap
, __unused
int32_t *retval
)
1962 int error
, new_error
;
1963 size_t oldlen
= 0, newlen
;
1966 struct sysctl_req req
;
1967 int oid
[CTL_MAXNAME
];
1969 if (uap
->namelen
>= MAXPATHLEN
) { /* XXX arbitrary, undocumented */
1970 return ENAMETOOLONG
;
1972 namelen
= (size_t)uap
->namelen
;
1974 name
= kheap_alloc(KHEAP_TEMP
, namelen
+ 1, Z_WAITOK
);
1979 error
= copyin(uap
->name
, name
, namelen
);
1981 kheap_free(KHEAP_TEMP
, name
, namelen
+ 1);
1984 name
[namelen
] = '\0';
1987 * AUDIT_ARG(ctlname, name, uap->namelen);
1990 if (uap
->newlen
> SIZE_T_MAX
) {
1991 kheap_free(KHEAP_TEMP
, name
, namelen
+ 1);
1994 newlen
= (size_t)uap
->newlen
;
1996 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
1997 uint64_t oldlen64
= fuulong(uap
->oldlenp
);
2000 * If more than 4G, clamp to 4G
2002 if (oldlen64
> SIZE_T_MAX
) {
2003 oldlen
= SIZE_T_MAX
;
2005 oldlen
= (size_t)oldlen64
;
2009 sysctl_create_user_req(&req
, p
, uap
->old
, oldlen
, uap
->new, newlen
);
2011 error
= userland_sysctl(TRUE
, name
, namelen
+ 1, oid
, CTL_MAXNAME
, &req
, &oldlen
);
2013 kheap_free(KHEAP_TEMP
, name
, namelen
+ 1);
2015 if ((error
) && (error
!= ENOMEM
)) {
2019 if (uap
->oldlenp
!= USER_ADDR_NULL
) {
2021 * Only overwrite the old error value on a new error
2023 new_error
= suulong(uap
->oldlenp
, oldlen
);
2034 * This is used from various compatibility syscalls too. That's why name
2035 * must be in kernel space.
2038 userland_sysctl(boolean_t string_is_canonical
,
2039 char *namestring
, size_t namestringlen
,
2040 int *name
, u_int namelen
, struct sysctl_req
*req
,
2044 struct sysctl_req req2
;
2047 /* if EAGAIN, reset output cursor */
2049 if (!string_is_canonical
) {
2050 namestring
[0] = '\0';
2053 error
= sysctl_root(FALSE
, string_is_canonical
, namestring
, namestringlen
, name
, namelen
, &req2
);
2054 } while (error
== EAGAIN
);
2056 if (error
&& error
!= ENOMEM
) {
2061 if (req2
.oldptr
&& req2
.oldidx
> req2
.oldlen
) {
2062 *retval
= req2
.oldlen
;
2064 *retval
= req2
.oldidx
;
2071 * Kernel versions of the userland sysctl helper functions.
2073 * These allow sysctl to be used in the same fashion in both
2074 * userland and the kernel.
2076 * Note that some sysctl handlers use copyin/copyout, which
2077 * may not work correctly.
2079 * The "sysctlbyname" KPI for use by kexts is aliased to this function.
2083 kernel_sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
2085 int oid
[CTL_MAXNAME
];
2086 int name2mib_oid
[2];
2090 /* look up the OID with magic service node */
2091 name2mib_oid
[0] = 0;
2092 name2mib_oid
[1] = 3;
2094 oidlen
= sizeof(oid
);
2095 error
= kernel_sysctl(current_proc(), name2mib_oid
, 2, oid
, &oidlen
, __DECONST(void *, name
), strlen(name
));
2096 oidlen
/= sizeof(int);
2097 if (oidlen
> UINT_MAX
) {
2101 /* now use the OID */
2103 error
= kernel_sysctl(current_proc(), oid
, (u_int
)oidlen
, oldp
, oldlenp
, newp
, newlen
);
2109 scalable_counter_sysctl_handler SYSCTL_HANDLER_ARGS
2111 #pragma unused(arg2, oidp)
2112 scalable_counter_t counter
= *(scalable_counter_t
*) arg1
;
2113 uint64_t value
= counter_load(&counter
);
2114 return SYSCTL_OUT(req
, &value
, sizeof(value
));
2117 #define X(name, T) \
2119 experiment_factor_##name##_handler SYSCTL_HANDLER_ARGS \
2121 int error, changed = 0; \
2123 T new_value, current_value; \
2124 struct experiment_spec *spec = (struct experiment_spec *) arg1; \
2128 ptr = (T *)(spec->ptr); \
2129 current_value = *ptr; \
2130 error = sysctl_io_number(req, current_value, sizeof(T), &new_value, &changed); \
2135 if (new_value < (T) spec->min_value || new_value > (T) spec->max_value) { \
2138 if (os_atomic_cmpxchg(&spec->modified, false, true, acq_rel)) { \
2139 spec->original_value = current_value; \
2141 os_atomic_store_wide(ptr, new_value, relaxed); \
2146 experiment_factor_numeric_types