1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD 11 * project, to make these variables more userfriendly. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 38 */ 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 #include "opt_capsicum.h" 44 #include "opt_ktrace.h" 45 46 #include <sys/param.h> 47 #include <sys/fail.h> 48 #include <sys/systm.h> 49 #include <sys/capsicum.h> 50 #include <sys/kernel.h> 51 #include <sys/sysctl.h> 52 #include <sys/malloc.h> 53 #include <sys/priv.h> 54 #include <sys/proc.h> 55 #include <sys/jail.h> 56 #include <sys/lock.h> 57 #include <sys/mutex.h> 58 #include <sys/rmlock.h> 59 #include <sys/sbuf.h> 60 #include <sys/sx.h> 61 #include <sys/sysproto.h> 62 #include <sys/uio.h> 63 #ifdef KTRACE 64 #include <sys/ktrace.h> 65 #endif 66 67 #include <net/vnet.h> 68 69 #include <security/mac/mac_framework.h> 70 71 #include <vm/vm.h> 72 #include <vm/vm_extern.h> 73 74 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); 75 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); 76 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer"); 77 78 /* 79 * The sysctllock protects the MIB tree. It also protects sysctl 80 * contexts used with dynamic sysctls. The sysctl_register_oid() and 81 * sysctl_unregister_oid() routines require the sysctllock to already 82 * be held, so the sysctl_wlock() and sysctl_wunlock() routines are 83 * provided for the few places in the kernel which need to use that 84 * API rather than using the dynamic API. Use of the dynamic API is 85 * strongly encouraged for most code. 86 * 87 * The sysctlmemlock is used to limit the amount of user memory wired for 88 * sysctl requests. This is implemented by serializing any userland 89 * sysctl requests larger than a single page via an exclusive lock. 90 */ 91 static struct rmlock sysctllock; 92 static struct sx __exclusive_cache_line sysctlmemlock; 93 94 #define SYSCTL_WLOCK() rm_wlock(&sysctllock) 95 #define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock) 96 #define SYSCTL_RLOCK(tracker) rm_rlock(&sysctllock, (tracker)) 97 #define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker)) 98 #define SYSCTL_WLOCKED() rm_wowned(&sysctllock) 99 #define SYSCTL_ASSERT_LOCKED() rm_assert(&sysctllock, RA_LOCKED) 100 #define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED) 101 #define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED) 102 #define SYSCTL_INIT() rm_init_flags(&sysctllock, "sysctl lock", \ 103 RM_SLEEPABLE) 104 #define SYSCTL_SLEEP(ch, wmesg, timo) \ 105 rm_sleep(ch, &sysctllock, 0, wmesg, timo) 106 107 static int sysctl_root(SYSCTL_HANDLER_ARGS); 108 109 /* Root list */ 110 struct sysctl_oid_list sysctl__children = SLIST_HEAD_INITIALIZER(&sysctl__children); 111 112 static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, 113 int recurse); 114 static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t); 115 static int sysctl_new_kernel(struct sysctl_req *, void *, size_t); 116 117 static struct sysctl_oid * 118 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list) 119 { 120 struct sysctl_oid *oidp; 121 122 SYSCTL_ASSERT_LOCKED(); 123 SLIST_FOREACH(oidp, list, oid_link) { 124 if (strcmp(oidp->oid_name, name) == 0) { 125 return (oidp); 126 } 127 } 128 return (NULL); 129 } 130 131 /* 132 * Initialization of the MIB tree. 133 * 134 * Order by number in each list. 135 */ 136 void 137 sysctl_wlock(void) 138 { 139 140 SYSCTL_WLOCK(); 141 } 142 143 void 144 sysctl_wunlock(void) 145 { 146 147 SYSCTL_WUNLOCK(); 148 } 149 150 static int 151 sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intmax_t arg2, 152 struct sysctl_req *req, struct rm_priotracker *tracker) 153 { 154 int error; 155 156 if (oid->oid_kind & CTLFLAG_DYN) 157 atomic_add_int(&oid->oid_running, 1); 158 159 if (tracker != NULL) 160 SYSCTL_RUNLOCK(tracker); 161 else 162 SYSCTL_WUNLOCK(); 163 164 if (!(oid->oid_kind & CTLFLAG_MPSAFE)) 165 mtx_lock(&Giant); 166 error = oid->oid_handler(oid, arg1, arg2, req); 167 if (!(oid->oid_kind & CTLFLAG_MPSAFE)) 168 mtx_unlock(&Giant); 169 170 KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error); 171 172 if (tracker != NULL) 173 SYSCTL_RLOCK(tracker); 174 else 175 SYSCTL_WLOCK(); 176 177 if (oid->oid_kind & CTLFLAG_DYN) { 178 if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 && 179 (oid->oid_kind & CTLFLAG_DYING) != 0) 180 wakeup(&oid->oid_running); 181 } 182 183 return (error); 184 } 185 186 static void 187 sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp) 188 { 189 struct sysctl_req req; 190 struct sysctl_oid *curr; 191 char *penv = NULL; 192 char path[96]; 193 ssize_t rem = sizeof(path); 194 ssize_t len; 195 uint8_t data[512] __aligned(sizeof(uint64_t)); 196 int size; 197 int error; 198 199 path[--rem] = 0; 200 201 for (curr = oidp; curr != NULL; curr = SYSCTL_PARENT(curr)) { 202 len = strlen(curr->oid_name); 203 rem -= len; 204 if (curr != oidp) 205 rem -= 1; 206 if (rem < 0) { 207 printf("OID path exceeds %d bytes\n", (int)sizeof(path)); 208 return; 209 } 210 memcpy(path + rem, curr->oid_name, len); 211 if (curr != oidp) 212 path[rem + len] = '.'; 213 } 214 215 memset(&req, 0, sizeof(req)); 216 217 req.td = curthread; 218 req.oldfunc = sysctl_old_kernel; 219 req.newfunc = sysctl_new_kernel; 220 req.lock = REQ_UNWIRED; 221 222 switch (oidp->oid_kind & CTLTYPE) { 223 case CTLTYPE_INT: 224 if (getenv_array(path + rem, data, sizeof(data), &size, 225 sizeof(int), GETENV_SIGNED) == 0) 226 return; 227 req.newlen = size; 228 req.newptr = data; 229 break; 230 case CTLTYPE_UINT: 231 if (getenv_array(path + rem, data, sizeof(data), &size, 232 sizeof(int), GETENV_UNSIGNED) == 0) 233 return; 234 req.newlen = size; 235 req.newptr = data; 236 break; 237 case CTLTYPE_LONG: 238 if (getenv_array(path + rem, data, sizeof(data), &size, 239 sizeof(long), GETENV_SIGNED) == 0) 240 return; 241 req.newlen = size; 242 req.newptr = data; 243 break; 244 case CTLTYPE_ULONG: 245 if (getenv_array(path + rem, data, sizeof(data), &size, 246 sizeof(long), GETENV_UNSIGNED) == 0) 247 return; 248 req.newlen = size; 249 req.newptr = data; 250 break; 251 case CTLTYPE_S8: 252 if (getenv_array(path + rem, data, sizeof(data), &size, 253 sizeof(int8_t), GETENV_SIGNED) == 0) 254 return; 255 req.newlen = size; 256 req.newptr = data; 257 break; 258 case CTLTYPE_S16: 259 if (getenv_array(path + rem, data, sizeof(data), &size, 260 sizeof(int16_t), GETENV_SIGNED) == 0) 261 return; 262 req.newlen = size; 263 req.newptr = data; 264 break; 265 case CTLTYPE_S32: 266 if (getenv_array(path + rem, data, sizeof(data), &size, 267 sizeof(int32_t), GETENV_SIGNED) == 0) 268 return; 269 req.newlen = size; 270 req.newptr = data; 271 break; 272 case CTLTYPE_S64: 273 if (getenv_array(path + rem, data, sizeof(data), &size, 274 sizeof(int64_t), GETENV_SIGNED) == 0) 275 return; 276 req.newlen = size; 277 req.newptr = data; 278 break; 279 case CTLTYPE_U8: 280 if (getenv_array(path + rem, data, sizeof(data), &size, 281 sizeof(uint8_t), GETENV_UNSIGNED) == 0) 282 return; 283 req.newlen = size; 284 req.newptr = data; 285 break; 286 case CTLTYPE_U16: 287 if (getenv_array(path + rem, data, sizeof(data), &size, 288 sizeof(uint16_t), GETENV_UNSIGNED) == 0) 289 return; 290 req.newlen = size; 291 req.newptr = data; 292 break; 293 case CTLTYPE_U32: 294 if (getenv_array(path + rem, data, sizeof(data), &size, 295 sizeof(uint32_t), GETENV_UNSIGNED) == 0) 296 return; 297 req.newlen = size; 298 req.newptr = data; 299 break; 300 case CTLTYPE_U64: 301 if (getenv_array(path + rem, data, sizeof(data), &size, 302 sizeof(uint64_t), GETENV_UNSIGNED) == 0) 303 return; 304 req.newlen = size; 305 req.newptr = data; 306 break; 307 case CTLTYPE_STRING: 308 penv = kern_getenv(path + rem); 309 if (penv == NULL) 310 return; 311 req.newlen = strlen(penv); 312 req.newptr = penv; 313 break; 314 default: 315 return; 316 } 317 error = sysctl_root_handler_locked(oidp, oidp->oid_arg1, 318 oidp->oid_arg2, &req, NULL); 319 if (error != 0) 320 printf("Setting sysctl %s failed: %d\n", path + rem, error); 321 if (penv != NULL) 322 freeenv(penv); 323 } 324 325 /* 326 * Locate the path to a given oid. Returns the length of the resulting path, 327 * or -1 if the oid was not found. nodes must have room for CTL_MAXNAME 328 * elements and be NULL initialized. 329 */ 330 static int 331 sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle) 332 { 333 int indx; 334 335 SYSCTL_ASSERT_LOCKED(); 336 indx = 0; 337 while (indx < CTL_MAXNAME && indx >= 0) { 338 if (nodes[indx] == NULL && indx == 0) 339 nodes[indx] = SLIST_FIRST(&sysctl__children); 340 else if (nodes[indx] == NULL) 341 nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children); 342 else 343 nodes[indx] = SLIST_NEXT(nodes[indx], oid_link); 344 345 if (nodes[indx] == needle) 346 return (indx + 1); 347 348 if (nodes[indx] == NULL) { 349 indx--; 350 continue; 351 } 352 353 if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 354 indx++; 355 continue; 356 } 357 } 358 return (-1); 359 } 360 361 static void 362 sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf) 363 { 364 struct sysctl_oid *nodes[CTL_MAXNAME]; 365 char buf[128]; 366 struct sbuf sb; 367 int rc, i; 368 369 (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL); 370 sbuf_set_drain(&sb, sbuf_printf_drain, NULL); 371 372 sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__); 373 374 memset(nodes, 0, sizeof(nodes)); 375 rc = sysctl_search_oid(nodes, leaf); 376 if (rc > 0) { 377 for (i = 0; i < rc; i++) 378 sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name, 379 i != (rc - 1), "."); 380 } else { 381 sbuf_printf(&sb, "%s", leaf->oid_name); 382 } 383 sbuf_printf(&sb, ")!\n"); 384 385 (void)sbuf_finish(&sb); 386 } 387 388 #ifdef SYSCTL_DEBUG 389 static int 390 sysctl_reuse_test(SYSCTL_HANDLER_ARGS) 391 { 392 struct rm_priotracker tracker; 393 394 SYSCTL_RLOCK(&tracker); 395 sysctl_warn_reuse(__func__, oidp); 396 SYSCTL_RUNLOCK(&tracker); 397 return (0); 398 } 399 SYSCTL_PROC(_sysctl, 0, reuse_test, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, 400 0, 0, sysctl_reuse_test, "-", ""); 401 #endif 402 403 void 404 sysctl_register_oid(struct sysctl_oid *oidp) 405 { 406 struct sysctl_oid_list *parent = oidp->oid_parent; 407 struct sysctl_oid *p; 408 struct sysctl_oid *q; 409 int oid_number; 410 int timeout = 2; 411 412 /* 413 * First check if another oid with the same name already 414 * exists in the parent's list. 415 */ 416 SYSCTL_ASSERT_WLOCKED(); 417 p = sysctl_find_oidname(oidp->oid_name, parent); 418 if (p != NULL) { 419 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 420 p->oid_refcnt++; 421 return; 422 } else { 423 sysctl_warn_reuse(__func__, p); 424 return; 425 } 426 } 427 /* get current OID number */ 428 oid_number = oidp->oid_number; 429 430 #if (OID_AUTO >= 0) 431 #error "OID_AUTO is expected to be a negative value" 432 #endif 433 /* 434 * Any negative OID number qualifies as OID_AUTO. Valid OID 435 * numbers should always be positive. 436 * 437 * NOTE: DO NOT change the starting value here, change it in 438 * <sys/sysctl.h>, and make sure it is at least 256 to 439 * accommodate e.g. net.inet.raw as a static sysctl node. 440 */ 441 if (oid_number < 0) { 442 static int newoid; 443 444 /* 445 * By decrementing the next OID number we spend less 446 * time inserting the OIDs into a sorted list. 447 */ 448 if (--newoid < CTL_AUTO_START) 449 newoid = 0x7fffffff; 450 451 oid_number = newoid; 452 } 453 454 /* 455 * Insert the OID into the parent's list sorted by OID number. 456 */ 457 retry: 458 q = NULL; 459 SLIST_FOREACH(p, parent, oid_link) { 460 /* check if the current OID number is in use */ 461 if (oid_number == p->oid_number) { 462 /* get the next valid OID number */ 463 if (oid_number < CTL_AUTO_START || 464 oid_number == 0x7fffffff) { 465 /* wraparound - restart */ 466 oid_number = CTL_AUTO_START; 467 /* don't loop forever */ 468 if (!timeout--) 469 panic("sysctl: Out of OID numbers\n"); 470 goto retry; 471 } else { 472 oid_number++; 473 } 474 } else if (oid_number < p->oid_number) 475 break; 476 q = p; 477 } 478 /* check for non-auto OID number collision */ 479 if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START && 480 oid_number >= CTL_AUTO_START) { 481 printf("sysctl: OID number(%d) is already in use for '%s'\n", 482 oidp->oid_number, oidp->oid_name); 483 } 484 /* update the OID number, if any */ 485 oidp->oid_number = oid_number; 486 if (q != NULL) 487 SLIST_INSERT_AFTER(q, oidp, oid_link); 488 else 489 SLIST_INSERT_HEAD(parent, oidp, oid_link); 490 491 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE && 492 #ifdef VIMAGE 493 (oidp->oid_kind & CTLFLAG_VNET) == 0 && 494 #endif 495 (oidp->oid_kind & CTLFLAG_TUN) != 0 && 496 (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) { 497 /* only fetch value once */ 498 oidp->oid_kind |= CTLFLAG_NOFETCH; 499 /* try to fetch value from kernel environment */ 500 sysctl_load_tunable_by_oid_locked(oidp); 501 } 502 } 503 504 void 505 sysctl_register_disabled_oid(struct sysctl_oid *oidp) 506 { 507 508 /* 509 * Mark the leaf as dormant if it's not to be immediately enabled. 510 * We do not disable nodes as they can be shared between modules 511 * and it is always safe to access a node. 512 */ 513 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0, 514 ("internal flag is set in oid_kind")); 515 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 516 oidp->oid_kind |= CTLFLAG_DORMANT; 517 sysctl_register_oid(oidp); 518 } 519 520 void 521 sysctl_enable_oid(struct sysctl_oid *oidp) 522 { 523 524 SYSCTL_ASSERT_WLOCKED(); 525 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 526 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0, 527 ("sysctl node is marked as dormant")); 528 return; 529 } 530 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) != 0, 531 ("enabling already enabled sysctl oid")); 532 oidp->oid_kind &= ~CTLFLAG_DORMANT; 533 } 534 535 void 536 sysctl_unregister_oid(struct sysctl_oid *oidp) 537 { 538 struct sysctl_oid *p; 539 int error; 540 541 SYSCTL_ASSERT_WLOCKED(); 542 if (oidp->oid_number == OID_AUTO) { 543 error = EINVAL; 544 } else { 545 error = ENOENT; 546 SLIST_FOREACH(p, oidp->oid_parent, oid_link) { 547 if (p == oidp) { 548 SLIST_REMOVE(oidp->oid_parent, oidp, 549 sysctl_oid, oid_link); 550 error = 0; 551 break; 552 } 553 } 554 } 555 556 /* 557 * This can happen when a module fails to register and is 558 * being unloaded afterwards. It should not be a panic() 559 * for normal use. 560 */ 561 if (error) { 562 printf("%s: failed(%d) to unregister sysctl(%s)\n", 563 __func__, error, oidp->oid_name); 564 } 565 } 566 567 /* Initialize a new context to keep track of dynamically added sysctls. */ 568 int 569 sysctl_ctx_init(struct sysctl_ctx_list *c) 570 { 571 572 if (c == NULL) { 573 return (EINVAL); 574 } 575 576 /* 577 * No locking here, the caller is responsible for not adding 578 * new nodes to a context until after this function has 579 * returned. 580 */ 581 TAILQ_INIT(c); 582 return (0); 583 } 584 585 /* Free the context, and destroy all dynamic oids registered in this context */ 586 int 587 sysctl_ctx_free(struct sysctl_ctx_list *clist) 588 { 589 struct sysctl_ctx_entry *e, *e1; 590 int error; 591 592 error = 0; 593 /* 594 * First perform a "dry run" to check if it's ok to remove oids. 595 * XXX FIXME 596 * XXX This algorithm is a hack. But I don't know any 597 * XXX better solution for now... 598 */ 599 SYSCTL_WLOCK(); 600 TAILQ_FOREACH(e, clist, link) { 601 error = sysctl_remove_oid_locked(e->entry, 0, 0); 602 if (error) 603 break; 604 } 605 /* 606 * Restore deregistered entries, either from the end, 607 * or from the place where error occurred. 608 * e contains the entry that was not unregistered 609 */ 610 if (error) 611 e1 = TAILQ_PREV(e, sysctl_ctx_list, link); 612 else 613 e1 = TAILQ_LAST(clist, sysctl_ctx_list); 614 while (e1 != NULL) { 615 sysctl_register_oid(e1->entry); 616 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); 617 } 618 if (error) { 619 SYSCTL_WUNLOCK(); 620 return(EBUSY); 621 } 622 /* Now really delete the entries */ 623 e = TAILQ_FIRST(clist); 624 while (e != NULL) { 625 e1 = TAILQ_NEXT(e, link); 626 error = sysctl_remove_oid_locked(e->entry, 1, 0); 627 if (error) 628 panic("sysctl_remove_oid: corrupt tree, entry: %s", 629 e->entry->oid_name); 630 free(e, M_SYSCTLOID); 631 e = e1; 632 } 633 SYSCTL_WUNLOCK(); 634 return (error); 635 } 636 637 /* Add an entry to the context */ 638 struct sysctl_ctx_entry * 639 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 640 { 641 struct sysctl_ctx_entry *e; 642 643 SYSCTL_ASSERT_WLOCKED(); 644 if (clist == NULL || oidp == NULL) 645 return(NULL); 646 e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); 647 e->entry = oidp; 648 TAILQ_INSERT_HEAD(clist, e, link); 649 return (e); 650 } 651 652 /* Find an entry in the context */ 653 struct sysctl_ctx_entry * 654 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 655 { 656 struct sysctl_ctx_entry *e; 657 658 SYSCTL_ASSERT_WLOCKED(); 659 if (clist == NULL || oidp == NULL) 660 return(NULL); 661 TAILQ_FOREACH(e, clist, link) { 662 if(e->entry == oidp) 663 return(e); 664 } 665 return (e); 666 } 667 668 /* 669 * Delete an entry from the context. 670 * NOTE: this function doesn't free oidp! You have to remove it 671 * with sysctl_remove_oid(). 672 */ 673 int 674 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 675 { 676 struct sysctl_ctx_entry *e; 677 678 if (clist == NULL || oidp == NULL) 679 return (EINVAL); 680 SYSCTL_WLOCK(); 681 e = sysctl_ctx_entry_find(clist, oidp); 682 if (e != NULL) { 683 TAILQ_REMOVE(clist, e, link); 684 SYSCTL_WUNLOCK(); 685 free(e, M_SYSCTLOID); 686 return (0); 687 } else { 688 SYSCTL_WUNLOCK(); 689 return (ENOENT); 690 } 691 } 692 693 /* 694 * Remove dynamically created sysctl trees. 695 * oidp - top of the tree to be removed 696 * del - if 0 - just deregister, otherwise free up entries as well 697 * recurse - if != 0 traverse the subtree to be deleted 698 */ 699 int 700 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse) 701 { 702 int error; 703 704 SYSCTL_WLOCK(); 705 error = sysctl_remove_oid_locked(oidp, del, recurse); 706 SYSCTL_WUNLOCK(); 707 return (error); 708 } 709 710 int 711 sysctl_remove_name(struct sysctl_oid *parent, const char *name, 712 int del, int recurse) 713 { 714 struct sysctl_oid *p, *tmp; 715 int error; 716 717 error = ENOENT; 718 SYSCTL_WLOCK(); 719 SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) { 720 if (strcmp(p->oid_name, name) == 0) { 721 error = sysctl_remove_oid_locked(p, del, recurse); 722 break; 723 } 724 } 725 SYSCTL_WUNLOCK(); 726 727 return (error); 728 } 729 730 731 static int 732 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse) 733 { 734 struct sysctl_oid *p, *tmp; 735 int error; 736 737 SYSCTL_ASSERT_WLOCKED(); 738 if (oidp == NULL) 739 return(EINVAL); 740 if ((oidp->oid_kind & CTLFLAG_DYN) == 0) { 741 printf("Warning: can't remove non-dynamic nodes (%s)!\n", 742 oidp->oid_name); 743 return (EINVAL); 744 } 745 /* 746 * WARNING: normal method to do this should be through 747 * sysctl_ctx_free(). Use recursing as the last resort 748 * method to purge your sysctl tree of leftovers... 749 * However, if some other code still references these nodes, 750 * it will panic. 751 */ 752 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 753 if (oidp->oid_refcnt == 1) { 754 SLIST_FOREACH_SAFE(p, 755 SYSCTL_CHILDREN(oidp), oid_link, tmp) { 756 if (!recurse) { 757 printf("Warning: failed attempt to " 758 "remove oid %s with child %s\n", 759 oidp->oid_name, p->oid_name); 760 return (ENOTEMPTY); 761 } 762 error = sysctl_remove_oid_locked(p, del, 763 recurse); 764 if (error) 765 return (error); 766 } 767 } 768 } 769 if (oidp->oid_refcnt > 1 ) { 770 oidp->oid_refcnt--; 771 } else { 772 if (oidp->oid_refcnt == 0) { 773 printf("Warning: bad oid_refcnt=%u (%s)!\n", 774 oidp->oid_refcnt, oidp->oid_name); 775 return (EINVAL); 776 } 777 sysctl_unregister_oid(oidp); 778 if (del) { 779 /* 780 * Wait for all threads running the handler to drain. 781 * This preserves the previous behavior when the 782 * sysctl lock was held across a handler invocation, 783 * and is necessary for module unload correctness. 784 */ 785 while (oidp->oid_running > 0) { 786 oidp->oid_kind |= CTLFLAG_DYING; 787 SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0); 788 } 789 if (oidp->oid_descr) 790 free(__DECONST(char *, oidp->oid_descr), 791 M_SYSCTLOID); 792 if (oidp->oid_label) 793 free(__DECONST(char *, oidp->oid_label), 794 M_SYSCTLOID); 795 free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID); 796 free(oidp, M_SYSCTLOID); 797 } 798 } 799 return (0); 800 } 801 /* 802 * Create new sysctls at run time. 803 * clist may point to a valid context initialized with sysctl_ctx_init(). 804 */ 805 struct sysctl_oid * 806 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, 807 int number, const char *name, int kind, void *arg1, intmax_t arg2, 808 int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr, 809 const char *label) 810 { 811 struct sysctl_oid *oidp; 812 813 /* You have to hook up somewhere.. */ 814 if (parent == NULL) 815 return(NULL); 816 /* Check if the node already exists, otherwise create it */ 817 SYSCTL_WLOCK(); 818 oidp = sysctl_find_oidname(name, parent); 819 if (oidp != NULL) { 820 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 821 oidp->oid_refcnt++; 822 /* Update the context */ 823 if (clist != NULL) 824 sysctl_ctx_entry_add(clist, oidp); 825 SYSCTL_WUNLOCK(); 826 return (oidp); 827 } else { 828 sysctl_warn_reuse(__func__, oidp); 829 SYSCTL_WUNLOCK(); 830 return (NULL); 831 } 832 } 833 oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO); 834 oidp->oid_parent = parent; 835 SLIST_INIT(&oidp->oid_children); 836 oidp->oid_number = number; 837 oidp->oid_refcnt = 1; 838 oidp->oid_name = strdup(name, M_SYSCTLOID); 839 oidp->oid_handler = handler; 840 oidp->oid_kind = CTLFLAG_DYN | kind; 841 oidp->oid_arg1 = arg1; 842 oidp->oid_arg2 = arg2; 843 oidp->oid_fmt = fmt; 844 if (descr != NULL) 845 oidp->oid_descr = strdup(descr, M_SYSCTLOID); 846 if (label != NULL) 847 oidp->oid_label = strdup(label, M_SYSCTLOID); 848 /* Update the context, if used */ 849 if (clist != NULL) 850 sysctl_ctx_entry_add(clist, oidp); 851 /* Register this oid */ 852 sysctl_register_oid(oidp); 853 SYSCTL_WUNLOCK(); 854 return (oidp); 855 } 856 857 /* 858 * Rename an existing oid. 859 */ 860 void 861 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name) 862 { 863 char *newname; 864 char *oldname; 865 866 newname = strdup(name, M_SYSCTLOID); 867 SYSCTL_WLOCK(); 868 oldname = __DECONST(char *, oidp->oid_name); 869 oidp->oid_name = newname; 870 SYSCTL_WUNLOCK(); 871 free(oldname, M_SYSCTLOID); 872 } 873 874 /* 875 * Reparent an existing oid. 876 */ 877 int 878 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent) 879 { 880 struct sysctl_oid *oidp; 881 882 SYSCTL_WLOCK(); 883 if (oid->oid_parent == parent) { 884 SYSCTL_WUNLOCK(); 885 return (0); 886 } 887 oidp = sysctl_find_oidname(oid->oid_name, parent); 888 if (oidp != NULL) { 889 SYSCTL_WUNLOCK(); 890 return (EEXIST); 891 } 892 sysctl_unregister_oid(oid); 893 oid->oid_parent = parent; 894 oid->oid_number = OID_AUTO; 895 sysctl_register_oid(oid); 896 SYSCTL_WUNLOCK(); 897 return (0); 898 } 899 900 /* 901 * Register the kernel's oids on startup. 902 */ 903 SET_DECLARE(sysctl_set, struct sysctl_oid); 904 905 static void 906 sysctl_register_all(void *arg) 907 { 908 struct sysctl_oid **oidp; 909 910 sx_init(&sysctlmemlock, "sysctl mem"); 911 SYSCTL_INIT(); 912 SYSCTL_WLOCK(); 913 SET_FOREACH(oidp, sysctl_set) 914 sysctl_register_oid(*oidp); 915 SYSCTL_WUNLOCK(); 916 } 917 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL); 918 919 /* 920 * "Staff-functions" 921 * 922 * These functions implement a presently undocumented interface 923 * used by the sysctl program to walk the tree, and get the type 924 * so it can print the value. 925 * This interface is under work and consideration, and should probably 926 * be killed with a big axe by the first person who can find the time. 927 * (be aware though, that the proper interface isn't as obvious as it 928 * may seem, there are various conflicting requirements. 929 * 930 * {0,0} printf the entire MIB-tree. 931 * {0,1,...} return the name of the "..." OID. 932 * {0,2,...} return the next OID. 933 * {0,3} return the OID of the name in "new" 934 * {0,4,...} return the kind & format info for the "..." OID. 935 * {0,5,...} return the description of the "..." OID. 936 * {0,6,...} return the aggregation label of the "..." OID. 937 */ 938 939 #ifdef SYSCTL_DEBUG 940 static void 941 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i) 942 { 943 int k; 944 struct sysctl_oid *oidp; 945 946 SYSCTL_ASSERT_LOCKED(); 947 SLIST_FOREACH(oidp, l, oid_link) { 948 949 for (k=0; k<i; k++) 950 printf(" "); 951 952 printf("%d %s ", oidp->oid_number, oidp->oid_name); 953 954 printf("%c%c", 955 oidp->oid_kind & CTLFLAG_RD ? 'R':' ', 956 oidp->oid_kind & CTLFLAG_WR ? 'W':' '); 957 958 if (oidp->oid_handler) 959 printf(" *Handler"); 960 961 switch (oidp->oid_kind & CTLTYPE) { 962 case CTLTYPE_NODE: 963 printf(" Node\n"); 964 if (!oidp->oid_handler) { 965 sysctl_sysctl_debug_dump_node( 966 SYSCTL_CHILDREN(oidp), i + 2); 967 } 968 break; 969 case CTLTYPE_INT: printf(" Int\n"); break; 970 case CTLTYPE_UINT: printf(" u_int\n"); break; 971 case CTLTYPE_LONG: printf(" Long\n"); break; 972 case CTLTYPE_ULONG: printf(" u_long\n"); break; 973 case CTLTYPE_STRING: printf(" String\n"); break; 974 case CTLTYPE_S8: printf(" int8_t\n"); break; 975 case CTLTYPE_S16: printf(" int16_t\n"); break; 976 case CTLTYPE_S32: printf(" int32_t\n"); break; 977 case CTLTYPE_S64: printf(" int64_t\n"); break; 978 case CTLTYPE_U8: printf(" uint8_t\n"); break; 979 case CTLTYPE_U16: printf(" uint16_t\n"); break; 980 case CTLTYPE_U32: printf(" uint32_t\n"); break; 981 case CTLTYPE_U64: printf(" uint64_t\n"); break; 982 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 983 default: printf("\n"); 984 } 985 986 } 987 } 988 989 static int 990 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS) 991 { 992 struct rm_priotracker tracker; 993 int error; 994 995 error = priv_check(req->td, PRIV_SYSCTL_DEBUG); 996 if (error) 997 return (error); 998 SYSCTL_RLOCK(&tracker); 999 sysctl_sysctl_debug_dump_node(&sysctl__children, 0); 1000 SYSCTL_RUNLOCK(&tracker); 1001 return (ENOENT); 1002 } 1003 1004 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, 1005 0, 0, sysctl_sysctl_debug, "-", ""); 1006 #endif 1007 1008 static int 1009 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) 1010 { 1011 int *name = (int *) arg1; 1012 u_int namelen = arg2; 1013 int error = 0; 1014 struct sysctl_oid *oid; 1015 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; 1016 struct rm_priotracker tracker; 1017 char buf[10]; 1018 1019 SYSCTL_RLOCK(&tracker); 1020 while (namelen) { 1021 if (!lsp) { 1022 snprintf(buf,sizeof(buf),"%d",*name); 1023 if (req->oldidx) 1024 error = SYSCTL_OUT(req, ".", 1); 1025 if (!error) 1026 error = SYSCTL_OUT(req, buf, strlen(buf)); 1027 if (error) 1028 goto out; 1029 namelen--; 1030 name++; 1031 continue; 1032 } 1033 lsp2 = NULL; 1034 SLIST_FOREACH(oid, lsp, oid_link) { 1035 if (oid->oid_number != *name) 1036 continue; 1037 1038 if (req->oldidx) 1039 error = SYSCTL_OUT(req, ".", 1); 1040 if (!error) 1041 error = SYSCTL_OUT(req, oid->oid_name, 1042 strlen(oid->oid_name)); 1043 if (error) 1044 goto out; 1045 1046 namelen--; 1047 name++; 1048 1049 if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 1050 break; 1051 1052 if (oid->oid_handler) 1053 break; 1054 1055 lsp2 = SYSCTL_CHILDREN(oid); 1056 break; 1057 } 1058 lsp = lsp2; 1059 } 1060 error = SYSCTL_OUT(req, "", 1); 1061 out: 1062 SYSCTL_RUNLOCK(&tracker); 1063 return (error); 1064 } 1065 1066 /* 1067 * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in 1068 * capability mode. 1069 */ 1070 static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, 1071 sysctl_sysctl_name, ""); 1072 1073 static int 1074 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, 1075 int *next, int *len, int level, struct sysctl_oid **oidpp) 1076 { 1077 struct sysctl_oid *oidp; 1078 1079 SYSCTL_ASSERT_LOCKED(); 1080 *len = level; 1081 SLIST_FOREACH(oidp, lsp, oid_link) { 1082 *next = oidp->oid_number; 1083 *oidpp = oidp; 1084 1085 if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0) 1086 continue; 1087 1088 if (!namelen) { 1089 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 1090 return (0); 1091 if (oidp->oid_handler) 1092 /* We really should call the handler here...*/ 1093 return (0); 1094 lsp = SYSCTL_CHILDREN(oidp); 1095 if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, 1096 len, level+1, oidpp)) 1097 return (0); 1098 goto emptynode; 1099 } 1100 1101 if (oidp->oid_number < *name) 1102 continue; 1103 1104 if (oidp->oid_number > *name) { 1105 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 1106 return (0); 1107 if (oidp->oid_handler) 1108 return (0); 1109 lsp = SYSCTL_CHILDREN(oidp); 1110 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, 1111 next+1, len, level+1, oidpp)) 1112 return (0); 1113 goto next; 1114 } 1115 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 1116 continue; 1117 1118 if (oidp->oid_handler) 1119 continue; 1120 1121 lsp = SYSCTL_CHILDREN(oidp); 1122 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, 1123 len, level+1, oidpp)) 1124 return (0); 1125 next: 1126 namelen = 1; 1127 emptynode: 1128 *len = level; 1129 } 1130 return (1); 1131 } 1132 1133 static int 1134 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) 1135 { 1136 int *name = (int *) arg1; 1137 u_int namelen = arg2; 1138 int i, j, error; 1139 struct sysctl_oid *oid; 1140 struct sysctl_oid_list *lsp = &sysctl__children; 1141 struct rm_priotracker tracker; 1142 int newoid[CTL_MAXNAME]; 1143 1144 SYSCTL_RLOCK(&tracker); 1145 i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid); 1146 SYSCTL_RUNLOCK(&tracker); 1147 if (i) 1148 return (ENOENT); 1149 error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 1150 return (error); 1151 } 1152 1153 /* 1154 * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in 1155 * capability mode. 1156 */ 1157 static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, 1158 sysctl_sysctl_next, ""); 1159 1160 static int 1161 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp) 1162 { 1163 struct sysctl_oid *oidp; 1164 struct sysctl_oid_list *lsp = &sysctl__children; 1165 char *p; 1166 1167 SYSCTL_ASSERT_LOCKED(); 1168 1169 for (*len = 0; *len < CTL_MAXNAME;) { 1170 p = strsep(&name, "."); 1171 1172 oidp = SLIST_FIRST(lsp); 1173 for (;; oidp = SLIST_NEXT(oidp, oid_link)) { 1174 if (oidp == NULL) 1175 return (ENOENT); 1176 if (strcmp(p, oidp->oid_name) == 0) 1177 break; 1178 } 1179 *oid++ = oidp->oid_number; 1180 (*len)++; 1181 1182 if (name == NULL || *name == '\0') { 1183 if (oidpp) 1184 *oidpp = oidp; 1185 return (0); 1186 } 1187 1188 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 1189 break; 1190 1191 if (oidp->oid_handler) 1192 break; 1193 1194 lsp = SYSCTL_CHILDREN(oidp); 1195 } 1196 return (ENOENT); 1197 } 1198 1199 static int 1200 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS) 1201 { 1202 char *p; 1203 int error, oid[CTL_MAXNAME], len = 0; 1204 struct sysctl_oid *op = NULL; 1205 struct rm_priotracker tracker; 1206 char buf[32]; 1207 1208 if (!req->newlen) 1209 return (ENOENT); 1210 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */ 1211 return (ENAMETOOLONG); 1212 1213 p = buf; 1214 if (req->newlen >= sizeof(buf)) 1215 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 1216 1217 error = SYSCTL_IN(req, p, req->newlen); 1218 if (error) { 1219 if (p != buf) 1220 free(p, M_SYSCTL); 1221 return (error); 1222 } 1223 1224 p [req->newlen] = '\0'; 1225 1226 SYSCTL_RLOCK(&tracker); 1227 error = name2oid(p, oid, &len, &op); 1228 SYSCTL_RUNLOCK(&tracker); 1229 1230 if (p != buf) 1231 free(p, M_SYSCTL); 1232 1233 if (error) 1234 return (error); 1235 1236 error = SYSCTL_OUT(req, oid, len * sizeof *oid); 1237 return (error); 1238 } 1239 1240 /* 1241 * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in 1242 * capability mode. 1243 */ 1244 SYSCTL_PROC(_sysctl, 3, name2oid, 1245 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE 1246 | CTLFLAG_CAPRW, 0, 0, sysctl_sysctl_name2oid, "I", ""); 1247 1248 static int 1249 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS) 1250 { 1251 struct sysctl_oid *oid; 1252 struct rm_priotracker tracker; 1253 int error; 1254 1255 SYSCTL_RLOCK(&tracker); 1256 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 1257 if (error) 1258 goto out; 1259 1260 if (oid->oid_fmt == NULL) { 1261 error = ENOENT; 1262 goto out; 1263 } 1264 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind)); 1265 if (error) 1266 goto out; 1267 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1); 1268 out: 1269 SYSCTL_RUNLOCK(&tracker); 1270 return (error); 1271 } 1272 1273 1274 static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD, 1275 sysctl_sysctl_oidfmt, ""); 1276 1277 static int 1278 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS) 1279 { 1280 struct sysctl_oid *oid; 1281 struct rm_priotracker tracker; 1282 int error; 1283 1284 SYSCTL_RLOCK(&tracker); 1285 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 1286 if (error) 1287 goto out; 1288 1289 if (oid->oid_descr == NULL) { 1290 error = ENOENT; 1291 goto out; 1292 } 1293 error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1); 1294 out: 1295 SYSCTL_RUNLOCK(&tracker); 1296 return (error); 1297 } 1298 1299 static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD, 1300 sysctl_sysctl_oiddescr, ""); 1301 1302 static int 1303 sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS) 1304 { 1305 struct sysctl_oid *oid; 1306 struct rm_priotracker tracker; 1307 int error; 1308 1309 SYSCTL_RLOCK(&tracker); 1310 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 1311 if (error) 1312 goto out; 1313 1314 if (oid->oid_label == NULL) { 1315 error = ENOENT; 1316 goto out; 1317 } 1318 error = SYSCTL_OUT(req, oid->oid_label, strlen(oid->oid_label) + 1); 1319 out: 1320 SYSCTL_RUNLOCK(&tracker); 1321 return (error); 1322 } 1323 1324 static SYSCTL_NODE(_sysctl, 6, oidlabel, 1325 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidlabel, ""); 1326 1327 /* 1328 * Default "handler" functions. 1329 */ 1330 1331 /* 1332 * Handle a bool. 1333 * Two cases: 1334 * a variable: point arg1 at it. 1335 * a constant: pass it in arg2. 1336 */ 1337 1338 int 1339 sysctl_handle_bool(SYSCTL_HANDLER_ARGS) 1340 { 1341 uint8_t temp; 1342 int error; 1343 1344 /* 1345 * Attempt to get a coherent snapshot by making a copy of the data. 1346 */ 1347 if (arg1) 1348 temp = *(bool *)arg1 ? 1 : 0; 1349 else 1350 temp = arg2 ? 1 : 0; 1351 1352 error = SYSCTL_OUT(req, &temp, sizeof(temp)); 1353 if (error || !req->newptr) 1354 return (error); 1355 1356 if (!arg1) 1357 error = EPERM; 1358 else { 1359 error = SYSCTL_IN(req, &temp, sizeof(temp)); 1360 if (!error) 1361 *(bool *)arg1 = temp ? 1 : 0; 1362 } 1363 return (error); 1364 } 1365 1366 /* 1367 * Handle an int8_t, signed or unsigned. 1368 * Two cases: 1369 * a variable: point arg1 at it. 1370 * a constant: pass it in arg2. 1371 */ 1372 1373 int 1374 sysctl_handle_8(SYSCTL_HANDLER_ARGS) 1375 { 1376 int8_t tmpout; 1377 int error = 0; 1378 1379 /* 1380 * Attempt to get a coherent snapshot by making a copy of the data. 1381 */ 1382 if (arg1) 1383 tmpout = *(int8_t *)arg1; 1384 else 1385 tmpout = arg2; 1386 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout)); 1387 1388 if (error || !req->newptr) 1389 return (error); 1390 1391 if (!arg1) 1392 error = EPERM; 1393 else 1394 error = SYSCTL_IN(req, arg1, sizeof(tmpout)); 1395 return (error); 1396 } 1397 1398 /* 1399 * Handle an int16_t, signed or unsigned. 1400 * Two cases: 1401 * a variable: point arg1 at it. 1402 * a constant: pass it in arg2. 1403 */ 1404 1405 int 1406 sysctl_handle_16(SYSCTL_HANDLER_ARGS) 1407 { 1408 int16_t tmpout; 1409 int error = 0; 1410 1411 /* 1412 * Attempt to get a coherent snapshot by making a copy of the data. 1413 */ 1414 if (arg1) 1415 tmpout = *(int16_t *)arg1; 1416 else 1417 tmpout = arg2; 1418 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout)); 1419 1420 if (error || !req->newptr) 1421 return (error); 1422 1423 if (!arg1) 1424 error = EPERM; 1425 else 1426 error = SYSCTL_IN(req, arg1, sizeof(tmpout)); 1427 return (error); 1428 } 1429 1430 /* 1431 * Handle an int32_t, signed or unsigned. 1432 * Two cases: 1433 * a variable: point arg1 at it. 1434 * a constant: pass it in arg2. 1435 */ 1436 1437 int 1438 sysctl_handle_32(SYSCTL_HANDLER_ARGS) 1439 { 1440 int32_t tmpout; 1441 int error = 0; 1442 1443 /* 1444 * Attempt to get a coherent snapshot by making a copy of the data. 1445 */ 1446 if (arg1) 1447 tmpout = *(int32_t *)arg1; 1448 else 1449 tmpout = arg2; 1450 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout)); 1451 1452 if (error || !req->newptr) 1453 return (error); 1454 1455 if (!arg1) 1456 error = EPERM; 1457 else 1458 error = SYSCTL_IN(req, arg1, sizeof(tmpout)); 1459 return (error); 1460 } 1461 1462 /* 1463 * Handle an int, signed or unsigned. 1464 * Two cases: 1465 * a variable: point arg1 at it. 1466 * a constant: pass it in arg2. 1467 */ 1468 1469 int 1470 sysctl_handle_int(SYSCTL_HANDLER_ARGS) 1471 { 1472 int tmpout, error = 0; 1473 1474 /* 1475 * Attempt to get a coherent snapshot by making a copy of the data. 1476 */ 1477 if (arg1) 1478 tmpout = *(int *)arg1; 1479 else 1480 tmpout = arg2; 1481 error = SYSCTL_OUT(req, &tmpout, sizeof(int)); 1482 1483 if (error || !req->newptr) 1484 return (error); 1485 1486 if (!arg1) 1487 error = EPERM; 1488 else 1489 error = SYSCTL_IN(req, arg1, sizeof(int)); 1490 return (error); 1491 } 1492 1493 /* 1494 * Based on on sysctl_handle_int() convert milliseconds into ticks. 1495 * Note: this is used by TCP. 1496 */ 1497 1498 int 1499 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS) 1500 { 1501 int error, s, tt; 1502 1503 tt = *(int *)arg1; 1504 s = (int)((int64_t)tt * 1000 / hz); 1505 1506 error = sysctl_handle_int(oidp, &s, 0, req); 1507 if (error || !req->newptr) 1508 return (error); 1509 1510 tt = (int)((int64_t)s * hz / 1000); 1511 if (tt < 1) 1512 return (EINVAL); 1513 1514 *(int *)arg1 = tt; 1515 return (0); 1516 } 1517 1518 1519 /* 1520 * Handle a long, signed or unsigned. 1521 * Two cases: 1522 * a variable: point arg1 at it. 1523 * a constant: pass it in arg2. 1524 */ 1525 1526 int 1527 sysctl_handle_long(SYSCTL_HANDLER_ARGS) 1528 { 1529 int error = 0; 1530 long tmplong; 1531 #ifdef SCTL_MASK32 1532 int tmpint; 1533 #endif 1534 1535 /* 1536 * Attempt to get a coherent snapshot by making a copy of the data. 1537 */ 1538 if (arg1) 1539 tmplong = *(long *)arg1; 1540 else 1541 tmplong = arg2; 1542 #ifdef SCTL_MASK32 1543 if (req->flags & SCTL_MASK32) { 1544 tmpint = tmplong; 1545 error = SYSCTL_OUT(req, &tmpint, sizeof(int)); 1546 } else 1547 #endif 1548 error = SYSCTL_OUT(req, &tmplong, sizeof(long)); 1549 1550 if (error || !req->newptr) 1551 return (error); 1552 1553 if (!arg1) 1554 error = EPERM; 1555 #ifdef SCTL_MASK32 1556 else if (req->flags & SCTL_MASK32) { 1557 error = SYSCTL_IN(req, &tmpint, sizeof(int)); 1558 *(long *)arg1 = (long)tmpint; 1559 } 1560 #endif 1561 else 1562 error = SYSCTL_IN(req, arg1, sizeof(long)); 1563 return (error); 1564 } 1565 1566 /* 1567 * Handle a 64 bit int, signed or unsigned. 1568 * Two cases: 1569 * a variable: point arg1 at it. 1570 * a constant: pass it in arg2. 1571 */ 1572 int 1573 sysctl_handle_64(SYSCTL_HANDLER_ARGS) 1574 { 1575 int error = 0; 1576 uint64_t tmpout; 1577 1578 /* 1579 * Attempt to get a coherent snapshot by making a copy of the data. 1580 */ 1581 if (arg1) 1582 tmpout = *(uint64_t *)arg1; 1583 else 1584 tmpout = arg2; 1585 error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t)); 1586 1587 if (error || !req->newptr) 1588 return (error); 1589 1590 if (!arg1) 1591 error = EPERM; 1592 else 1593 error = SYSCTL_IN(req, arg1, sizeof(uint64_t)); 1594 return (error); 1595 } 1596 1597 /* 1598 * Handle our generic '\0' terminated 'C' string. 1599 * Two cases: 1600 * a variable string: point arg1 at it, arg2 is max length. 1601 * a constant string: point arg1 at it, arg2 is zero. 1602 */ 1603 1604 int 1605 sysctl_handle_string(SYSCTL_HANDLER_ARGS) 1606 { 1607 size_t outlen; 1608 int error = 0, ro_string = 0; 1609 1610 /* 1611 * A zero-length buffer indicates a fixed size read-only 1612 * string: 1613 */ 1614 if (arg2 == 0) { 1615 arg2 = strlen((char *)arg1) + 1; 1616 ro_string = 1; 1617 } 1618 1619 if (req->oldptr != NULL) { 1620 char *tmparg; 1621 1622 if (ro_string) { 1623 tmparg = arg1; 1624 } else { 1625 /* try to make a coherent snapshot of the string */ 1626 tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK); 1627 memcpy(tmparg, arg1, arg2); 1628 } 1629 1630 outlen = strnlen(tmparg, arg2 - 1) + 1; 1631 error = SYSCTL_OUT(req, tmparg, outlen); 1632 1633 if (!ro_string) 1634 free(tmparg, M_SYSCTLTMP); 1635 } else { 1636 outlen = strnlen((char *)arg1, arg2 - 1) + 1; 1637 error = SYSCTL_OUT(req, NULL, outlen); 1638 } 1639 if (error || !req->newptr) 1640 return (error); 1641 1642 if ((req->newlen - req->newidx) >= arg2) { 1643 error = EINVAL; 1644 } else { 1645 arg2 = (req->newlen - req->newidx); 1646 error = SYSCTL_IN(req, arg1, arg2); 1647 ((char *)arg1)[arg2] = '\0'; 1648 } 1649 return (error); 1650 } 1651 1652 /* 1653 * Handle any kind of opaque data. 1654 * arg1 points to it, arg2 is the size. 1655 */ 1656 1657 int 1658 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS) 1659 { 1660 int error, tries; 1661 u_int generation; 1662 struct sysctl_req req2; 1663 1664 /* 1665 * Attempt to get a coherent snapshot, by using the thread 1666 * pre-emption counter updated from within mi_switch() to 1667 * determine if we were pre-empted during a bcopy() or 1668 * copyout(). Make 3 attempts at doing this before giving up. 1669 * If we encounter an error, stop immediately. 1670 */ 1671 tries = 0; 1672 req2 = *req; 1673 retry: 1674 generation = curthread->td_generation; 1675 error = SYSCTL_OUT(req, arg1, arg2); 1676 if (error) 1677 return (error); 1678 tries++; 1679 if (generation != curthread->td_generation && tries < 3) { 1680 *req = req2; 1681 goto retry; 1682 } 1683 1684 error = SYSCTL_IN(req, arg1, arg2); 1685 1686 return (error); 1687 } 1688 1689 /* 1690 * Based on on sysctl_handle_int() convert microseconds to a sbintime. 1691 */ 1692 int 1693 sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS) 1694 { 1695 int error; 1696 int64_t tt; 1697 sbintime_t sb; 1698 1699 tt = *(int64_t *)arg1; 1700 sb = sbttous(tt); 1701 1702 error = sysctl_handle_64(oidp, &sb, 0, req); 1703 if (error || !req->newptr) 1704 return (error); 1705 1706 tt = ustosbt(sb); 1707 *(int64_t *)arg1 = tt; 1708 1709 return (0); 1710 } 1711 1712 /* 1713 * Based on on sysctl_handle_int() convert milliseconds to a sbintime. 1714 */ 1715 int 1716 sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS) 1717 { 1718 int error; 1719 int64_t tt; 1720 sbintime_t sb; 1721 1722 tt = *(int64_t *)arg1; 1723 sb = sbttoms(tt); 1724 1725 error = sysctl_handle_64(oidp, &sb, 0, req); 1726 if (error || !req->newptr) 1727 return (error); 1728 1729 tt = mstosbt(sb); 1730 *(int64_t *)arg1 = tt; 1731 1732 return (0); 1733 } 1734 1735 /* 1736 * Convert seconds to a struct timeval. Intended for use with 1737 * intervals and thus does not permit negative seconds. 1738 */ 1739 int 1740 sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS) 1741 { 1742 struct timeval *tv; 1743 int error, secs; 1744 1745 tv = arg1; 1746 secs = tv->tv_sec; 1747 1748 error = sysctl_handle_int(oidp, &secs, 0, req); 1749 if (error || req->newptr == NULL) 1750 return (error); 1751 1752 if (secs < 0) 1753 return (EINVAL); 1754 tv->tv_sec = secs; 1755 1756 return (0); 1757 } 1758 1759 /* 1760 * Transfer functions to/from kernel space. 1761 * XXX: rather untested at this point 1762 */ 1763 static int 1764 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l) 1765 { 1766 size_t i = 0; 1767 1768 if (req->oldptr) { 1769 i = l; 1770 if (req->oldlen <= req->oldidx) 1771 i = 0; 1772 else 1773 if (i > req->oldlen - req->oldidx) 1774 i = req->oldlen - req->oldidx; 1775 if (i > 0) 1776 bcopy(p, (char *)req->oldptr + req->oldidx, i); 1777 } 1778 req->oldidx += l; 1779 if (req->oldptr && i != l) 1780 return (ENOMEM); 1781 return (0); 1782 } 1783 1784 static int 1785 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) 1786 { 1787 if (!req->newptr) 1788 return (0); 1789 if (req->newlen - req->newidx < l) 1790 return (EINVAL); 1791 bcopy((const char *)req->newptr + req->newidx, p, l); 1792 req->newidx += l; 1793 return (0); 1794 } 1795 1796 int 1797 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, 1798 size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags) 1799 { 1800 int error = 0; 1801 struct sysctl_req req; 1802 1803 bzero(&req, sizeof req); 1804 1805 req.td = td; 1806 req.flags = flags; 1807 1808 if (oldlenp) { 1809 req.oldlen = *oldlenp; 1810 } 1811 req.validlen = req.oldlen; 1812 1813 if (old) { 1814 req.oldptr= old; 1815 } 1816 1817 if (new != NULL) { 1818 req.newlen = newlen; 1819 req.newptr = new; 1820 } 1821 1822 req.oldfunc = sysctl_old_kernel; 1823 req.newfunc = sysctl_new_kernel; 1824 req.lock = REQ_UNWIRED; 1825 1826 error = sysctl_root(0, name, namelen, &req); 1827 1828 if (req.lock == REQ_WIRED && req.validlen > 0) 1829 vsunlock(req.oldptr, req.validlen); 1830 1831 if (error && error != ENOMEM) 1832 return (error); 1833 1834 if (retval) { 1835 if (req.oldptr && req.oldidx > req.validlen) 1836 *retval = req.validlen; 1837 else 1838 *retval = req.oldidx; 1839 } 1840 return (error); 1841 } 1842 1843 int 1844 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, 1845 void *new, size_t newlen, size_t *retval, int flags) 1846 { 1847 int oid[CTL_MAXNAME]; 1848 size_t oidlen, plen; 1849 int error; 1850 1851 oid[0] = 0; /* sysctl internal magic */ 1852 oid[1] = 3; /* name2oid */ 1853 oidlen = sizeof(oid); 1854 1855 error = kernel_sysctl(td, oid, 2, oid, &oidlen, 1856 (void *)name, strlen(name), &plen, flags); 1857 if (error) 1858 return (error); 1859 1860 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp, 1861 new, newlen, retval, flags); 1862 return (error); 1863 } 1864 1865 /* 1866 * Transfer function to/from user space. 1867 */ 1868 static int 1869 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l) 1870 { 1871 size_t i, len, origidx; 1872 int error; 1873 1874 origidx = req->oldidx; 1875 req->oldidx += l; 1876 if (req->oldptr == NULL) 1877 return (0); 1878 /* 1879 * If we have not wired the user supplied buffer and we are currently 1880 * holding locks, drop a witness warning, as it's possible that 1881 * write operations to the user page can sleep. 1882 */ 1883 if (req->lock != REQ_WIRED) 1884 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 1885 "sysctl_old_user()"); 1886 i = l; 1887 len = req->validlen; 1888 if (len <= origidx) 1889 i = 0; 1890 else { 1891 if (i > len - origidx) 1892 i = len - origidx; 1893 if (req->lock == REQ_WIRED) { 1894 error = copyout_nofault(p, (char *)req->oldptr + 1895 origidx, i); 1896 } else 1897 error = copyout(p, (char *)req->oldptr + origidx, i); 1898 if (error != 0) 1899 return (error); 1900 } 1901 if (i < l) 1902 return (ENOMEM); 1903 return (0); 1904 } 1905 1906 static int 1907 sysctl_new_user(struct sysctl_req *req, void *p, size_t l) 1908 { 1909 int error; 1910 1911 if (!req->newptr) 1912 return (0); 1913 if (req->newlen - req->newidx < l) 1914 return (EINVAL); 1915 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 1916 "sysctl_new_user()"); 1917 error = copyin((const char *)req->newptr + req->newidx, p, l); 1918 req->newidx += l; 1919 return (error); 1920 } 1921 1922 /* 1923 * Wire the user space destination buffer. If set to a value greater than 1924 * zero, the len parameter limits the maximum amount of wired memory. 1925 */ 1926 int 1927 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len) 1928 { 1929 int ret; 1930 size_t wiredlen; 1931 1932 wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen; 1933 ret = 0; 1934 if (req->lock != REQ_WIRED && req->oldptr && 1935 req->oldfunc == sysctl_old_user) { 1936 if (wiredlen != 0) { 1937 ret = vslock(req->oldptr, wiredlen); 1938 if (ret != 0) { 1939 if (ret != ENOMEM) 1940 return (ret); 1941 wiredlen = 0; 1942 } 1943 } 1944 req->lock = REQ_WIRED; 1945 req->validlen = wiredlen; 1946 } 1947 return (0); 1948 } 1949 1950 int 1951 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, 1952 int *nindx, struct sysctl_req *req) 1953 { 1954 struct sysctl_oid_list *lsp; 1955 struct sysctl_oid *oid; 1956 int indx; 1957 1958 SYSCTL_ASSERT_LOCKED(); 1959 lsp = &sysctl__children; 1960 indx = 0; 1961 while (indx < CTL_MAXNAME) { 1962 SLIST_FOREACH(oid, lsp, oid_link) { 1963 if (oid->oid_number == name[indx]) 1964 break; 1965 } 1966 if (oid == NULL) 1967 return (ENOENT); 1968 1969 indx++; 1970 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1971 if (oid->oid_handler != NULL || indx == namelen) { 1972 *noid = oid; 1973 if (nindx != NULL) 1974 *nindx = indx; 1975 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0, 1976 ("%s found DYING node %p", __func__, oid)); 1977 return (0); 1978 } 1979 lsp = SYSCTL_CHILDREN(oid); 1980 } else if (indx == namelen) { 1981 if ((oid->oid_kind & CTLFLAG_DORMANT) != 0) 1982 return (ENOENT); 1983 *noid = oid; 1984 if (nindx != NULL) 1985 *nindx = indx; 1986 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0, 1987 ("%s found DYING node %p", __func__, oid)); 1988 return (0); 1989 } else { 1990 return (ENOTDIR); 1991 } 1992 } 1993 return (ENOENT); 1994 } 1995 1996 /* 1997 * Traverse our tree, and find the right node, execute whatever it points 1998 * to, and return the resulting error code. 1999 */ 2000 2001 static int 2002 sysctl_root(SYSCTL_HANDLER_ARGS) 2003 { 2004 struct sysctl_oid *oid; 2005 struct rm_priotracker tracker; 2006 int error, indx, lvl; 2007 2008 SYSCTL_RLOCK(&tracker); 2009 2010 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req); 2011 if (error) 2012 goto out; 2013 2014 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 2015 /* 2016 * You can't call a sysctl when it's a node, but has 2017 * no handler. Inform the user that it's a node. 2018 * The indx may or may not be the same as namelen. 2019 */ 2020 if (oid->oid_handler == NULL) { 2021 error = EISDIR; 2022 goto out; 2023 } 2024 } 2025 2026 /* Is this sysctl writable? */ 2027 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) { 2028 error = EPERM; 2029 goto out; 2030 } 2031 2032 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); 2033 2034 #ifdef CAPABILITY_MODE 2035 /* 2036 * If the process is in capability mode, then don't permit reading or 2037 * writing unless specifically granted for the node. 2038 */ 2039 if (IN_CAPABILITY_MODE(req->td)) { 2040 if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) || 2041 (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) { 2042 error = EPERM; 2043 goto out; 2044 } 2045 } 2046 #endif 2047 2048 /* Is this sysctl sensitive to securelevels? */ 2049 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { 2050 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE; 2051 error = securelevel_gt(req->td->td_ucred, lvl); 2052 if (error) 2053 goto out; 2054 } 2055 2056 /* Is this sysctl writable by only privileged users? */ 2057 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) { 2058 int priv; 2059 2060 if (oid->oid_kind & CTLFLAG_PRISON) 2061 priv = PRIV_SYSCTL_WRITEJAIL; 2062 #ifdef VIMAGE 2063 else if ((oid->oid_kind & CTLFLAG_VNET) && 2064 prison_owns_vnet(req->td->td_ucred)) 2065 priv = PRIV_SYSCTL_WRITEJAIL; 2066 #endif 2067 else 2068 priv = PRIV_SYSCTL_WRITE; 2069 error = priv_check(req->td, priv); 2070 if (error) 2071 goto out; 2072 } 2073 2074 if (!oid->oid_handler) { 2075 error = EINVAL; 2076 goto out; 2077 } 2078 2079 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 2080 arg1 = (int *)arg1 + indx; 2081 arg2 -= indx; 2082 } else { 2083 arg1 = oid->oid_arg1; 2084 arg2 = oid->oid_arg2; 2085 } 2086 #ifdef MAC 2087 error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2, 2088 req); 2089 if (error != 0) 2090 goto out; 2091 #endif 2092 #ifdef VIMAGE 2093 if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL) 2094 arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1); 2095 #endif 2096 error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker); 2097 2098 out: 2099 SYSCTL_RUNLOCK(&tracker); 2100 return (error); 2101 } 2102 2103 #ifndef _SYS_SYSPROTO_H_ 2104 struct sysctl_args { 2105 int *name; 2106 u_int namelen; 2107 void *old; 2108 size_t *oldlenp; 2109 void *new; 2110 size_t newlen; 2111 }; 2112 #endif 2113 int 2114 sys___sysctl(struct thread *td, struct sysctl_args *uap) 2115 { 2116 int error, i, name[CTL_MAXNAME]; 2117 size_t j; 2118 2119 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 2120 return (EINVAL); 2121 2122 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 2123 if (error) 2124 return (error); 2125 2126 error = userland_sysctl(td, name, uap->namelen, 2127 uap->old, uap->oldlenp, 0, 2128 uap->new, uap->newlen, &j, 0); 2129 if (error && error != ENOMEM) 2130 return (error); 2131 if (uap->oldlenp) { 2132 i = copyout(&j, uap->oldlenp, sizeof(j)); 2133 if (i) 2134 return (i); 2135 } 2136 return (error); 2137 } 2138 2139 /* 2140 * This is used from various compatibility syscalls too. That's why name 2141 * must be in kernel space. 2142 */ 2143 int 2144 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, 2145 size_t *oldlenp, int inkernel, const void *new, size_t newlen, 2146 size_t *retval, int flags) 2147 { 2148 int error = 0, memlocked; 2149 struct sysctl_req req; 2150 2151 bzero(&req, sizeof req); 2152 2153 req.td = td; 2154 req.flags = flags; 2155 2156 if (oldlenp) { 2157 if (inkernel) { 2158 req.oldlen = *oldlenp; 2159 } else { 2160 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 2161 if (error) 2162 return (error); 2163 } 2164 } 2165 req.validlen = req.oldlen; 2166 req.oldptr = old; 2167 2168 if (new != NULL) { 2169 req.newlen = newlen; 2170 req.newptr = new; 2171 } 2172 2173 req.oldfunc = sysctl_old_user; 2174 req.newfunc = sysctl_new_user; 2175 req.lock = REQ_UNWIRED; 2176 2177 #ifdef KTRACE 2178 if (KTRPOINT(curthread, KTR_SYSCTL)) 2179 ktrsysctl(name, namelen); 2180 #endif 2181 memlocked = 0; 2182 if (req.oldptr && req.oldlen > 4 * PAGE_SIZE) { 2183 memlocked = 1; 2184 sx_xlock(&sysctlmemlock); 2185 } 2186 CURVNET_SET(TD_TO_VNET(td)); 2187 2188 for (;;) { 2189 req.oldidx = 0; 2190 req.newidx = 0; 2191 error = sysctl_root(0, name, namelen, &req); 2192 if (error != EAGAIN) 2193 break; 2194 kern_yield(PRI_USER); 2195 } 2196 2197 CURVNET_RESTORE(); 2198 2199 if (req.lock == REQ_WIRED && req.validlen > 0) 2200 vsunlock(req.oldptr, req.validlen); 2201 if (memlocked) 2202 sx_xunlock(&sysctlmemlock); 2203 2204 if (error && error != ENOMEM) 2205 return (error); 2206 2207 if (retval) { 2208 if (req.oldptr && req.oldidx > req.validlen) 2209 *retval = req.validlen; 2210 else 2211 *retval = req.oldidx; 2212 } 2213 return (error); 2214 } 2215 2216 /* 2217 * Drain into a sysctl struct. The user buffer should be wired if a page 2218 * fault would cause issue. 2219 */ 2220 static int 2221 sbuf_sysctl_drain(void *arg, const char *data, int len) 2222 { 2223 struct sysctl_req *req = arg; 2224 int error; 2225 2226 error = SYSCTL_OUT(req, data, len); 2227 KASSERT(error >= 0, ("Got unexpected negative value %d", error)); 2228 return (error == 0 ? len : -error); 2229 } 2230 2231 struct sbuf * 2232 sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length, 2233 struct sysctl_req *req) 2234 { 2235 2236 /* Supply a default buffer size if none given. */ 2237 if (buf == NULL && length == 0) 2238 length = 64; 2239 s = sbuf_new(s, buf, length, SBUF_FIXEDLEN | SBUF_INCLUDENUL); 2240 sbuf_set_drain(s, sbuf_sysctl_drain, req); 2241 return (s); 2242 } 2243