2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Mike Karels at Berkeley Software Design, Inc.
8 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
9 * project, to make these variables more userfriendly.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
41 #include "opt_capsicum.h"
42 #include "opt_compat.h"
43 #include "opt_ktrace.h"
45 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/capsicum.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
51 #include <sys/malloc.h>
56 #include <sys/mutex.h>
57 #include <sys/rmlock.h>
60 #include <sys/sysproto.h>
63 #include <sys/ktrace.h>
68 #include <security/mac/mac_framework.h>
71 #include <vm/vm_extern.h>
73 static MALLOC_DEFINE(M_SYSCTL
, "sysctl", "sysctl internal magic");
74 static MALLOC_DEFINE(M_SYSCTLOID
, "sysctloid", "sysctl dynamic oids");
75 static MALLOC_DEFINE(M_SYSCTLTMP
, "sysctltmp", "sysctl temp output buffer");
78 * The sysctllock protects the MIB tree. It also protects sysctl
79 * contexts used with dynamic sysctls. The sysctl_register_oid() and
80 * sysctl_unregister_oid() routines require the sysctllock to already
81 * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
82 * provided for the few places in the kernel which need to use that
83 * API rather than using the dynamic API. Use of the dynamic API is
84 * strongly encouraged for most code.
86 * The sysctlmemlock is used to limit the amount of user memory wired for
87 * sysctl requests. This is implemented by serializing any userland
88 * sysctl requests larger than a single page via an exclusive lock.
90 static struct rmlock sysctllock
;
91 static struct sx sysctlmemlock
;
93 #define SYSCTL_WLOCK() rm_wlock(&sysctllock)
94 #define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock)
95 #define SYSCTL_RLOCK(tracker) rm_rlock(&sysctllock, (tracker))
96 #define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
97 #define SYSCTL_WLOCKED() rm_wowned(&sysctllock)
98 #define SYSCTL_ASSERT_LOCKED() rm_assert(&sysctllock, RA_LOCKED)
99 #define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
100 #define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
101 #define SYSCTL_INIT() rm_init_flags(&sysctllock, "sysctl lock", \
103 #define SYSCTL_SLEEP(ch, wmesg, timo) \
104 rm_sleep(ch, &sysctllock, 0, wmesg, timo)
106 static int sysctl_root(SYSCTL_HANDLER_ARGS
);
109 struct sysctl_oid_list sysctl__children
= SLIST_HEAD_INITIALIZER(&sysctl__children
);
111 static int sysctl_remove_oid_locked(struct sysctl_oid
*oidp
, int del
,
113 static int sysctl_old_kernel(struct sysctl_req
*, const void *, size_t);
114 static int sysctl_new_kernel(struct sysctl_req
*, void *, size_t);
116 static struct sysctl_oid
*
117 sysctl_find_oidname(const char *name
, struct sysctl_oid_list
*list
)
119 struct sysctl_oid
*oidp
;
121 SYSCTL_ASSERT_LOCKED();
122 SLIST_FOREACH(oidp
, list
, oid_link
) {
123 if (strcmp(oidp
->oid_name
, name
) == 0) {
131 * Initialization of the MIB tree.
133 * Order by number in each list.
150 sysctl_root_handler_locked(struct sysctl_oid
*oid
, void *arg1
, intmax_t arg2
,
151 struct sysctl_req
*req
, struct rm_priotracker
*tracker
)
155 if (oid
->oid_kind
& CTLFLAG_DYN
)
156 atomic_add_int(&oid
->oid_running
, 1);
159 SYSCTL_RUNLOCK(tracker
);
163 if (!(oid
->oid_kind
& CTLFLAG_MPSAFE
))
165 error
= oid
->oid_handler(oid
, arg1
, arg2
, req
);
166 if (!(oid
->oid_kind
& CTLFLAG_MPSAFE
))
170 SYSCTL_RLOCK(tracker
);
174 if (oid
->oid_kind
& CTLFLAG_DYN
) {
175 if (atomic_fetchadd_int(&oid
->oid_running
, -1) == 1 &&
176 (oid
->oid_kind
& CTLFLAG_DYING
) != 0)
177 wakeup(&oid
->oid_running
);
184 sysctl_load_tunable_by_oid_locked(struct sysctl_oid
*oidp
)
186 struct sysctl_req req
;
187 struct sysctl_oid
*curr
;
190 ssize_t rem
= sizeof(path
);
203 for (curr
= oidp
; curr
!= NULL
; curr
= SYSCTL_PARENT(curr
)) {
204 len
= strlen(curr
->oid_name
);
209 printf("OID path exceeds %d bytes\n", (int)sizeof(path
));
212 memcpy(path
+ rem
, curr
->oid_name
, len
);
214 path
[rem
+ len
] = '.';
217 memset(&req
, 0, sizeof(req
));
220 req
.oldfunc
= sysctl_old_kernel
;
221 req
.newfunc
= sysctl_new_kernel
;
222 req
.lock
= REQ_UNWIRED
;
224 switch (oidp
->oid_kind
& CTLTYPE
) {
226 if (getenv_int(path
+ rem
, &val_int
) == 0)
228 req
.newlen
= sizeof(val_int
);
229 req
.newptr
= &val_int
;
232 if (getenv_uint(path
+ rem
, (unsigned int *)&val_int
) == 0)
234 req
.newlen
= sizeof(val_int
);
235 req
.newptr
= &val_int
;
238 if (getenv_long(path
+ rem
, &val_long
) == 0)
240 req
.newlen
= sizeof(val_long
);
241 req
.newptr
= &val_long
;
244 if (getenv_ulong(path
+ rem
, (unsigned long *)&val_long
) == 0)
246 req
.newlen
= sizeof(val_long
);
247 req
.newptr
= &val_long
;
250 if (getenv_int(path
+ rem
, &val_int
) == 0)
253 req
.newlen
= sizeof(val_8
);
257 if (getenv_int(path
+ rem
, &val_int
) == 0)
260 req
.newlen
= sizeof(val_16
);
261 req
.newptr
= &val_16
;
264 if (getenv_long(path
+ rem
, &val_long
) == 0)
267 req
.newlen
= sizeof(val_32
);
268 req
.newptr
= &val_32
;
271 if (getenv_quad(path
+ rem
, &val_quad
) == 0)
274 req
.newlen
= sizeof(val_64
);
275 req
.newptr
= &val_64
;
278 if (getenv_uint(path
+ rem
, (unsigned int *)&val_int
) == 0)
281 req
.newlen
= sizeof(val_8
);
285 if (getenv_uint(path
+ rem
, (unsigned int *)&val_int
) == 0)
288 req
.newlen
= sizeof(val_16
);
289 req
.newptr
= &val_16
;
292 if (getenv_ulong(path
+ rem
, (unsigned long *)&val_long
) == 0)
295 req
.newlen
= sizeof(val_32
);
296 req
.newptr
= &val_32
;
299 /* XXX there is no getenv_uquad() */
300 if (getenv_quad(path
+ rem
, &val_quad
) == 0)
303 req
.newlen
= sizeof(val_64
);
304 req
.newptr
= &val_64
;
307 penv
= kern_getenv(path
+ rem
);
310 req
.newlen
= strlen(penv
);
316 error
= sysctl_root_handler_locked(oidp
, oidp
->oid_arg1
,
317 oidp
->oid_arg2
, &req
, NULL
);
319 printf("Setting sysctl %s failed: %d\n", path
+ rem
, error
);
325 sysctl_register_oid(struct sysctl_oid
*oidp
)
327 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
328 struct sysctl_oid
*p
;
329 struct sysctl_oid
*q
;
334 * First check if another oid with the same name already
335 * exists in the parent's list.
337 SYSCTL_ASSERT_WLOCKED();
338 p
= sysctl_find_oidname(oidp
->oid_name
, parent
);
340 if ((p
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
344 printf("can't re-use a leaf (%s)!\n", p
->oid_name
);
348 /* get current OID number */
349 oid_number
= oidp
->oid_number
;
352 #error "OID_AUTO is expected to be a negative value"
355 * Any negative OID number qualifies as OID_AUTO. Valid OID
356 * numbers should always be positive.
358 * NOTE: DO NOT change the starting value here, change it in
359 * <sys/sysctl.h>, and make sure it is at least 256 to
360 * accomodate e.g. net.inet.raw as a static sysctl node.
362 if (oid_number
< 0) {
366 * By decrementing the next OID number we spend less
367 * time inserting the OIDs into a sorted list.
369 if (--newoid
< CTL_AUTO_START
)
376 * Insert the OID into the parent's list sorted by OID number.
380 SLIST_FOREACH(p
, parent
, oid_link
) {
381 /* check if the current OID number is in use */
382 if (oid_number
== p
->oid_number
) {
383 /* get the next valid OID number */
384 if (oid_number
< CTL_AUTO_START
||
385 oid_number
== 0x7fffffff) {
386 /* wraparound - restart */
387 oid_number
= CTL_AUTO_START
;
388 /* don't loop forever */
390 panic("sysctl: Out of OID numbers\n");
395 } else if (oid_number
< p
->oid_number
)
399 /* check for non-auto OID number collision */
400 if (oidp
->oid_number
>= 0 && oidp
->oid_number
< CTL_AUTO_START
&&
401 oid_number
>= CTL_AUTO_START
) {
402 printf("sysctl: OID number(%d) is already in use for '%s'\n",
403 oidp
->oid_number
, oidp
->oid_name
);
405 /* update the OID number, if any */
406 oidp
->oid_number
= oid_number
;
408 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
410 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
412 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
&&
414 (oidp
->oid_kind
& CTLFLAG_VNET
) == 0 &&
416 (oidp
->oid_kind
& CTLFLAG_TUN
) != 0 &&
417 (oidp
->oid_kind
& CTLFLAG_NOFETCH
) == 0) {
418 /* only fetch value once */
419 oidp
->oid_kind
|= CTLFLAG_NOFETCH
;
420 /* try to fetch value from kernel environment */
421 sysctl_load_tunable_by_oid_locked(oidp
);
426 sysctl_unregister_oid(struct sysctl_oid
*oidp
)
428 struct sysctl_oid
*p
;
431 SYSCTL_ASSERT_WLOCKED();
433 if (oidp
->oid_number
== OID_AUTO
) {
436 SLIST_FOREACH(p
, oidp
->oid_parent
, oid_link
) {
438 SLIST_REMOVE(oidp
->oid_parent
, oidp
,
439 sysctl_oid
, oid_link
);
447 * This can happen when a module fails to register and is
448 * being unloaded afterwards. It should not be a panic()
452 printf("%s: failed to unregister sysctl\n", __func__
);
455 /* Initialize a new context to keep track of dynamically added sysctls. */
457 sysctl_ctx_init(struct sysctl_ctx_list
*c
)
465 * No locking here, the caller is responsible for not adding
466 * new nodes to a context until after this function has
473 /* Free the context, and destroy all dynamic oids registered in this context */
475 sysctl_ctx_free(struct sysctl_ctx_list
*clist
)
477 struct sysctl_ctx_entry
*e
, *e1
;
482 * First perform a "dry run" to check if it's ok to remove oids.
484 * XXX This algorithm is a hack. But I don't know any
485 * XXX better solution for now...
488 TAILQ_FOREACH(e
, clist
, link
) {
489 error
= sysctl_remove_oid_locked(e
->entry
, 0, 0);
494 * Restore deregistered entries, either from the end,
495 * or from the place where error occured.
496 * e contains the entry that was not unregistered
499 e1
= TAILQ_PREV(e
, sysctl_ctx_list
, link
);
501 e1
= TAILQ_LAST(clist
, sysctl_ctx_list
);
503 sysctl_register_oid(e1
->entry
);
504 e1
= TAILQ_PREV(e1
, sysctl_ctx_list
, link
);
510 /* Now really delete the entries */
511 e
= TAILQ_FIRST(clist
);
513 e1
= TAILQ_NEXT(e
, link
);
514 error
= sysctl_remove_oid_locked(e
->entry
, 1, 0);
516 panic("sysctl_remove_oid: corrupt tree, entry: %s",
518 free(e
, M_SYSCTLOID
);
525 /* Add an entry to the context */
526 struct sysctl_ctx_entry
*
527 sysctl_ctx_entry_add(struct sysctl_ctx_list
*clist
, struct sysctl_oid
*oidp
)
529 struct sysctl_ctx_entry
*e
;
531 SYSCTL_ASSERT_WLOCKED();
532 if (clist
== NULL
|| oidp
== NULL
)
534 e
= malloc(sizeof(struct sysctl_ctx_entry
), M_SYSCTLOID
, M_WAITOK
);
536 TAILQ_INSERT_HEAD(clist
, e
, link
);
540 /* Find an entry in the context */
541 struct sysctl_ctx_entry
*
542 sysctl_ctx_entry_find(struct sysctl_ctx_list
*clist
, struct sysctl_oid
*oidp
)
544 struct sysctl_ctx_entry
*e
;
546 SYSCTL_ASSERT_WLOCKED();
547 if (clist
== NULL
|| oidp
== NULL
)
549 TAILQ_FOREACH(e
, clist
, link
) {
557 * Delete an entry from the context.
558 * NOTE: this function doesn't free oidp! You have to remove it
559 * with sysctl_remove_oid().
562 sysctl_ctx_entry_del(struct sysctl_ctx_list
*clist
, struct sysctl_oid
*oidp
)
564 struct sysctl_ctx_entry
*e
;
566 if (clist
== NULL
|| oidp
== NULL
)
569 e
= sysctl_ctx_entry_find(clist
, oidp
);
571 TAILQ_REMOVE(clist
, e
, link
);
573 free(e
, M_SYSCTLOID
);
582 * Remove dynamically created sysctl trees.
583 * oidp - top of the tree to be removed
584 * del - if 0 - just deregister, otherwise free up entries as well
585 * recurse - if != 0 traverse the subtree to be deleted
588 sysctl_remove_oid(struct sysctl_oid
*oidp
, int del
, int recurse
)
593 error
= sysctl_remove_oid_locked(oidp
, del
, recurse
);
599 sysctl_remove_name(struct sysctl_oid
*parent
, const char *name
,
600 int del
, int recurse
)
602 struct sysctl_oid
*p
, *tmp
;
607 SLIST_FOREACH_SAFE(p
, SYSCTL_CHILDREN(parent
), oid_link
, tmp
) {
608 if (strcmp(p
->oid_name
, name
) == 0) {
609 error
= sysctl_remove_oid_locked(p
, del
, recurse
);
620 sysctl_remove_oid_locked(struct sysctl_oid
*oidp
, int del
, int recurse
)
622 struct sysctl_oid
*p
, *tmp
;
625 SYSCTL_ASSERT_WLOCKED();
628 if ((oidp
->oid_kind
& CTLFLAG_DYN
) == 0) {
629 printf("can't remove non-dynamic nodes!\n");
633 * WARNING: normal method to do this should be through
634 * sysctl_ctx_free(). Use recursing as the last resort
635 * method to purge your sysctl tree of leftovers...
636 * However, if some other code still references these nodes,
639 if ((oidp
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
640 if (oidp
->oid_refcnt
== 1) {
641 SLIST_FOREACH_SAFE(p
,
642 SYSCTL_CHILDREN(oidp
), oid_link
, tmp
) {
644 printf("Warning: failed attempt to "
645 "remove oid %s with child %s\n",
646 oidp
->oid_name
, p
->oid_name
);
649 error
= sysctl_remove_oid_locked(p
, del
,
656 if (oidp
->oid_refcnt
> 1 ) {
659 if (oidp
->oid_refcnt
== 0) {
660 printf("Warning: bad oid_refcnt=%u (%s)!\n",
661 oidp
->oid_refcnt
, oidp
->oid_name
);
664 sysctl_unregister_oid(oidp
);
667 * Wait for all threads running the handler to drain.
668 * This preserves the previous behavior when the
669 * sysctl lock was held across a handler invocation,
670 * and is necessary for module unload correctness.
672 while (oidp
->oid_running
> 0) {
673 oidp
->oid_kind
|= CTLFLAG_DYING
;
674 SYSCTL_SLEEP(&oidp
->oid_running
, "oidrm", 0);
677 free(__DECONST(char *, oidp
->oid_descr
),
679 free(__DECONST(char *, oidp
->oid_name
), M_SYSCTLOID
);
680 free(oidp
, M_SYSCTLOID
);
686 * Create new sysctls at run time.
687 * clist may point to a valid context initialized with sysctl_ctx_init().
690 sysctl_add_oid(struct sysctl_ctx_list
*clist
, struct sysctl_oid_list
*parent
,
691 int number
, const char *name
, int kind
, void *arg1
, intmax_t arg2
,
692 int (*handler
)(SYSCTL_HANDLER_ARGS
), const char *fmt
, const char *descr
)
694 struct sysctl_oid
*oidp
;
696 /* You have to hook up somewhere.. */
699 /* Check if the node already exists, otherwise create it */
701 oidp
= sysctl_find_oidname(name
, parent
);
703 if ((oidp
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
705 /* Update the context */
707 sysctl_ctx_entry_add(clist
, oidp
);
712 printf("can't re-use a leaf (%s)!\n", name
);
716 oidp
= malloc(sizeof(struct sysctl_oid
), M_SYSCTLOID
, M_WAITOK
|M_ZERO
);
717 oidp
->oid_parent
= parent
;
718 SLIST_INIT(&oidp
->oid_children
);
719 oidp
->oid_number
= number
;
720 oidp
->oid_refcnt
= 1;
721 oidp
->oid_name
= strdup(name
, M_SYSCTLOID
);
722 oidp
->oid_handler
= handler
;
723 oidp
->oid_kind
= CTLFLAG_DYN
| kind
;
724 oidp
->oid_arg1
= arg1
;
725 oidp
->oid_arg2
= arg2
;
728 oidp
->oid_descr
= strdup(descr
, M_SYSCTLOID
);
729 /* Update the context, if used */
731 sysctl_ctx_entry_add(clist
, oidp
);
732 /* Register this oid */
733 sysctl_register_oid(oidp
);
739 * Rename an existing oid.
742 sysctl_rename_oid(struct sysctl_oid
*oidp
, const char *name
)
747 newname
= strdup(name
, M_SYSCTLOID
);
749 oldname
= __DECONST(char *, oidp
->oid_name
);
750 oidp
->oid_name
= newname
;
752 free(oldname
, M_SYSCTLOID
);
756 * Reparent an existing oid.
759 sysctl_move_oid(struct sysctl_oid
*oid
, struct sysctl_oid_list
*parent
)
761 struct sysctl_oid
*oidp
;
764 if (oid
->oid_parent
== parent
) {
768 oidp
= sysctl_find_oidname(oid
->oid_name
, parent
);
773 sysctl_unregister_oid(oid
);
774 oid
->oid_parent
= parent
;
775 oid
->oid_number
= OID_AUTO
;
776 sysctl_register_oid(oid
);
782 * Register the kernel's oids on startup.
784 SET_DECLARE(sysctl_set
, struct sysctl_oid
);
787 sysctl_register_all(void *arg
)
789 struct sysctl_oid
**oidp
;
791 sx_init(&sysctlmemlock
, "sysctl mem");
794 SET_FOREACH(oidp
, sysctl_set
)
795 sysctl_register_oid(*oidp
);
798 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_FIRST
, sysctl_register_all
, 0);
803 * These functions implement a presently undocumented interface
804 * used by the sysctl program to walk the tree, and get the type
805 * so it can print the value.
806 * This interface is under work and consideration, and should probably
807 * be killed with a big axe by the first person who can find the time.
808 * (be aware though, that the proper interface isn't as obvious as it
809 * may seem, there are various conflicting requirements.
811 * {0,0} printf the entire MIB-tree.
812 * {0,1,...} return the name of the "..." OID.
813 * {0,2,...} return the next OID.
814 * {0,3} return the OID of the name in "new"
815 * {0,4,...} return the kind & format info for the "..." OID.
816 * {0,5,...} return the description the "..." OID.
821 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
824 struct sysctl_oid
*oidp
;
826 SYSCTL_ASSERT_LOCKED();
827 SLIST_FOREACH(oidp
, l
, oid_link
) {
832 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
835 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
836 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
838 if (oidp
->oid_handler
)
841 switch (oidp
->oid_kind
& CTLTYPE
) {
844 if (!oidp
->oid_handler
) {
845 sysctl_sysctl_debug_dump_node(
846 SYSCTL_CHILDREN(oidp
), i
+ 2);
849 case CTLTYPE_INT
: printf(" Int\n"); break;
850 case CTLTYPE_UINT
: printf(" u_int\n"); break;
851 case CTLTYPE_LONG
: printf(" Long\n"); break;
852 case CTLTYPE_ULONG
: printf(" u_long\n"); break;
853 case CTLTYPE_STRING
: printf(" String\n"); break;
854 case CTLTYPE_S8
: printf(" int8_t\n"); break;
855 case CTLTYPE_S16
: printf(" int16_t\n"); break;
856 case CTLTYPE_S32
: printf(" int32_t\n"); break;
857 case CTLTYPE_S64
: printf(" int64_t\n"); break;
858 case CTLTYPE_U8
: printf(" uint8_t\n"); break;
859 case CTLTYPE_U16
: printf(" uint16_t\n"); break;
860 case CTLTYPE_U32
: printf(" uint32_t\n"); break;
861 case CTLTYPE_U64
: printf(" uint64_t\n"); break;
862 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
863 default: printf("\n");
870 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS
)
872 struct rm_priotracker tracker
;
875 error
= priv_check(req
->td
, PRIV_SYSCTL_DEBUG
);
878 SYSCTL_RLOCK(&tracker
);
879 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
880 SYSCTL_RUNLOCK(&tracker
);
884 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
|CTLFLAG_MPSAFE
,
885 0, 0, sysctl_sysctl_debug
, "-", "");
889 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS
)
891 int *name
= (int *) arg1
;
892 u_int namelen
= arg2
;
894 struct sysctl_oid
*oid
;
895 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
896 struct rm_priotracker tracker
;
899 SYSCTL_RLOCK(&tracker
);
902 snprintf(buf
,sizeof(buf
),"%d",*name
);
904 error
= SYSCTL_OUT(req
, ".", 1);
906 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
914 SLIST_FOREACH(oid
, lsp
, oid_link
) {
915 if (oid
->oid_number
!= *name
)
919 error
= SYSCTL_OUT(req
, ".", 1);
921 error
= SYSCTL_OUT(req
, oid
->oid_name
,
922 strlen(oid
->oid_name
));
929 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
932 if (oid
->oid_handler
)
935 lsp2
= SYSCTL_CHILDREN(oid
);
940 error
= SYSCTL_OUT(req
, "", 1);
942 SYSCTL_RUNLOCK(&tracker
);
947 * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in
950 static SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
| CTLFLAG_MPSAFE
| CTLFLAG_CAPRD
,
951 sysctl_sysctl_name
, "");
954 sysctl_sysctl_next_ls(struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
955 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
957 struct sysctl_oid
*oidp
;
959 SYSCTL_ASSERT_LOCKED();
961 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
962 *next
= oidp
->oid_number
;
965 if (oidp
->oid_kind
& CTLFLAG_SKIP
)
969 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
971 if (oidp
->oid_handler
)
972 /* We really should call the handler here...*/
974 lsp
= SYSCTL_CHILDREN(oidp
);
975 if (!sysctl_sysctl_next_ls(lsp
, 0, 0, next
+1,
976 len
, level
+1, oidpp
))
981 if (oidp
->oid_number
< *name
)
984 if (oidp
->oid_number
> *name
) {
985 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
987 if (oidp
->oid_handler
)
989 lsp
= SYSCTL_CHILDREN(oidp
);
990 if (!sysctl_sysctl_next_ls(lsp
, name
+1, namelen
-1,
991 next
+1, len
, level
+1, oidpp
))
995 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
998 if (oidp
->oid_handler
)
1001 lsp
= SYSCTL_CHILDREN(oidp
);
1002 if (!sysctl_sysctl_next_ls(lsp
, name
+1, namelen
-1, next
+1,
1003 len
, level
+1, oidpp
))
1014 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS
)
1016 int *name
= (int *) arg1
;
1017 u_int namelen
= arg2
;
1019 struct sysctl_oid
*oid
;
1020 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1021 struct rm_priotracker tracker
;
1022 int newoid
[CTL_MAXNAME
];
1024 SYSCTL_RLOCK(&tracker
);
1025 i
= sysctl_sysctl_next_ls(lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
1026 SYSCTL_RUNLOCK(&tracker
);
1029 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
1034 * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in
1037 static SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
| CTLFLAG_MPSAFE
| CTLFLAG_CAPRD
,
1038 sysctl_sysctl_next
, "");
1041 name2oid(char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
1043 struct sysctl_oid
*oidp
;
1044 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1047 SYSCTL_ASSERT_LOCKED();
1049 for (*len
= 0; *len
< CTL_MAXNAME
;) {
1050 p
= strsep(&name
, ".");
1052 oidp
= SLIST_FIRST(lsp
);
1053 for (;; oidp
= SLIST_NEXT(oidp
, oid_link
)) {
1056 if (strcmp(p
, oidp
->oid_name
) == 0)
1059 *oid
++ = oidp
->oid_number
;
1062 if (name
== NULL
|| *name
== '\0') {
1068 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
1071 if (oidp
->oid_handler
)
1074 lsp
= SYSCTL_CHILDREN(oidp
);
1080 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS
)
1083 int error
, oid
[CTL_MAXNAME
], len
= 0;
1084 struct sysctl_oid
*op
= 0;
1085 struct rm_priotracker tracker
;
1089 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
1090 return (ENAMETOOLONG
);
1092 p
= malloc(req
->newlen
+1, M_SYSCTL
, M_WAITOK
);
1094 error
= SYSCTL_IN(req
, p
, req
->newlen
);
1100 p
[req
->newlen
] = '\0';
1102 SYSCTL_RLOCK(&tracker
);
1103 error
= name2oid(p
, oid
, &len
, &op
);
1104 SYSCTL_RUNLOCK(&tracker
);
1111 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
1116 * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in
1119 SYSCTL_PROC(_sysctl
, 3, name2oid
,
1120 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MPSAFE
1121 | CTLFLAG_CAPRW
, 0, 0, sysctl_sysctl_name2oid
, "I", "");
1124 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS
)
1126 struct sysctl_oid
*oid
;
1127 struct rm_priotracker tracker
;
1130 SYSCTL_RLOCK(&tracker
);
1131 error
= sysctl_find_oid(arg1
, arg2
, &oid
, NULL
, req
);
1135 if (oid
->oid_fmt
== NULL
) {
1139 error
= SYSCTL_OUT(req
, &oid
->oid_kind
, sizeof(oid
->oid_kind
));
1142 error
= SYSCTL_OUT(req
, oid
->oid_fmt
, strlen(oid
->oid_fmt
) + 1);
1144 SYSCTL_RUNLOCK(&tracker
);
1149 static SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
|CTLFLAG_MPSAFE
|CTLFLAG_CAPRD
,
1150 sysctl_sysctl_oidfmt
, "");
1153 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS
)
1155 struct sysctl_oid
*oid
;
1156 struct rm_priotracker tracker
;
1159 SYSCTL_RLOCK(&tracker
);
1160 error
= sysctl_find_oid(arg1
, arg2
, &oid
, NULL
, req
);
1164 if (oid
->oid_descr
== NULL
) {
1168 error
= SYSCTL_OUT(req
, oid
->oid_descr
, strlen(oid
->oid_descr
) + 1);
1170 SYSCTL_RUNLOCK(&tracker
);
1174 static SYSCTL_NODE(_sysctl
, 5, oiddescr
, CTLFLAG_RD
|CTLFLAG_MPSAFE
|CTLFLAG_CAPRD
,
1175 sysctl_sysctl_oiddescr
, "");
1178 * Default "handler" functions.
1182 * Handle an int8_t, signed or unsigned.
1184 * a variable: point arg1 at it.
1185 * a constant: pass it in arg2.
1189 sysctl_handle_8(SYSCTL_HANDLER_ARGS
)
1195 * Attempt to get a coherent snapshot by making a copy of the data.
1198 tmpout
= *(int8_t *)arg1
;
1201 error
= SYSCTL_OUT(req
, &tmpout
, sizeof(tmpout
));
1203 if (error
|| !req
->newptr
)
1209 error
= SYSCTL_IN(req
, arg1
, sizeof(tmpout
));
1214 * Handle an int16_t, signed or unsigned.
1216 * a variable: point arg1 at it.
1217 * a constant: pass it in arg2.
1221 sysctl_handle_16(SYSCTL_HANDLER_ARGS
)
1227 * Attempt to get a coherent snapshot by making a copy of the data.
1230 tmpout
= *(int16_t *)arg1
;
1233 error
= SYSCTL_OUT(req
, &tmpout
, sizeof(tmpout
));
1235 if (error
|| !req
->newptr
)
1241 error
= SYSCTL_IN(req
, arg1
, sizeof(tmpout
));
1246 * Handle an int32_t, signed or unsigned.
1248 * a variable: point arg1 at it.
1249 * a constant: pass it in arg2.
1253 sysctl_handle_32(SYSCTL_HANDLER_ARGS
)
1259 * Attempt to get a coherent snapshot by making a copy of the data.
1262 tmpout
= *(int32_t *)arg1
;
1265 error
= SYSCTL_OUT(req
, &tmpout
, sizeof(tmpout
));
1267 if (error
|| !req
->newptr
)
1273 error
= SYSCTL_IN(req
, arg1
, sizeof(tmpout
));
1278 * Handle an int, signed or unsigned.
1280 * a variable: point arg1 at it.
1281 * a constant: pass it in arg2.
1285 sysctl_handle_int(SYSCTL_HANDLER_ARGS
)
1287 int tmpout
, error
= 0;
1290 * Attempt to get a coherent snapshot by making a copy of the data.
1293 tmpout
= *(int *)arg1
;
1296 error
= SYSCTL_OUT(req
, &tmpout
, sizeof(int));
1298 if (error
|| !req
->newptr
)
1304 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
1309 * Based on on sysctl_handle_int() convert milliseconds into ticks.
1310 * Note: this is used by TCP.
1314 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS
)
1319 s
= (int)((int64_t)tt
* 1000 / hz
);
1321 error
= sysctl_handle_int(oidp
, &s
, 0, req
);
1322 if (error
|| !req
->newptr
)
1325 tt
= (int)((int64_t)s
* hz
/ 1000);
1335 * Handle a long, signed or unsigned.
1337 * a variable: point arg1 at it.
1338 * a constant: pass it in arg2.
1342 sysctl_handle_long(SYSCTL_HANDLER_ARGS
)
1351 * Attempt to get a coherent snapshot by making a copy of the data.
1354 tmplong
= *(long *)arg1
;
1358 if (req
->flags
& SCTL_MASK32
) {
1360 error
= SYSCTL_OUT(req
, &tmpint
, sizeof(int));
1363 error
= SYSCTL_OUT(req
, &tmplong
, sizeof(long));
1365 if (error
|| !req
->newptr
)
1371 else if (req
->flags
& SCTL_MASK32
) {
1372 error
= SYSCTL_IN(req
, &tmpint
, sizeof(int));
1373 *(long *)arg1
= (long)tmpint
;
1377 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
1382 * Handle a 64 bit int, signed or unsigned.
1384 * a variable: point arg1 at it.
1385 * a constant: pass it in arg2.
1388 sysctl_handle_64(SYSCTL_HANDLER_ARGS
)
1394 * Attempt to get a coherent snapshot by making a copy of the data.
1397 tmpout
= *(uint64_t *)arg1
;
1400 error
= SYSCTL_OUT(req
, &tmpout
, sizeof(uint64_t));
1402 if (error
|| !req
->newptr
)
1408 error
= SYSCTL_IN(req
, arg1
, sizeof(uint64_t));
1413 * Handle our generic '\0' terminated 'C' string.
1415 * a variable string: point arg1 at it, arg2 is max length.
1416 * a constant string: point arg1 at it, arg2 is zero.
1420 sysctl_handle_string(SYSCTL_HANDLER_ARGS
)
1423 int error
= 0, ro_string
= 0;
1426 * A zero-length buffer indicates a fixed size read-only
1430 arg2
= strlen((char *)arg1
) + 1;
1434 if (req
->oldptr
!= NULL
) {
1440 /* try to make a coherent snapshot of the string */
1441 tmparg
= malloc(arg2
, M_SYSCTLTMP
, M_WAITOK
);
1442 memcpy(tmparg
, arg1
, arg2
);
1445 outlen
= strnlen(tmparg
, arg2
- 1) + 1;
1446 error
= SYSCTL_OUT(req
, tmparg
, outlen
);
1449 free(tmparg
, M_SYSCTLTMP
);
1451 outlen
= strnlen((char *)arg1
, arg2
- 1) + 1;
1452 error
= SYSCTL_OUT(req
, NULL
, outlen
);
1454 if (error
|| !req
->newptr
)
1457 if ((req
->newlen
- req
->newidx
) >= arg2
) {
1460 arg2
= (req
->newlen
- req
->newidx
);
1461 error
= SYSCTL_IN(req
, arg1
, arg2
);
1462 ((char *)arg1
)[arg2
] = '\0';
1468 * Handle any kind of opaque data.
1469 * arg1 points to it, arg2 is the size.
1473 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS
)
1477 struct sysctl_req req2
;
1480 * Attempt to get a coherent snapshot, by using the thread
1481 * pre-emption counter updated from within mi_switch() to
1482 * determine if we were pre-empted during a bcopy() or
1483 * copyout(). Make 3 attempts at doing this before giving up.
1484 * If we encounter an error, stop immediately.
1489 generation
= curthread
->td_generation
;
1490 error
= SYSCTL_OUT(req
, arg1
, arg2
);
1494 if (generation
!= curthread
->td_generation
&& tries
< 3) {
1499 error
= SYSCTL_IN(req
, arg1
, arg2
);
1505 * Transfer functions to/from kernel space.
1506 * XXX: rather untested at this point
1509 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
1515 if (req
->oldlen
<= req
->oldidx
)
1518 if (i
> req
->oldlen
- req
->oldidx
)
1519 i
= req
->oldlen
- req
->oldidx
;
1521 bcopy(p
, (char *)req
->oldptr
+ req
->oldidx
, i
);
1524 if (req
->oldptr
&& i
!= l
)
1530 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
1534 if (req
->newlen
- req
->newidx
< l
)
1536 bcopy((char *)req
->newptr
+ req
->newidx
, p
, l
);
1542 kernel_sysctl(struct thread
*td
, int *name
, u_int namelen
, void *old
,
1543 size_t *oldlenp
, void *new, size_t newlen
, size_t *retval
, int flags
)
1546 struct sysctl_req req
;
1548 bzero(&req
, sizeof req
);
1554 req
.oldlen
= *oldlenp
;
1556 req
.validlen
= req
.oldlen
;
1563 req
.newlen
= newlen
;
1567 req
.oldfunc
= sysctl_old_kernel
;
1568 req
.newfunc
= sysctl_new_kernel
;
1569 req
.lock
= REQ_UNWIRED
;
1571 error
= sysctl_root(0, name
, namelen
, &req
);
1573 if (req
.lock
== REQ_WIRED
&& req
.validlen
> 0)
1574 vsunlock(req
.oldptr
, req
.validlen
);
1576 if (error
&& error
!= ENOMEM
)
1580 if (req
.oldptr
&& req
.oldidx
> req
.validlen
)
1581 *retval
= req
.validlen
;
1583 *retval
= req
.oldidx
;
1589 kernel_sysctlbyname(struct thread
*td
, char *name
, void *old
, size_t *oldlenp
,
1590 void *new, size_t newlen
, size_t *retval
, int flags
)
1592 int oid
[CTL_MAXNAME
];
1593 size_t oidlen
, plen
;
1596 oid
[0] = 0; /* sysctl internal magic */
1597 oid
[1] = 3; /* name2oid */
1598 oidlen
= sizeof(oid
);
1600 error
= kernel_sysctl(td
, oid
, 2, oid
, &oidlen
,
1601 (void *)name
, strlen(name
), &plen
, flags
);
1605 error
= kernel_sysctl(td
, oid
, plen
/ sizeof(int), old
, oldlenp
,
1606 new, newlen
, retval
, flags
);
1611 * Transfer function to/from user space.
1614 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
1616 size_t i
, len
, origidx
;
1619 origidx
= req
->oldidx
;
1621 if (req
->oldptr
== NULL
)
1624 * If we have not wired the user supplied buffer and we are currently
1625 * holding locks, drop a witness warning, as it's possible that
1626 * write operations to the user page can sleep.
1628 if (req
->lock
!= REQ_WIRED
)
1629 WITNESS_WARN(WARN_GIANTOK
| WARN_SLEEPOK
, NULL
,
1630 "sysctl_old_user()");
1632 len
= req
->validlen
;
1636 if (i
> len
- origidx
)
1638 if (req
->lock
== REQ_WIRED
) {
1639 error
= copyout_nofault(p
, (char *)req
->oldptr
+
1642 error
= copyout(p
, (char *)req
->oldptr
+ origidx
, i
);
1652 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
1658 if (req
->newlen
- req
->newidx
< l
)
1660 WITNESS_WARN(WARN_GIANTOK
| WARN_SLEEPOK
, NULL
,
1661 "sysctl_new_user()");
1662 error
= copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
1668 * Wire the user space destination buffer. If set to a value greater than
1669 * zero, the len parameter limits the maximum amount of wired memory.
1672 sysctl_wire_old_buffer(struct sysctl_req
*req
, size_t len
)
1677 wiredlen
= (len
> 0 && len
< req
->oldlen
) ? len
: req
->oldlen
;
1679 if (req
->lock
!= REQ_WIRED
&& req
->oldptr
&&
1680 req
->oldfunc
== sysctl_old_user
) {
1681 if (wiredlen
!= 0) {
1682 ret
= vslock(req
->oldptr
, wiredlen
);
1689 req
->lock
= REQ_WIRED
;
1690 req
->validlen
= wiredlen
;
1696 sysctl_find_oid(int *name
, u_int namelen
, struct sysctl_oid
**noid
,
1697 int *nindx
, struct sysctl_req
*req
)
1699 struct sysctl_oid_list
*lsp
;
1700 struct sysctl_oid
*oid
;
1703 SYSCTL_ASSERT_LOCKED();
1704 lsp
= &sysctl__children
;
1706 while (indx
< CTL_MAXNAME
) {
1707 SLIST_FOREACH(oid
, lsp
, oid_link
) {
1708 if (oid
->oid_number
== name
[indx
])
1715 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1716 if (oid
->oid_handler
!= NULL
|| indx
== namelen
) {
1720 KASSERT((oid
->oid_kind
& CTLFLAG_DYING
) == 0,
1721 ("%s found DYING node %p", __func__
, oid
));
1724 lsp
= SYSCTL_CHILDREN(oid
);
1725 } else if (indx
== namelen
) {
1729 KASSERT((oid
->oid_kind
& CTLFLAG_DYING
) == 0,
1730 ("%s found DYING node %p", __func__
, oid
));
1740 * Traverse our tree, and find the right node, execute whatever it points
1741 * to, and return the resulting error code.
1745 sysctl_root(SYSCTL_HANDLER_ARGS
)
1747 struct sysctl_oid
*oid
;
1748 struct rm_priotracker tracker
;
1749 int error
, indx
, lvl
;
1751 SYSCTL_RLOCK(&tracker
);
1753 error
= sysctl_find_oid(arg1
, arg2
, &oid
, &indx
, req
);
1757 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1759 * You can't call a sysctl when it's a node, but has
1760 * no handler. Inform the user that it's a node.
1761 * The indx may or may not be the same as namelen.
1763 if (oid
->oid_handler
== NULL
) {
1769 /* Is this sysctl writable? */
1770 if (req
->newptr
&& !(oid
->oid_kind
& CTLFLAG_WR
)) {
1775 KASSERT(req
->td
!= NULL
, ("sysctl_root(): req->td == NULL"));
1777 #ifdef CAPABILITY_MODE
1779 * If the process is in capability mode, then don't permit reading or
1780 * writing unless specifically granted for the node.
1782 if (IN_CAPABILITY_MODE(req
->td
)) {
1783 if ((req
->oldptr
&& !(oid
->oid_kind
& CTLFLAG_CAPRD
)) ||
1784 (req
->newptr
&& !(oid
->oid_kind
& CTLFLAG_CAPWR
))) {
1791 /* Is this sysctl sensitive to securelevels? */
1792 if (req
->newptr
&& (oid
->oid_kind
& CTLFLAG_SECURE
)) {
1793 lvl
= (oid
->oid_kind
& CTLMASK_SECURE
) >> CTLSHIFT_SECURE
;
1794 error
= securelevel_gt(req
->td
->td_ucred
, lvl
);
1799 /* Is this sysctl writable by only privileged users? */
1800 if (req
->newptr
&& !(oid
->oid_kind
& CTLFLAG_ANYBODY
)) {
1803 if (oid
->oid_kind
& CTLFLAG_PRISON
)
1804 priv
= PRIV_SYSCTL_WRITEJAIL
;
1806 else if ((oid
->oid_kind
& CTLFLAG_VNET
) &&
1807 prison_owns_vnet(req
->td
->td_ucred
))
1808 priv
= PRIV_SYSCTL_WRITEJAIL
;
1811 priv
= PRIV_SYSCTL_WRITE
;
1812 error
= priv_check(req
->td
, priv
);
1817 if (!oid
->oid_handler
) {
1822 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1823 arg1
= (int *)arg1
+ indx
;
1826 arg1
= oid
->oid_arg1
;
1827 arg2
= oid
->oid_arg2
;
1830 error
= mac_system_check_sysctl(req
->td
->td_ucred
, oid
, arg1
, arg2
,
1836 if ((oid
->oid_kind
& CTLFLAG_VNET
) && arg1
!= NULL
)
1837 arg1
= (void *)(curvnet
->vnet_data_base
+ (uintptr_t)arg1
);
1839 error
= sysctl_root_handler_locked(oid
, arg1
, arg2
, req
, &tracker
);
1841 KFAIL_POINT_ERROR(_debug_fail_point
, sysctl_running
, error
);
1844 SYSCTL_RUNLOCK(&tracker
);
1848 #ifndef _SYS_SYSPROTO_H_
1849 struct sysctl_args
{
1859 sys___sysctl(struct thread
*td
, struct sysctl_args
*uap
)
1861 int error
, i
, name
[CTL_MAXNAME
];
1864 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
1867 error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int));
1871 error
= userland_sysctl(td
, name
, uap
->namelen
,
1872 uap
->old
, uap
->oldlenp
, 0,
1873 uap
->new, uap
->newlen
, &j
, 0);
1874 if (error
&& error
!= ENOMEM
)
1877 i
= copyout(&j
, uap
->oldlenp
, sizeof(j
));
1885 * This is used from various compatibility syscalls too. That's why name
1886 * must be in kernel space.
1889 userland_sysctl(struct thread
*td
, int *name
, u_int namelen
, void *old
,
1890 size_t *oldlenp
, int inkernel
, void *new, size_t newlen
, size_t *retval
,
1893 int error
= 0, memlocked
;
1894 struct sysctl_req req
;
1896 bzero(&req
, sizeof req
);
1903 req
.oldlen
= *oldlenp
;
1905 error
= copyin(oldlenp
, &req
.oldlen
, sizeof(*oldlenp
));
1910 req
.validlen
= req
.oldlen
;
1913 if (!useracc(old
, req
.oldlen
, VM_PROT_WRITE
))
1919 if (!useracc(new, newlen
, VM_PROT_READ
))
1921 req
.newlen
= newlen
;
1925 req
.oldfunc
= sysctl_old_user
;
1926 req
.newfunc
= sysctl_new_user
;
1927 req
.lock
= REQ_UNWIRED
;
1930 if (KTRPOINT(curthread
, KTR_SYSCTL
))
1931 ktrsysctl(name
, namelen
);
1934 if (req
.oldptr
&& req
.oldlen
> PAGE_SIZE
) {
1936 sx_xlock(&sysctlmemlock
);
1939 CURVNET_SET(TD_TO_VNET(td
));
1944 error
= sysctl_root(0, name
, namelen
, &req
);
1945 if (error
!= EAGAIN
)
1947 kern_yield(PRI_USER
);
1952 if (req
.lock
== REQ_WIRED
&& req
.validlen
> 0)
1953 vsunlock(req
.oldptr
, req
.validlen
);
1955 sx_xunlock(&sysctlmemlock
);
1957 if (error
&& error
!= ENOMEM
)
1961 if (req
.oldptr
&& req
.oldidx
> req
.validlen
)
1962 *retval
= req
.validlen
;
1964 *retval
= req
.oldidx
;
1970 * Drain into a sysctl struct. The user buffer should be wired if a page
1971 * fault would cause issue.
1974 sbuf_sysctl_drain(void *arg
, const char *data
, int len
)
1976 struct sysctl_req
*req
= arg
;
1979 error
= SYSCTL_OUT(req
, data
, len
);
1980 KASSERT(error
>= 0, ("Got unexpected negative value %d", error
));
1981 return (error
== 0 ? len
: -error
);
1985 sbuf_new_for_sysctl(struct sbuf
*s
, char *buf
, int length
,
1986 struct sysctl_req
*req
)
1989 /* Supply a default buffer size if none given. */
1990 if (buf
== NULL
&& length
== 0)
1992 s
= sbuf_new(s
, buf
, length
, SBUF_FIXEDLEN
| SBUF_INCLUDENUL
);
1993 sbuf_set_drain(s
, sbuf_sysctl_drain
, req
);