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