kern_sysctl.c revision 267985
1175164Sjhb/*- 2225344Srwatson * Copyright (c) 1982, 1986, 1989, 1993 3175164Sjhb * The Regents of the University of California. All rights reserved. 4175164Sjhb * 5175164Sjhb * This code is derived from software contributed to Berkeley by 6175164Sjhb * Mike Karels at Berkeley Software Design, Inc. 7175164Sjhb * 8175164Sjhb * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD 9175164Sjhb * project, to make these variables more userfriendly. 10175164Sjhb * 11175164Sjhb * Redistribution and use in source and binary forms, with or without 12175164Sjhb * modification, are permitted provided that the following conditions 13175164Sjhb * are met: 14175164Sjhb * 1. Redistributions of source code must retain the above copyright 15175164Sjhb * notice, this list of conditions and the following disclaimer. 16175164Sjhb * 2. Redistributions in binary form must reproduce the above copyright 17175164Sjhb * notice, this list of conditions and the following disclaimer in the 18175164Sjhb * documentation and/or other materials provided with the distribution. 19175164Sjhb * 4. Neither the name of the University nor the names of its contributors 20175164Sjhb * may be used to endorse or promote products derived from this software 21175164Sjhb * without specific prior written permission. 22175164Sjhb * 23175164Sjhb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24175164Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25175164Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26175164Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27175164Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28175164Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29175164Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30175164Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31175164Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32175164Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33175164Sjhb * SUCH DAMAGE. 34225344Srwatson * 35175164Sjhb * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 36175164Sjhb */ 37175164Sjhb 38225344Srwatson#include <sys/cdefs.h> 39175164Sjhb__FBSDID("$FreeBSD: head/sys/kern/kern_sysctl.c 267985 2014-06-27 22:05:21Z gjb $"); 40225344Srwatson 41175164Sjhb#include "opt_capsicum.h" 42175164Sjhb#include "opt_compat.h" 43175164Sjhb#include "opt_ktrace.h" 44175164Sjhb 45175164Sjhb#include <sys/param.h> 46175164Sjhb#include <sys/fail.h> 47223692Sjonathan#include <sys/systm.h> 48223692Sjonathan#include <sys/capsicum.h> 49175164Sjhb#include <sys/kernel.h> 50223692Sjonathan#include <sys/sysctl.h> 51175164Sjhb#include <sys/malloc.h> 52175164Sjhb#include <sys/priv.h> 53175164Sjhb#include <sys/proc.h> 54175164Sjhb#include <sys/jail.h> 55175164Sjhb#include <sys/lock.h> 56175164Sjhb#include <sys/mutex.h> 57175164Sjhb#include <sys/sbuf.h> 58175164Sjhb#include <sys/sx.h> 59175164Sjhb#include <sys/sysproto.h> 60224914Skib#include <sys/uio.h> 61175164Sjhb#ifdef KTRACE 62175164Sjhb#include <sys/ktrace.h> 63175164Sjhb#endif 64175164Sjhb 65175164Sjhb#include <net/vnet.h> 66175164Sjhb 67175164Sjhb#include <security/mac/mac_framework.h> 68175164Sjhb 69175164Sjhb#include <vm/vm.h> 70175164Sjhb#include <vm/vm_extern.h> 71175164Sjhb 72175164Sjhbstatic MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); 73175164Sjhbstatic MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); 74175164Sjhbstatic MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer"); 75175164Sjhb 76175164Sjhb/* 77236683Sjhb * The sysctllock protects the MIB tree. It also protects sysctl 78175164Sjhb * contexts used with dynamic sysctls. The sysctl_register_oid() and 79236683Sjhb * sysctl_unregister_oid() routines require the sysctllock to already 80175164Sjhb * be held, so the sysctl_lock() and sysctl_unlock() routines are 81175164Sjhb * provided for the few places in the kernel which need to use that 82236208Salc * API rather than using the dynamic API. Use of the dynamic API is 83175164Sjhb * strongly encouraged for most code. 84175164Sjhb * 85175164Sjhb * The sysctlmemlock is used to limit the amount of user memory wired for 86175164Sjhb * sysctl requests. This is implemented by serializing any userland 87175164Sjhb * sysctl requests larger than a single page via an exclusive lock. 88175164Sjhb */ 89175164Sjhbstatic struct sx sysctllock; 90175164Sjhbstatic struct sx sysctlmemlock; 91175164Sjhb 92175164Sjhb#define SYSCTL_XLOCK() sx_xlock(&sysctllock) 93175164Sjhb#define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock) 94175164Sjhb#define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED) 95175164Sjhb#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock") 96175164Sjhb#define SYSCTL_SLEEP(ch, wmesg, timo) \ 97175164Sjhb sx_sleep(ch, &sysctllock, 0, wmesg, timo) 98175164Sjhb 99175164Sjhbstatic int sysctl_root(SYSCTL_HANDLER_ARGS); 100175164Sjhb 101175164Sjhbstruct sysctl_oid_list sysctl__children; /* root list */ 102175164Sjhb 103175164Sjhbstatic int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, 104175164Sjhb int recurse); 105175164Sjhb 106175164Sjhbstatic struct sysctl_oid * 107175164Sjhbsysctl_find_oidname(const char *name, struct sysctl_oid_list *list) 108175164Sjhb{ 109194766Skib struct sysctl_oid *oidp; 110175164Sjhb 111175164Sjhb SYSCTL_ASSERT_XLOCKED(); 112175164Sjhb SLIST_FOREACH(oidp, list, oid_link) { 113175164Sjhb if (strcmp(oidp->oid_name, name) == 0) { 114175164Sjhb return (oidp); 115175164Sjhb } 116175164Sjhb } 117175164Sjhb return (NULL); 118175164Sjhb} 119224914Skib 120224914Skib/* 121175164Sjhb * Initialization of the MIB tree. 122175164Sjhb * 123175164Sjhb * Order by number in each list. 124175164Sjhb */ 125175164Sjhbvoid 126175164Sjhbsysctl_lock(void) 127175164Sjhb{ 128175164Sjhb 129175164Sjhb SYSCTL_XLOCK(); 130175164Sjhb} 131175164Sjhb 132224914Skibvoid 133224914Skibsysctl_unlock(void) 134175164Sjhb{ 135175164Sjhb 136175164Sjhb SYSCTL_XUNLOCK(); 137175164Sjhb} 138175164Sjhb 139175164Sjhbvoid 140175164Sjhbsysctl_register_oid(struct sysctl_oid *oidp) 141175164Sjhb{ 142175164Sjhb struct sysctl_oid_list *parent = oidp->oid_parent; 143175164Sjhb struct sysctl_oid *p; 144175164Sjhb struct sysctl_oid *q; 145175164Sjhb 146175164Sjhb /* 147175164Sjhb * First check if another oid with the same name already 148175164Sjhb * exists in the parent's list. 149175164Sjhb */ 150175164Sjhb SYSCTL_ASSERT_XLOCKED(); 151175164Sjhb p = sysctl_find_oidname(oidp->oid_name, parent); 152175164Sjhb if (p != NULL) { 153175164Sjhb if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 154175164Sjhb p->oid_refcnt++; 155175164Sjhb return; 156175164Sjhb } else { 157175164Sjhb printf("can't re-use a leaf (%s)!\n", p->oid_name); 158175164Sjhb return; 159175164Sjhb } 160175164Sjhb } 161175164Sjhb /* 162175164Sjhb * If this oid has a number OID_AUTO, give it a number which 163175164Sjhb * is greater than any current oid. 164175164Sjhb * NOTE: DO NOT change the starting value here, change it in 165175164Sjhb * <sys/sysctl.h>, and make sure it is at least 256 to 166175164Sjhb * accomodate e.g. net.inet.raw as a static sysctl node. 167175164Sjhb */ 168175164Sjhb if (oidp->oid_number == OID_AUTO) { 169175164Sjhb static int newoid = CTL_AUTO_START; 170194766Skib 171175164Sjhb oidp->oid_number = newoid++; 172175164Sjhb if (newoid == 0x7fffffff) 173175164Sjhb panic("out of oids"); 174175164Sjhb } 175175164Sjhb#if 0 176175164Sjhb else if (oidp->oid_number >= CTL_AUTO_START) { 177175164Sjhb /* do not panic; this happens when unregistering sysctl sets */ 178175164Sjhb printf("static sysctl oid too high: %d", oidp->oid_number); 179175164Sjhb } 180175164Sjhb#endif 181175164Sjhb 182175164Sjhb /* 183175164Sjhb * Insert the oid into the parent's list in order. 184175164Sjhb */ 185175164Sjhb q = NULL; 186175164Sjhb SLIST_FOREACH(p, parent, oid_link) { 187175164Sjhb if (oidp->oid_number < p->oid_number) 188175164Sjhb break; 189175164Sjhb q = p; 190175164Sjhb } 191175164Sjhb if (q) 192175164Sjhb SLIST_INSERT_AFTER(q, oidp, oid_link); 193175164Sjhb else 194175164Sjhb SLIST_INSERT_HEAD(parent, oidp, oid_link); 195175164Sjhb} 196175164Sjhb 197175164Sjhbvoid 198175164Sjhbsysctl_unregister_oid(struct sysctl_oid *oidp) 199175164Sjhb{ 200175164Sjhb struct sysctl_oid *p; 201175164Sjhb int error; 202175164Sjhb 203175164Sjhb SYSCTL_ASSERT_XLOCKED(); 204175164Sjhb error = ENOENT; 205175164Sjhb if (oidp->oid_number == OID_AUTO) { 206175164Sjhb error = EINVAL; 207175164Sjhb } else { 208175164Sjhb SLIST_FOREACH(p, oidp->oid_parent, oid_link) { 209175164Sjhb if (p == oidp) { 210175164Sjhb SLIST_REMOVE(oidp->oid_parent, oidp, 211175164Sjhb sysctl_oid, oid_link); 212175164Sjhb error = 0; 213175164Sjhb break; 214175164Sjhb } 215175164Sjhb } 216175164Sjhb } 217175164Sjhb 218175164Sjhb /* 219175164Sjhb * This can happen when a module fails to register and is 220175164Sjhb * being unloaded afterwards. It should not be a panic() 221224914Skib * for normal use. 222205792Sed */ 223205792Sed if (error) 224205792Sed printf("%s: failed to unregister sysctl\n", __func__); 225224914Skib} 226224914Skib 227175164Sjhb/* Initialize a new context to keep track of dynamically added sysctls. */ 228175164Sjhbint 229224914Skibsysctl_ctx_init(struct sysctl_ctx_list *c) 230175164Sjhb{ 231175164Sjhb 232175164Sjhb if (c == NULL) { 233175164Sjhb return (EINVAL); 234175164Sjhb } 235175164Sjhb 236175164Sjhb /* 237175164Sjhb * No locking here, the caller is responsible for not adding 238175164Sjhb * new nodes to a context until after this function has 239175164Sjhb * returned. 240175164Sjhb */ 241175164Sjhb TAILQ_INIT(c); 242175164Sjhb return (0); 243175164Sjhb} 244175164Sjhb 245175164Sjhb/* Free the context, and destroy all dynamic oids registered in this context */ 246194766Skibint 247175164Sjhbsysctl_ctx_free(struct sysctl_ctx_list *clist) 248175164Sjhb{ 249175164Sjhb struct sysctl_ctx_entry *e, *e1; 250236208Salc int error; 251236208Salc 252194766Skib error = 0; 253236208Salc /* 254175164Sjhb * First perform a "dry run" to check if it's ok to remove oids. 255175164Sjhb * XXX FIXME 256175164Sjhb * XXX This algorithm is a hack. But I don't know any 257175164Sjhb * XXX better solution for now... 258175164Sjhb */ 259194766Skib SYSCTL_XLOCK(); 260175164Sjhb TAILQ_FOREACH(e, clist, link) { 261175164Sjhb error = sysctl_remove_oid_locked(e->entry, 0, 0); 262175164Sjhb if (error) 263175164Sjhb break; 264175164Sjhb } 265236683Sjhb /* 266236683Sjhb * Restore deregistered entries, either from the end, 267236683Sjhb * or from the place where error occured. 268236683Sjhb * e contains the entry that was not unregistered 269236683Sjhb */ 270236683Sjhb if (error) 271236683Sjhb e1 = TAILQ_PREV(e, sysctl_ctx_list, link); 272236683Sjhb else 273236208Salc e1 = TAILQ_LAST(clist, sysctl_ctx_list); 274236208Salc while (e1 != NULL) { 275236208Salc sysctl_register_oid(e1->entry); 276236208Salc e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); 277236208Salc } 278236208Salc if (error) { 279236208Salc SYSCTL_XUNLOCK(); 280236208Salc return(EBUSY); 281236208Salc } 282236208Salc /* Now really delete the entries */ 283236208Salc e = TAILQ_FIRST(clist); 284236208Salc while (e != NULL) { 285236208Salc e1 = TAILQ_NEXT(e, link); 286236208Salc error = sysctl_remove_oid_locked(e->entry, 1, 0); 287236208Salc if (error) 288236208Salc panic("sysctl_remove_oid: corrupt tree, entry: %s", 289236208Salc e->entry->oid_name); 290236208Salc free(e, M_SYSCTLOID); 291236208Salc e = e1; 292236208Salc } 293236208Salc SYSCTL_XUNLOCK(); 294236208Salc return (error); 295236208Salc} 296236208Salc 297236208Salc/* Add an entry to the context */ 298236208Salcstruct sysctl_ctx_entry * 299236208Salcsysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 300236208Salc{ 301236208Salc struct sysctl_ctx_entry *e; 302236208Salc 303236208Salc SYSCTL_ASSERT_XLOCKED(); 304236208Salc if (clist == NULL || oidp == NULL) 305236208Salc return(NULL); 306236208Salc e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); 307236208Salc e->entry = oidp; 308236208Salc TAILQ_INSERT_HEAD(clist, e, link); 309236208Salc return (e); 310236208Salc} 311236208Salc 312236208Salc/* Find an entry in the context */ 313236208Salcstruct sysctl_ctx_entry * 314236208Salcsysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 315236208Salc{ 316236208Salc struct sysctl_ctx_entry *e; 317236208Salc 318236208Salc SYSCTL_ASSERT_XLOCKED(); 319236208Salc if (clist == NULL || oidp == NULL) 320236208Salc return(NULL); 321236208Salc TAILQ_FOREACH(e, clist, link) { 322236208Salc if(e->entry == oidp) 323194766Skib return(e); 324194766Skib } 325175164Sjhb return (e); 326175164Sjhb} 327175164Sjhb 328223677Salc/* 329175164Sjhb * Delete an entry from the context. 330175164Sjhb * NOTE: this function doesn't free oidp! You have to remove it 331175164Sjhb * with sysctl_remove_oid(). 332194766Skib */ 333175164Sjhbint 334194766Skibsysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 335216128Strasz{ 336194766Skib struct sysctl_ctx_entry *e; 337194766Skib 338194766Skib if (clist == NULL || oidp == NULL) 339194766Skib return (EINVAL); 340216128Strasz SYSCTL_XLOCK(); 341194766Skib e = sysctl_ctx_entry_find(clist, oidp); 342194766Skib if (e != NULL) { 343194766Skib TAILQ_REMOVE(clist, e, link); 344194766Skib SYSCTL_XUNLOCK(); 345175164Sjhb free(e, M_SYSCTLOID); 346175164Sjhb return (0); 347175164Sjhb } else { 348175164Sjhb SYSCTL_XUNLOCK(); 349175164Sjhb return (ENOENT); 350175164Sjhb } 351175164Sjhb} 352175164Sjhb 353194766Skib/* 354175164Sjhb * Remove dynamically created sysctl trees. 355175164Sjhb * oidp - top of the tree to be removed 356175164Sjhb * del - if 0 - just deregister, otherwise free up entries as well 357175164Sjhb * recurse - if != 0 traverse the subtree to be deleted 358175164Sjhb */ 359175164Sjhbint 360175164Sjhbsysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse) 361175164Sjhb{ 362175164Sjhb int error; 363175164Sjhb 364175164Sjhb SYSCTL_XLOCK(); 365175164Sjhb error = sysctl_remove_oid_locked(oidp, del, recurse); 366175164Sjhb SYSCTL_XUNLOCK(); 367175164Sjhb return (error); 368175164Sjhb} 369175164Sjhb 370175164Sjhbint 371194766Skibsysctl_remove_name(struct sysctl_oid *parent, const char *name, 372175164Sjhb int del, int recurse) 373178181Salc{ 374178181Salc struct sysctl_oid *p, *tmp; 375178181Salc int error; 376178181Salc 377175164Sjhb error = ENOENT; 378175164Sjhb SYSCTL_XLOCK(); 379175164Sjhb SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) { 380175164Sjhb if (strcmp(p->oid_name, name) == 0) { 381175164Sjhb error = sysctl_remove_oid_locked(p, del, recurse); 382175164Sjhb break; 383175164Sjhb } 384175164Sjhb } 385175164Sjhb SYSCTL_XUNLOCK(); 386175164Sjhb 387175164Sjhb return (error); 388175164Sjhb} 389175164Sjhb 390175164Sjhb 391175164Sjhbstatic int 392175164Sjhbsysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse) 393175164Sjhb{ 394175164Sjhb struct sysctl_oid *p, *tmp; 395175164Sjhb int error; 396175164Sjhb 397175164Sjhb SYSCTL_ASSERT_XLOCKED(); 398175164Sjhb if (oidp == NULL) 399175164Sjhb return(EINVAL); 400175164Sjhb if ((oidp->oid_kind & CTLFLAG_DYN) == 0) { 401175164Sjhb printf("can't remove non-dynamic nodes!\n"); 402175164Sjhb return (EINVAL); 403175164Sjhb } 404175164Sjhb /* 405175164Sjhb * WARNING: normal method to do this should be through 406175164Sjhb * sysctl_ctx_free(). Use recursing as the last resort 407175164Sjhb * method to purge your sysctl tree of leftovers... 408175164Sjhb * However, if some other code still references these nodes, 409175164Sjhb * it will panic. 410175164Sjhb */ 411175164Sjhb if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 412175164Sjhb if (oidp->oid_refcnt == 1) { 413175164Sjhb SLIST_FOREACH_SAFE(p, 414175164Sjhb SYSCTL_CHILDREN(oidp), oid_link, tmp) { 415175164Sjhb if (!recurse) { 416175164Sjhb printf("Warning: failed attempt to " 417184413Strasz "remove oid %s with child %s\n", 418224914Skib oidp->oid_name, p->oid_name); 419175164Sjhb return (ENOTEMPTY); 420184413Strasz } 421175164Sjhb error = sysctl_remove_oid_locked(p, del, 422184413Strasz recurse); 423175164Sjhb if (error) 424184413Strasz return (error); 425224914Skib } 426224914Skib if (del) 427224914Skib free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID); 428224914Skib } 429224914Skib } 430175164Sjhb if (oidp->oid_refcnt > 1 ) { 431175164Sjhb oidp->oid_refcnt--; 432175164Sjhb } else { 433175164Sjhb if (oidp->oid_refcnt == 0) { 434175164Sjhb printf("Warning: bad oid_refcnt=%u (%s)!\n", 435175164Sjhb oidp->oid_refcnt, oidp->oid_name); 436175164Sjhb return (EINVAL); 437175164Sjhb } 438175164Sjhb sysctl_unregister_oid(oidp); 439175164Sjhb if (del) { 440175164Sjhb /* 441175164Sjhb * Wait for all threads running the handler to drain. 442175164Sjhb * This preserves the previous behavior when the 443175164Sjhb * sysctl lock was held across a handler invocation, 444175164Sjhb * and is necessary for module unload correctness. 445175164Sjhb */ 446175164Sjhb while (oidp->oid_running > 0) { 447175164Sjhb oidp->oid_kind |= CTLFLAG_DYING; 448175164Sjhb SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0); 449175164Sjhb } 450175164Sjhb if (oidp->oid_descr) 451175164Sjhb free(__DECONST(char *, oidp->oid_descr), 452175164Sjhb M_SYSCTLOID); 453175164Sjhb free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID); 454175164Sjhb free(oidp, M_SYSCTLOID); 455175164Sjhb } 456175164Sjhb } 457175164Sjhb return (0); 458175164Sjhb} 459175164Sjhb/* 460175164Sjhb * Create new sysctls at run time. 461175164Sjhb * clist may point to a valid context initialized with sysctl_ctx_init(). 462175164Sjhb */ 463175164Sjhbstruct sysctl_oid * 464175164Sjhbsysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, 465175164Sjhb int number, const char *name, int kind, void *arg1, intptr_t arg2, 466175164Sjhb int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr) 467175164Sjhb{ 468175164Sjhb struct sysctl_oid *oidp; 469175164Sjhb 470175164Sjhb /* You have to hook up somewhere.. */ 471236698Sjhb if (parent == NULL) 472175164Sjhb return(NULL); 473175164Sjhb /* Check if the node already exists, otherwise create it */ 474175164Sjhb SYSCTL_XLOCK(); 475175164Sjhb oidp = sysctl_find_oidname(name, parent); 476175164Sjhb if (oidp != NULL) { 477175164Sjhb if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 478175164Sjhb oidp->oid_refcnt++; 479175164Sjhb /* Update the context */ 480175164Sjhb if (clist != NULL) 481175164Sjhb sysctl_ctx_entry_add(clist, oidp); 482175164Sjhb SYSCTL_XUNLOCK(); 483175164Sjhb return (oidp); 484175164Sjhb } else { 485175164Sjhb SYSCTL_XUNLOCK(); 486175164Sjhb printf("can't re-use a leaf (%s)!\n", name); 487175164Sjhb return (NULL); 488175164Sjhb } 489175164Sjhb } 490175164Sjhb oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO); 491175164Sjhb oidp->oid_parent = parent; 492175164Sjhb SLIST_NEXT(oidp, oid_link) = NULL; 493175164Sjhb oidp->oid_number = number; 494236698Sjhb oidp->oid_refcnt = 1; 495175164Sjhb oidp->oid_name = strdup(name, M_SYSCTLOID); 496175164Sjhb oidp->oid_handler = handler; 497175164Sjhb oidp->oid_kind = CTLFLAG_DYN | kind; 498175164Sjhb if ((kind & CTLTYPE) == CTLTYPE_NODE) { 499175164Sjhb /* Allocate space for children */ 500175164Sjhb SYSCTL_CHILDREN_SET(oidp, malloc(sizeof(struct sysctl_oid_list), 501175164Sjhb M_SYSCTLOID, M_WAITOK)); 502175164Sjhb SLIST_INIT(SYSCTL_CHILDREN(oidp)); 503175164Sjhb oidp->oid_arg2 = arg2; 504175164Sjhb } else { 505175164Sjhb oidp->oid_arg1 = arg1; 506175164Sjhb oidp->oid_arg2 = arg2; 507175164Sjhb } 508225617Skmacy oidp->oid_fmt = fmt; 509175164Sjhb if (descr) 510175164Sjhb oidp->oid_descr = strdup(descr, M_SYSCTLOID); 511175164Sjhb /* Update the context, if used */ 512175164Sjhb if (clist != NULL) 513175164Sjhb sysctl_ctx_entry_add(clist, oidp); 514175164Sjhb /* Register this oid */ 515175164Sjhb sysctl_register_oid(oidp); 516175164Sjhb SYSCTL_XUNLOCK(); 517175164Sjhb return (oidp); 518223692Sjonathan} 519223692Sjonathan 520223692Sjonathan/* 521223692Sjonathan * Rename an existing oid. 522223692Sjonathan */ 523223692Sjonathanvoid 524223692Sjonathansysctl_rename_oid(struct sysctl_oid *oidp, const char *name) 525223692Sjonathan{ 526175164Sjhb char *newname; 527175164Sjhb char *oldname; 528175164Sjhb 529175164Sjhb newname = strdup(name, M_SYSCTLOID); 530175164Sjhb SYSCTL_XLOCK(); 531175164Sjhb oldname = __DECONST(char *, oidp->oid_name); 532175164Sjhb oidp->oid_name = newname; 533175164Sjhb SYSCTL_XUNLOCK(); 534175164Sjhb free(oldname, M_SYSCTLOID); 535175164Sjhb} 536249953Sjilles 537175164Sjhb/* 538175164Sjhb * Reparent an existing oid. 539175164Sjhb */ 540175164Sjhbint 541175164Sjhbsysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent) 542175164Sjhb{ 543175164Sjhb struct sysctl_oid *oidp; 544175164Sjhb 545175164Sjhb SYSCTL_XLOCK(); 546175164Sjhb if (oid->oid_parent == parent) { 547175164Sjhb SYSCTL_XUNLOCK(); 548175164Sjhb return (0); 549175164Sjhb } 550175164Sjhb oidp = sysctl_find_oidname(oid->oid_name, parent); 551175164Sjhb if (oidp != NULL) { 552175164Sjhb SYSCTL_XUNLOCK(); 553175164Sjhb return (EEXIST); 554175164Sjhb } 555175164Sjhb sysctl_unregister_oid(oid); 556175164Sjhb oid->oid_parent = parent; 557175164Sjhb oid->oid_number = OID_AUTO; 558175164Sjhb sysctl_register_oid(oid); 559175164Sjhb SYSCTL_XUNLOCK(); 560175164Sjhb return (0); 561175164Sjhb} 562175164Sjhb 563175164Sjhb/* 564175164Sjhb * Register the kernel's oids on startup. 565175164Sjhb */ 566175164SjhbSET_DECLARE(sysctl_set, struct sysctl_oid); 567175164Sjhb 568175164Sjhbstatic void 569225344Srwatsonsysctl_register_all(void *arg) 570225344Srwatson{ 571225344Srwatson struct sysctl_oid **oidp; 572225344Srwatson 573225344Srwatson sx_init(&sysctlmemlock, "sysctl mem"); 574225344Srwatson SYSCTL_INIT(); 575225344Srwatson SYSCTL_XLOCK(); 576225344Srwatson SET_FOREACH(oidp, sysctl_set) 577225344Srwatson sysctl_register_oid(*oidp); 578225344Srwatson SYSCTL_XUNLOCK(); 579175164Sjhb} 580175164SjhbSYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); 581175164Sjhb 582175164Sjhb/* 583175164Sjhb * "Staff-functions" 584175164Sjhb * 585175164Sjhb * These functions implement a presently undocumented interface 586175164Sjhb * used by the sysctl program to walk the tree, and get the type 587175164Sjhb * so it can print the value. 588175164Sjhb * This interface is under work and consideration, and should probably 589175164Sjhb * be killed with a big axe by the first person who can find the time. 590175164Sjhb * (be aware though, that the proper interface isn't as obvious as it 591175164Sjhb * may seem, there are various conflicting requirements. 592175164Sjhb * 593175164Sjhb * {0,0} printf the entire MIB-tree. 594175164Sjhb * {0,1,...} return the name of the "..." OID. 595225344Srwatson * {0,2,...} return the next OID. 596175164Sjhb * {0,3} return the OID of the name in "new" 597175164Sjhb * {0,4,...} return the kind & format info for the "..." OID. 598175164Sjhb * {0,5,...} return the description the "..." OID. 599175164Sjhb */ 600175164Sjhb 601175164Sjhb#ifdef SYSCTL_DEBUG 602175164Sjhbstatic void 603175164Sjhbsysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i) 604175164Sjhb{ 605175164Sjhb int k; 606175164Sjhb struct sysctl_oid *oidp; 607175164Sjhb 608175164Sjhb SYSCTL_ASSERT_XLOCKED(); 609175164Sjhb SLIST_FOREACH(oidp, l, oid_link) { 610175164Sjhb 611175164Sjhb for (k=0; k<i; k++) 612175164Sjhb printf(" "); 613175164Sjhb 614175164Sjhb printf("%d %s ", oidp->oid_number, oidp->oid_name); 615175164Sjhb 616175164Sjhb printf("%c%c", 617175164Sjhb oidp->oid_kind & CTLFLAG_RD ? 'R':' ', 618175164Sjhb oidp->oid_kind & CTLFLAG_WR ? 'W':' '); 619175164Sjhb 620175164Sjhb if (oidp->oid_handler) 621175164Sjhb printf(" *Handler"); 622175164Sjhb 623175164Sjhb switch (oidp->oid_kind & CTLTYPE) { 624175164Sjhb case CTLTYPE_NODE: 625175164Sjhb printf(" Node\n"); 626175164Sjhb if (!oidp->oid_handler) { 627175164Sjhb sysctl_sysctl_debug_dump_node( 628175164Sjhb oidp->oid_arg1, i+2); 629175164Sjhb } 630175164Sjhb break; 631175164Sjhb case CTLTYPE_INT: printf(" Int\n"); break; 632175164Sjhb case CTLTYPE_UINT: printf(" u_int\n"); break; 633175164Sjhb case CTLTYPE_LONG: printf(" Long\n"); break; 634175164Sjhb case CTLTYPE_ULONG: printf(" u_long\n"); break; 635175164Sjhb case CTLTYPE_STRING: printf(" String\n"); break; 636175164Sjhb case CTLTYPE_U64: printf(" uint64_t\n"); break; 637175164Sjhb case CTLTYPE_S64: printf(" int64_t\n"); break; 638225617Skmacy case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 639175164Sjhb default: printf("\n"); 640175164Sjhb } 641175164Sjhb 642175164Sjhb } 643175164Sjhb} 644175164Sjhb 645175164Sjhbstatic int 646175164Sjhbsysctl_sysctl_debug(SYSCTL_HANDLER_ARGS) 647175164Sjhb{ 648175164Sjhb int error; 649175164Sjhb 650175164Sjhb error = priv_check(req->td, PRIV_SYSCTL_DEBUG); 651175164Sjhb if (error) 652175164Sjhb return (error); 653175164Sjhb SYSCTL_XLOCK(); 654175164Sjhb sysctl_sysctl_debug_dump_node(&sysctl__children, 0); 655175164Sjhb SYSCTL_XUNLOCK(); 656175164Sjhb return (ENOENT); 657175164Sjhb} 658175164Sjhb 659175164SjhbSYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 660175164Sjhb 0, 0, sysctl_sysctl_debug, "-", ""); 661175164Sjhb#endif 662175164Sjhb 663175164Sjhbstatic int 664175164Sjhbsysctl_sysctl_name(SYSCTL_HANDLER_ARGS) 665175164Sjhb{ 666175164Sjhb int *name = (int *) arg1; 667175164Sjhb u_int namelen = arg2; 668175164Sjhb int error = 0; 669175164Sjhb struct sysctl_oid *oid; 670175164Sjhb struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; 671175164Sjhb char buf[10]; 672175164Sjhb 673185533Skan SYSCTL_XLOCK(); 674185533Skan while (namelen) { 675175164Sjhb if (!lsp) { 676175164Sjhb snprintf(buf,sizeof(buf),"%d",*name); 677175164Sjhb if (req->oldidx) 678175164Sjhb error = SYSCTL_OUT(req, ".", 1); 679175164Sjhb if (!error) 680175164Sjhb error = SYSCTL_OUT(req, buf, strlen(buf)); 681175164Sjhb if (error) 682175164Sjhb goto out; 683175164Sjhb namelen--; 684224914Skib name++; 685224914Skib continue; 686224914Skib } 687224914Skib lsp2 = 0; 688224914Skib SLIST_FOREACH(oid, lsp, oid_link) { 689224914Skib if (oid->oid_number != *name) 690224914Skib continue; 691224914Skib 692224914Skib if (req->oldidx) 693224914Skib error = SYSCTL_OUT(req, ".", 1); 694224914Skib if (!error) 695224914Skib error = SYSCTL_OUT(req, oid->oid_name, 696224914Skib strlen(oid->oid_name)); 697224914Skib if (error) 698224914Skib goto out; 699224914Skib 700224914Skib namelen--; 701224914Skib name++; 702224914Skib 703224914Skib if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 704224914Skib break; 705224914Skib 706224914Skib if (oid->oid_handler) 707224914Skib break; 708224914Skib 709224914Skib lsp2 = SYSCTL_CHILDREN(oid); 710224914Skib break; 711224914Skib } 712224914Skib lsp = lsp2; 713224914Skib } 714224914Skib error = SYSCTL_OUT(req, "", 1); 715224914Skib out: 716224914Skib SYSCTL_XUNLOCK(); 717224914Skib return (error); 718224914Skib} 719224914Skib 720224914Skib/* 721224935Skib * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in 722224914Skib * capability mode. 723224914Skib */ 724224914Skibstatic SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD | CTLFLAG_CAPRD, 725224914Skib sysctl_sysctl_name, ""); 726224914Skib 727224914Skibstatic int 728224914Skibsysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, 729224914Skib int *next, int *len, int level, struct sysctl_oid **oidpp) 730224914Skib{ 731224914Skib struct sysctl_oid *oidp; 732224914Skib 733224914Skib SYSCTL_ASSERT_XLOCKED(); 734224914Skib *len = level; 735224914Skib SLIST_FOREACH(oidp, lsp, oid_link) { 736224914Skib *next = oidp->oid_number; 737224914Skib *oidpp = oidp; 738224914Skib 739224914Skib if (oidp->oid_kind & CTLFLAG_SKIP) 740224914Skib continue; 741224914Skib 742224914Skib if (!namelen) { 743236683Sjhb if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 744236683Sjhb return (0); 745236683Sjhb if (oidp->oid_handler) 746236683Sjhb /* We really should call the handler here...*/ 747236683Sjhb return (0); 748236683Sjhb lsp = SYSCTL_CHILDREN(oidp); 749236683Sjhb if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, 750236683Sjhb len, level+1, oidpp)) 751236683Sjhb return (0); 752236683Sjhb goto emptynode; 753236683Sjhb } 754236683Sjhb 755236683Sjhb if (oidp->oid_number < *name) 756236683Sjhb continue; 757236683Sjhb 758236683Sjhb if (oidp->oid_number > *name) { 759236683Sjhb if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 760236683Sjhb return (0); 761236683Sjhb if (oidp->oid_handler) 762236683Sjhb return (0); 763236683Sjhb lsp = SYSCTL_CHILDREN(oidp); 764236683Sjhb if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, 765236683Sjhb next+1, len, level+1, oidpp)) 766236683Sjhb return (0); 767236683Sjhb goto next; 768236683Sjhb } 769236683Sjhb if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 770236683Sjhb continue; 771236683Sjhb 772236683Sjhb if (oidp->oid_handler) 773236683Sjhb continue; 774236683Sjhb 775236683Sjhb lsp = SYSCTL_CHILDREN(oidp); 776236683Sjhb if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, 777236683Sjhb len, level+1, oidpp)) 778236683Sjhb return (0); 779236683Sjhb next: 780236683Sjhb namelen = 1; 781258870Sjhb emptynode: 782236683Sjhb *len = level; 783236683Sjhb } 784236683Sjhb return (1); 785236683Sjhb} 786236683Sjhb 787236683Sjhbstatic int 788236683Sjhbsysctl_sysctl_next(SYSCTL_HANDLER_ARGS) 789236683Sjhb{ 790236683Sjhb int *name = (int *) arg1; 791236683Sjhb u_int namelen = arg2; 792236683Sjhb int i, j, error; 793236683Sjhb struct sysctl_oid *oid; 794236683Sjhb struct sysctl_oid_list *lsp = &sysctl__children; 795236683Sjhb int newoid[CTL_MAXNAME]; 796236683Sjhb 797236683Sjhb SYSCTL_XLOCK(); 798236683Sjhb i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid); 799236683Sjhb SYSCTL_XUNLOCK(); 800236683Sjhb if (i) 801236683Sjhb return (ENOENT); 802236683Sjhb error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 803236683Sjhb return (error); 804236683Sjhb} 805236683Sjhb 806236683Sjhb/* 807236683Sjhb * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in 808236683Sjhb * capability mode. 809236683Sjhb */ 810236683Sjhbstatic SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_CAPRD, 811236683Sjhb sysctl_sysctl_next, ""); 812236683Sjhb 813236683Sjhbstatic int 814236683Sjhbname2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp) 815236683Sjhb{ 816236683Sjhb struct sysctl_oid *oidp; 817236683Sjhb struct sysctl_oid_list *lsp = &sysctl__children; 818236683Sjhb char *p; 819236683Sjhb 820236683Sjhb SYSCTL_ASSERT_XLOCKED(); 821236683Sjhb 822236683Sjhb for (*len = 0; *len < CTL_MAXNAME;) { 823236683Sjhb p = strsep(&name, "."); 824236683Sjhb 825236683Sjhb oidp = SLIST_FIRST(lsp); 826236683Sjhb for (;; oidp = SLIST_NEXT(oidp, oid_link)) { 827236683Sjhb if (oidp == NULL) 828236683Sjhb return (ENOENT); 829236683Sjhb if (strcmp(p, oidp->oid_name) == 0) 830236683Sjhb break; 831236683Sjhb } 832236683Sjhb *oid++ = oidp->oid_number; 833236683Sjhb (*len)++; 834236683Sjhb 835236683Sjhb if (name == NULL || *name == '\0') { 836236683Sjhb if (oidpp) 837236683Sjhb *oidpp = oidp; 838236683Sjhb return (0); 839236683Sjhb } 840236683Sjhb 841236683Sjhb if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 842236683Sjhb break; 843236683Sjhb 844236683Sjhb if (oidp->oid_handler) 845236698Sjhb break; 846236698Sjhb 847236698Sjhb lsp = SYSCTL_CHILDREN(oidp); 848236698Sjhb } 849236698Sjhb return (ENOENT); 850236698Sjhb} 851236698Sjhb 852236698Sjhbstatic int 853236698Sjhbsysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS) 854236698Sjhb{ 855236698Sjhb char *p; 856236698Sjhb int error, oid[CTL_MAXNAME], len = 0; 857 struct sysctl_oid *op = 0; 858 859 if (!req->newlen) 860 return (ENOENT); 861 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */ 862 return (ENAMETOOLONG); 863 864 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 865 866 error = SYSCTL_IN(req, p, req->newlen); 867 if (error) { 868 free(p, M_SYSCTL); 869 return (error); 870 } 871 872 p [req->newlen] = '\0'; 873 874 SYSCTL_XLOCK(); 875 error = name2oid(p, oid, &len, &op); 876 SYSCTL_XUNLOCK(); 877 878 free(p, M_SYSCTL); 879 880 if (error) 881 return (error); 882 883 error = SYSCTL_OUT(req, oid, len * sizeof *oid); 884 return (error); 885} 886 887/* 888 * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in 889 * capability mode. 890 */ 891SYSCTL_PROC(_sysctl, 3, name2oid, 892 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE 893 | CTLFLAG_CAPRW, 0, 0, sysctl_sysctl_name2oid, "I", ""); 894 895static int 896sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS) 897{ 898 struct sysctl_oid *oid; 899 int error; 900 901 SYSCTL_XLOCK(); 902 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 903 if (error) 904 goto out; 905 906 if (oid->oid_fmt == NULL) { 907 error = ENOENT; 908 goto out; 909 } 910 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind)); 911 if (error) 912 goto out; 913 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1); 914 out: 915 SYSCTL_XUNLOCK(); 916 return (error); 917} 918 919 920static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD, 921 sysctl_sysctl_oidfmt, ""); 922 923static int 924sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS) 925{ 926 struct sysctl_oid *oid; 927 int error; 928 929 SYSCTL_XLOCK(); 930 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 931 if (error) 932 goto out; 933 934 if (oid->oid_descr == NULL) { 935 error = ENOENT; 936 goto out; 937 } 938 error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1); 939 out: 940 SYSCTL_XUNLOCK(); 941 return (error); 942} 943 944static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD|CTLFLAG_CAPRD, 945 sysctl_sysctl_oiddescr, ""); 946 947/* 948 * Default "handler" functions. 949 */ 950 951/* 952 * Handle an int, signed or unsigned. 953 * Two cases: 954 * a variable: point arg1 at it. 955 * a constant: pass it in arg2. 956 */ 957 958int 959sysctl_handle_int(SYSCTL_HANDLER_ARGS) 960{ 961 int tmpout, error = 0; 962 963 /* 964 * Attempt to get a coherent snapshot by making a copy of the data. 965 */ 966 if (arg1) 967 tmpout = *(int *)arg1; 968 else 969 tmpout = arg2; 970 error = SYSCTL_OUT(req, &tmpout, sizeof(int)); 971 972 if (error || !req->newptr) 973 return (error); 974 975 if (!arg1) 976 error = EPERM; 977 else 978 error = SYSCTL_IN(req, arg1, sizeof(int)); 979 return (error); 980} 981 982/* 983 * Based on on sysctl_handle_int() convert milliseconds into ticks. 984 * Note: this is used by TCP. 985 */ 986 987int 988sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS) 989{ 990 int error, s, tt; 991 992 tt = *(int *)arg1; 993 s = (int)((int64_t)tt * 1000 / hz); 994 995 error = sysctl_handle_int(oidp, &s, 0, req); 996 if (error || !req->newptr) 997 return (error); 998 999 tt = (int)((int64_t)s * hz / 1000); 1000 if (tt < 1) 1001 return (EINVAL); 1002 1003 *(int *)arg1 = tt; 1004 return (0); 1005} 1006 1007 1008/* 1009 * Handle a long, signed or unsigned. 1010 * Two cases: 1011 * a variable: point arg1 at it. 1012 * a constant: pass it in arg2. 1013 */ 1014 1015int 1016sysctl_handle_long(SYSCTL_HANDLER_ARGS) 1017{ 1018 int error = 0; 1019 long tmplong; 1020#ifdef SCTL_MASK32 1021 int tmpint; 1022#endif 1023 1024 /* 1025 * Attempt to get a coherent snapshot by making a copy of the data. 1026 */ 1027 if (arg1) 1028 tmplong = *(long *)arg1; 1029 else 1030 tmplong = arg2; 1031#ifdef SCTL_MASK32 1032 if (req->flags & SCTL_MASK32) { 1033 tmpint = tmplong; 1034 error = SYSCTL_OUT(req, &tmpint, sizeof(int)); 1035 } else 1036#endif 1037 error = SYSCTL_OUT(req, &tmplong, sizeof(long)); 1038 1039 if (error || !req->newptr) 1040 return (error); 1041 1042 if (!arg1) 1043 error = EPERM; 1044#ifdef SCTL_MASK32 1045 else if (req->flags & SCTL_MASK32) { 1046 error = SYSCTL_IN(req, &tmpint, sizeof(int)); 1047 *(long *)arg1 = (long)tmpint; 1048 } 1049#endif 1050 else 1051 error = SYSCTL_IN(req, arg1, sizeof(long)); 1052 return (error); 1053} 1054 1055/* 1056 * Handle a 64 bit int, signed or unsigned. 1057 * Two cases: 1058 * a variable: point arg1 at it. 1059 * a constant: pass it in arg2. 1060 */ 1061int 1062sysctl_handle_64(SYSCTL_HANDLER_ARGS) 1063{ 1064 int error = 0; 1065 uint64_t tmpout; 1066 1067 /* 1068 * Attempt to get a coherent snapshot by making a copy of the data. 1069 */ 1070 if (arg1) 1071 tmpout = *(uint64_t *)arg1; 1072 else 1073 tmpout = arg2; 1074 error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t)); 1075 1076 if (error || !req->newptr) 1077 return (error); 1078 1079 if (!arg1) 1080 error = EPERM; 1081 else 1082 error = SYSCTL_IN(req, arg1, sizeof(uint64_t)); 1083 return (error); 1084} 1085 1086/* 1087 * Handle our generic '\0' terminated 'C' string. 1088 * Two cases: 1089 * a variable string: point arg1 at it, arg2 is max length. 1090 * a constant string: point arg1 at it, arg2 is zero. 1091 */ 1092 1093int 1094sysctl_handle_string(SYSCTL_HANDLER_ARGS) 1095{ 1096 int error=0; 1097 char *tmparg; 1098 size_t outlen; 1099 1100 /* 1101 * Attempt to get a coherent snapshot by copying to a 1102 * temporary kernel buffer. 1103 */ 1104retry: 1105 outlen = strlen((char *)arg1)+1; 1106 tmparg = malloc(outlen, M_SYSCTLTMP, M_WAITOK); 1107 1108 if (strlcpy(tmparg, (char *)arg1, outlen) >= outlen) { 1109 free(tmparg, M_SYSCTLTMP); 1110 goto retry; 1111 } 1112 1113 error = SYSCTL_OUT(req, tmparg, outlen); 1114 free(tmparg, M_SYSCTLTMP); 1115 1116 if (error || !req->newptr) 1117 return (error); 1118 1119 if ((req->newlen - req->newidx) >= arg2) { 1120 error = EINVAL; 1121 } else { 1122 arg2 = (req->newlen - req->newidx); 1123 error = SYSCTL_IN(req, arg1, arg2); 1124 ((char *)arg1)[arg2] = '\0'; 1125 } 1126 1127 return (error); 1128} 1129 1130/* 1131 * Handle any kind of opaque data. 1132 * arg1 points to it, arg2 is the size. 1133 */ 1134 1135int 1136sysctl_handle_opaque(SYSCTL_HANDLER_ARGS) 1137{ 1138 int error, tries; 1139 u_int generation; 1140 struct sysctl_req req2; 1141 1142 /* 1143 * Attempt to get a coherent snapshot, by using the thread 1144 * pre-emption counter updated from within mi_switch() to 1145 * determine if we were pre-empted during a bcopy() or 1146 * copyout(). Make 3 attempts at doing this before giving up. 1147 * If we encounter an error, stop immediately. 1148 */ 1149 tries = 0; 1150 req2 = *req; 1151retry: 1152 generation = curthread->td_generation; 1153 error = SYSCTL_OUT(req, arg1, arg2); 1154 if (error) 1155 return (error); 1156 tries++; 1157 if (generation != curthread->td_generation && tries < 3) { 1158 *req = req2; 1159 goto retry; 1160 } 1161 1162 error = SYSCTL_IN(req, arg1, arg2); 1163 1164 return (error); 1165} 1166 1167/* 1168 * Transfer functions to/from kernel space. 1169 * XXX: rather untested at this point 1170 */ 1171static int 1172sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l) 1173{ 1174 size_t i = 0; 1175 1176 if (req->oldptr) { 1177 i = l; 1178 if (req->oldlen <= req->oldidx) 1179 i = 0; 1180 else 1181 if (i > req->oldlen - req->oldidx) 1182 i = req->oldlen - req->oldidx; 1183 if (i > 0) 1184 bcopy(p, (char *)req->oldptr + req->oldidx, i); 1185 } 1186 req->oldidx += l; 1187 if (req->oldptr && i != l) 1188 return (ENOMEM); 1189 return (0); 1190} 1191 1192static int 1193sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) 1194{ 1195 if (!req->newptr) 1196 return (0); 1197 if (req->newlen - req->newidx < l) 1198 return (EINVAL); 1199 bcopy((char *)req->newptr + req->newidx, p, l); 1200 req->newidx += l; 1201 return (0); 1202} 1203 1204int 1205kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, 1206 size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags) 1207{ 1208 int error = 0; 1209 struct sysctl_req req; 1210 1211 bzero(&req, sizeof req); 1212 1213 req.td = td; 1214 req.flags = flags; 1215 1216 if (oldlenp) { 1217 req.oldlen = *oldlenp; 1218 } 1219 req.validlen = req.oldlen; 1220 1221 if (old) { 1222 req.oldptr= old; 1223 } 1224 1225 if (new != NULL) { 1226 req.newlen = newlen; 1227 req.newptr = new; 1228 } 1229 1230 req.oldfunc = sysctl_old_kernel; 1231 req.newfunc = sysctl_new_kernel; 1232 req.lock = REQ_UNWIRED; 1233 1234 SYSCTL_XLOCK(); 1235 error = sysctl_root(0, name, namelen, &req); 1236 SYSCTL_XUNLOCK(); 1237 1238 if (req.lock == REQ_WIRED && req.validlen > 0) 1239 vsunlock(req.oldptr, req.validlen); 1240 1241 if (error && error != ENOMEM) 1242 return (error); 1243 1244 if (retval) { 1245 if (req.oldptr && req.oldidx > req.validlen) 1246 *retval = req.validlen; 1247 else 1248 *retval = req.oldidx; 1249 } 1250 return (error); 1251} 1252 1253int 1254kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, 1255 void *new, size_t newlen, size_t *retval, int flags) 1256{ 1257 int oid[CTL_MAXNAME]; 1258 size_t oidlen, plen; 1259 int error; 1260 1261 oid[0] = 0; /* sysctl internal magic */ 1262 oid[1] = 3; /* name2oid */ 1263 oidlen = sizeof(oid); 1264 1265 error = kernel_sysctl(td, oid, 2, oid, &oidlen, 1266 (void *)name, strlen(name), &plen, flags); 1267 if (error) 1268 return (error); 1269 1270 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp, 1271 new, newlen, retval, flags); 1272 return (error); 1273} 1274 1275/* 1276 * Transfer function to/from user space. 1277 */ 1278static int 1279sysctl_old_user(struct sysctl_req *req, const void *p, size_t l) 1280{ 1281 size_t i, len, origidx; 1282 int error; 1283 1284 origidx = req->oldidx; 1285 req->oldidx += l; 1286 if (req->oldptr == NULL) 1287 return (0); 1288 /* 1289 * If we have not wired the user supplied buffer and we are currently 1290 * holding locks, drop a witness warning, as it's possible that 1291 * write operations to the user page can sleep. 1292 */ 1293 if (req->lock != REQ_WIRED) 1294 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 1295 "sysctl_old_user()"); 1296 i = l; 1297 len = req->validlen; 1298 if (len <= origidx) 1299 i = 0; 1300 else { 1301 if (i > len - origidx) 1302 i = len - origidx; 1303 if (req->lock == REQ_WIRED) { 1304 error = copyout_nofault(p, (char *)req->oldptr + 1305 origidx, i); 1306 } else 1307 error = copyout(p, (char *)req->oldptr + origidx, i); 1308 if (error != 0) 1309 return (error); 1310 } 1311 if (i < l) 1312 return (ENOMEM); 1313 return (0); 1314} 1315 1316static int 1317sysctl_new_user(struct sysctl_req *req, void *p, size_t l) 1318{ 1319 int error; 1320 1321 if (!req->newptr) 1322 return (0); 1323 if (req->newlen - req->newidx < l) 1324 return (EINVAL); 1325 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 1326 "sysctl_new_user()"); 1327 error = copyin((char *)req->newptr + req->newidx, p, l); 1328 req->newidx += l; 1329 return (error); 1330} 1331 1332/* 1333 * Wire the user space destination buffer. If set to a value greater than 1334 * zero, the len parameter limits the maximum amount of wired memory. 1335 */ 1336int 1337sysctl_wire_old_buffer(struct sysctl_req *req, size_t len) 1338{ 1339 int ret; 1340 size_t wiredlen; 1341 1342 wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen; 1343 ret = 0; 1344 if (req->lock != REQ_WIRED && req->oldptr && 1345 req->oldfunc == sysctl_old_user) { 1346 if (wiredlen != 0) { 1347 ret = vslock(req->oldptr, wiredlen); 1348 if (ret != 0) { 1349 if (ret != ENOMEM) 1350 return (ret); 1351 wiredlen = 0; 1352 } 1353 } 1354 req->lock = REQ_WIRED; 1355 req->validlen = wiredlen; 1356 } 1357 return (0); 1358} 1359 1360int 1361sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, 1362 int *nindx, struct sysctl_req *req) 1363{ 1364 struct sysctl_oid_list *lsp; 1365 struct sysctl_oid *oid; 1366 int indx; 1367 1368 SYSCTL_ASSERT_XLOCKED(); 1369 lsp = &sysctl__children; 1370 indx = 0; 1371 while (indx < CTL_MAXNAME) { 1372 SLIST_FOREACH(oid, lsp, oid_link) { 1373 if (oid->oid_number == name[indx]) 1374 break; 1375 } 1376 if (oid == NULL) 1377 return (ENOENT); 1378 1379 indx++; 1380 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1381 if (oid->oid_handler != NULL || indx == namelen) { 1382 *noid = oid; 1383 if (nindx != NULL) 1384 *nindx = indx; 1385 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0, 1386 ("%s found DYING node %p", __func__, oid)); 1387 return (0); 1388 } 1389 lsp = SYSCTL_CHILDREN(oid); 1390 } else if (indx == namelen) { 1391 *noid = oid; 1392 if (nindx != NULL) 1393 *nindx = indx; 1394 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0, 1395 ("%s found DYING node %p", __func__, oid)); 1396 return (0); 1397 } else { 1398 return (ENOTDIR); 1399 } 1400 } 1401 return (ENOENT); 1402} 1403 1404/* 1405 * Traverse our tree, and find the right node, execute whatever it points 1406 * to, and return the resulting error code. 1407 */ 1408 1409static int 1410sysctl_root(SYSCTL_HANDLER_ARGS) 1411{ 1412 struct sysctl_oid *oid; 1413 int error, indx, lvl; 1414 1415 SYSCTL_ASSERT_XLOCKED(); 1416 1417 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req); 1418 if (error) 1419 return (error); 1420 1421 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1422 /* 1423 * You can't call a sysctl when it's a node, but has 1424 * no handler. Inform the user that it's a node. 1425 * The indx may or may not be the same as namelen. 1426 */ 1427 if (oid->oid_handler == NULL) 1428 return (EISDIR); 1429 } 1430 1431 /* Is this sysctl writable? */ 1432 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) 1433 return (EPERM); 1434 1435 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); 1436 1437#ifdef CAPABILITY_MODE 1438 /* 1439 * If the process is in capability mode, then don't permit reading or 1440 * writing unless specifically granted for the node. 1441 */ 1442 if (IN_CAPABILITY_MODE(req->td)) { 1443 if (req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) 1444 return (EPERM); 1445 if (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR)) 1446 return (EPERM); 1447 } 1448#endif 1449 1450 /* Is this sysctl sensitive to securelevels? */ 1451 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { 1452 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE; 1453 error = securelevel_gt(req->td->td_ucred, lvl); 1454 if (error) 1455 return (error); 1456 } 1457 1458 /* Is this sysctl writable by only privileged users? */ 1459 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) { 1460 int priv; 1461 1462 if (oid->oid_kind & CTLFLAG_PRISON) 1463 priv = PRIV_SYSCTL_WRITEJAIL; 1464#ifdef VIMAGE 1465 else if ((oid->oid_kind & CTLFLAG_VNET) && 1466 prison_owns_vnet(req->td->td_ucred)) 1467 priv = PRIV_SYSCTL_WRITEJAIL; 1468#endif 1469 else 1470 priv = PRIV_SYSCTL_WRITE; 1471 error = priv_check(req->td, priv); 1472 if (error) 1473 return (error); 1474 } 1475 1476 if (!oid->oid_handler) 1477 return (EINVAL); 1478 1479 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1480 arg1 = (int *)arg1 + indx; 1481 arg2 -= indx; 1482 } else { 1483 arg1 = oid->oid_arg1; 1484 arg2 = oid->oid_arg2; 1485 } 1486#ifdef MAC 1487 error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2, 1488 req); 1489 if (error != 0) 1490 return (error); 1491#endif 1492 oid->oid_running++; 1493 SYSCTL_XUNLOCK(); 1494#ifdef VIMAGE 1495 if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL) 1496 arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1); 1497#endif 1498 if (!(oid->oid_kind & CTLFLAG_MPSAFE)) 1499 mtx_lock(&Giant); 1500 error = oid->oid_handler(oid, arg1, arg2, req); 1501 if (!(oid->oid_kind & CTLFLAG_MPSAFE)) 1502 mtx_unlock(&Giant); 1503 1504 KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error); 1505 1506 SYSCTL_XLOCK(); 1507 oid->oid_running--; 1508 if (oid->oid_running == 0 && (oid->oid_kind & CTLFLAG_DYING) != 0) 1509 wakeup(&oid->oid_running); 1510 return (error); 1511} 1512 1513#ifndef _SYS_SYSPROTO_H_ 1514struct sysctl_args { 1515 int *name; 1516 u_int namelen; 1517 void *old; 1518 size_t *oldlenp; 1519 void *new; 1520 size_t newlen; 1521}; 1522#endif 1523int 1524sys___sysctl(struct thread *td, struct sysctl_args *uap) 1525{ 1526 int error, i, name[CTL_MAXNAME]; 1527 size_t j; 1528 1529 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1530 return (EINVAL); 1531 1532 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1533 if (error) 1534 return (error); 1535 1536 error = userland_sysctl(td, name, uap->namelen, 1537 uap->old, uap->oldlenp, 0, 1538 uap->new, uap->newlen, &j, 0); 1539 if (error && error != ENOMEM) 1540 return (error); 1541 if (uap->oldlenp) { 1542 i = copyout(&j, uap->oldlenp, sizeof(j)); 1543 if (i) 1544 return (i); 1545 } 1546 return (error); 1547} 1548 1549/* 1550 * This is used from various compatibility syscalls too. That's why name 1551 * must be in kernel space. 1552 */ 1553int 1554userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, 1555 size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval, 1556 int flags) 1557{ 1558 int error = 0, memlocked; 1559 struct sysctl_req req; 1560 1561 bzero(&req, sizeof req); 1562 1563 req.td = td; 1564 req.flags = flags; 1565 1566 if (oldlenp) { 1567 if (inkernel) { 1568 req.oldlen = *oldlenp; 1569 } else { 1570 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 1571 if (error) 1572 return (error); 1573 } 1574 } 1575 req.validlen = req.oldlen; 1576 1577 if (old) { 1578 if (!useracc(old, req.oldlen, VM_PROT_WRITE)) 1579 return (EFAULT); 1580 req.oldptr= old; 1581 } 1582 1583 if (new != NULL) { 1584 if (!useracc(new, newlen, VM_PROT_READ)) 1585 return (EFAULT); 1586 req.newlen = newlen; 1587 req.newptr = new; 1588 } 1589 1590 req.oldfunc = sysctl_old_user; 1591 req.newfunc = sysctl_new_user; 1592 req.lock = REQ_UNWIRED; 1593 1594#ifdef KTRACE 1595 if (KTRPOINT(curthread, KTR_SYSCTL)) 1596 ktrsysctl(name, namelen); 1597#endif 1598 1599 if (req.oldlen > PAGE_SIZE) { 1600 memlocked = 1; 1601 sx_xlock(&sysctlmemlock); 1602 } else 1603 memlocked = 0; 1604 CURVNET_SET(TD_TO_VNET(td)); 1605 1606 for (;;) { 1607 req.oldidx = 0; 1608 req.newidx = 0; 1609 SYSCTL_XLOCK(); 1610 error = sysctl_root(0, name, namelen, &req); 1611 SYSCTL_XUNLOCK(); 1612 if (error != EAGAIN) 1613 break; 1614 kern_yield(PRI_USER); 1615 } 1616 1617 CURVNET_RESTORE(); 1618 1619 if (req.lock == REQ_WIRED && req.validlen > 0) 1620 vsunlock(req.oldptr, req.validlen); 1621 if (memlocked) 1622 sx_xunlock(&sysctlmemlock); 1623 1624 if (error && error != ENOMEM) 1625 return (error); 1626 1627 if (retval) { 1628 if (req.oldptr && req.oldidx > req.validlen) 1629 *retval = req.validlen; 1630 else 1631 *retval = req.oldidx; 1632 } 1633 return (error); 1634} 1635 1636/* 1637 * Drain into a sysctl struct. The user buffer should be wired if a page 1638 * fault would cause issue. 1639 */ 1640static int 1641sbuf_sysctl_drain(void *arg, const char *data, int len) 1642{ 1643 struct sysctl_req *req = arg; 1644 int error; 1645 1646 error = SYSCTL_OUT(req, data, len); 1647 KASSERT(error >= 0, ("Got unexpected negative value %d", error)); 1648 return (error == 0 ? len : -error); 1649} 1650 1651struct sbuf * 1652sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length, 1653 struct sysctl_req *req) 1654{ 1655 1656 s = sbuf_new(s, buf, length, SBUF_FIXEDLEN); 1657 sbuf_set_drain(s, sbuf_sysctl_drain, req); 1658 return (s); 1659} 1660