1 /* $NetBSD: kern_sysctl.c,v 1.264 2019/07/03 17:31:32 maxv Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2007, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Brown. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c) 1982, 1986, 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Mike Karels at Berkeley Software Design, Inc. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 64 */ 65 66 /* 67 * sysctl system call. 68 */ 69 70 #include <sys/cdefs.h> 71 __KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.264 2019/07/03 17:31:32 maxv Exp $"); 72 73 #ifdef _KERNEL_OPT 74 #include "opt_defcorename.h" 75 #endif 76 77 #include "ksyms.h" 78 79 #include <sys/param.h> 80 #define __COMPAT_SYSCTL 81 #include <sys/sysctl.h> 82 #include <sys/systm.h> 83 #include <sys/buf.h> 84 #include <sys/ksyms.h> 85 #include <sys/malloc.h> 86 #include <sys/mount.h> 87 #include <sys/syscallargs.h> 88 #include <sys/kauth.h> 89 #include <sys/ktrace.h> 90 #include <sys/rndsource.h> 91 92 #define MAXDESCLEN 1024 93 MALLOC_DEFINE(M_SYSCTLNODE, "sysctlnode", "sysctl node structures"); 94 MALLOC_DEFINE(M_SYSCTLDATA, "sysctldata", "misc sysctl data"); 95 96 static int sysctl_mmap(SYSCTLFN_PROTO); 97 static int sysctl_alloc(struct sysctlnode *, int); 98 static int sysctl_realloc(struct sysctlnode *); 99 100 static int sysctl_cvt_in(struct lwp *, int *, const void *, size_t, 101 struct sysctlnode *); 102 static int sysctl_cvt_out(struct lwp *, int, const struct sysctlnode *, 103 void *, size_t, size_t *); 104 105 static int sysctl_log_add(struct sysctllog **, const struct sysctlnode *); 106 static int sysctl_log_realloc(struct sysctllog *); 107 108 typedef void sysctl_setup_func(struct sysctllog **); 109 110 #ifdef SYSCTL_DEBUG 111 #define DPRINTF(a) printf a 112 #else 113 #define DPRINTF(a) 114 #endif 115 116 struct sysctllog { 117 const struct sysctlnode *log_root; 118 int *log_num; 119 int log_size, log_left; 120 }; 121 122 /* 123 * the "root" of the new sysctl tree 124 */ 125 struct sysctlnode sysctl_root = { 126 .sysctl_flags = SYSCTL_VERSION| 127 CTLFLAG_ROOT|CTLFLAG_READWRITE| 128 CTLTYPE_NODE, 129 .sysctl_num = 0, 130 .sysctl_size = sizeof(struct sysctlnode), 131 .sysctl_name = "(root)", 132 }; 133 134 /* 135 * link set of functions that add nodes at boot time (see also 136 * sysctl_buildtree()) 137 */ 138 __link_set_decl(sysctl_funcs, sysctl_setup_func); 139 140 /* 141 * The `sysctl_treelock' is intended to serialize access to the sysctl 142 * tree. XXX This has serious problems; allocating memory and 143 * copying data out with the lock held is insane. 144 */ 145 krwlock_t sysctl_treelock; 146 147 kmutex_t sysctl_file_marker_lock; 148 149 /* 150 * Attributes stored in the kernel. 151 */ 152 char hostname[MAXHOSTNAMELEN]; 153 int hostnamelen; 154 155 char domainname[MAXHOSTNAMELEN]; 156 int domainnamelen; 157 158 long hostid; 159 160 #ifndef DEFCORENAME 161 #define DEFCORENAME "%n.core" 162 #endif 163 char defcorename[MAXPATHLEN] = DEFCORENAME; 164 165 /* 166 * ******************************************************************** 167 * Section 0: Some simple glue 168 * ******************************************************************** 169 * By wrapping copyin(), copyout(), and copyinstr() like this, we can 170 * stop caring about who's calling us and simplify some code a bunch. 171 * ******************************************************************** 172 */ 173 int 174 sysctl_copyin(struct lwp *l, const void *uaddr, void *kaddr, size_t len) 175 { 176 int error; 177 178 if (l != NULL) { 179 error = copyin(uaddr, kaddr, len); 180 ktrmibio(-1, UIO_WRITE, uaddr, len, error); 181 } else { 182 error = kcopy(uaddr, kaddr, len); 183 } 184 185 return error; 186 } 187 188 int 189 sysctl_copyout(struct lwp *l, const void *kaddr, void *uaddr, size_t len) 190 { 191 int error; 192 193 if (l != NULL) { 194 error = copyout(kaddr, uaddr, len); 195 ktrmibio(-1, UIO_READ, uaddr, len, error); 196 } else { 197 error = kcopy(kaddr, uaddr, len); 198 } 199 200 return error; 201 } 202 203 int 204 sysctl_copyinstr(struct lwp *l, const void *uaddr, void *kaddr, 205 size_t len, size_t *done) 206 { 207 int error; 208 209 if (l != NULL) { 210 error = copyinstr(uaddr, kaddr, len, done); 211 ktrmibio(-1, UIO_WRITE, uaddr, len, error); 212 } else { 213 error = copystr(uaddr, kaddr, len, done); 214 } 215 216 return error; 217 } 218 219 /* 220 * ******************************************************************** 221 * Initialize sysctl subsystem. 222 * ******************************************************************** 223 */ 224 void 225 sysctl_init(void) 226 { 227 sysctl_setup_func *const *sysctl_setup; 228 229 rw_init(&sysctl_treelock); 230 231 /* 232 * dynamic mib numbers start here 233 */ 234 sysctl_root.sysctl_num = CREATE_BASE; 235 sysctl_basenode_init(); 236 237 __link_set_foreach(sysctl_setup, sysctl_funcs) { 238 (**sysctl_setup)(NULL); 239 } 240 241 mutex_init(&sysctl_file_marker_lock, MUTEX_DEFAULT, IPL_NONE); 242 } 243 244 /* 245 * Setting this means no more permanent nodes can be added, 246 * trees that claim to be readonly at the root now are, and if 247 * the main tree is readonly, *everything* is. 248 * 249 * Also starts up the PRNG used for the "random" sysctl: it's 250 * better to start it later than sooner. 251 * 252 * Call this at the end of kernel init. 253 */ 254 void 255 sysctl_finalize(void) 256 { 257 258 sysctl_root.sysctl_flags |= CTLFLAG_PERMANENT; 259 } 260 261 /* 262 * ******************************************************************** 263 * The main native sysctl system call itself. 264 * ******************************************************************** 265 */ 266 int 267 sys___sysctl(struct lwp *l, const struct sys___sysctl_args *uap, register_t *retval) 268 { 269 /* { 270 syscallarg(const int *) name; 271 syscallarg(u_int) namelen; 272 syscallarg(void *) old; 273 syscallarg(size_t *) oldlenp; 274 syscallarg(const void *) new; 275 syscallarg(size_t) newlen; 276 } */ 277 int error, nerror, name[CTL_MAXNAME]; 278 size_t oldlen, savelen, *oldlenp; 279 280 /* 281 * get oldlen 282 */ 283 oldlen = 0; 284 oldlenp = SCARG(uap, oldlenp); 285 if (oldlenp != NULL) { 286 error = copyin(oldlenp, &oldlen, sizeof(oldlen)); 287 if (error) 288 return (error); 289 } 290 savelen = oldlen; 291 292 /* 293 * top-level sysctl names may or may not be non-terminal, but 294 * we don't care 295 */ 296 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 1) 297 return (EINVAL); 298 error = copyin(SCARG(uap, name), &name, 299 SCARG(uap, namelen) * sizeof(int)); 300 if (error) 301 return (error); 302 303 ktrmib(name, SCARG(uap, namelen)); 304 305 sysctl_lock(SCARG(uap, newv) != NULL); 306 307 /* 308 * do sysctl work (NULL means main built-in default tree) 309 */ 310 error = sysctl_dispatch(&name[0], SCARG(uap, namelen), 311 SCARG(uap, oldv), &oldlen, 312 SCARG(uap, newv), SCARG(uap, newlen), 313 &name[0], l, NULL); 314 315 /* 316 * release the sysctl lock 317 */ 318 sysctl_unlock(); 319 320 /* 321 * set caller's oldlen to new value even in the face of an 322 * error (if this gets an error and they didn't have one, they 323 * get this one) 324 */ 325 if (oldlenp) { 326 nerror = copyout(&oldlen, oldlenp, sizeof(oldlen)); 327 if (error == 0) 328 error = nerror; 329 } 330 331 /* 332 * if the only problem is that we weren't given enough space, 333 * that's an ENOMEM error 334 */ 335 if (error == 0 && SCARG(uap, oldv) != NULL && savelen < oldlen) 336 error = ENOMEM; 337 338 return (error); 339 } 340 341 /* 342 * ******************************************************************** 343 * Section 1: How the tree is used 344 * ******************************************************************** 345 * Implementations of sysctl for emulations should typically need only 346 * these three functions in this order: lock the tree, dispatch 347 * request into it, unlock the tree. 348 * ******************************************************************** 349 */ 350 void 351 sysctl_lock(bool write) 352 { 353 354 if (write) { 355 rw_enter(&sysctl_treelock, RW_WRITER); 356 curlwp->l_pflag |= LP_SYSCTLWRITE; 357 } else { 358 rw_enter(&sysctl_treelock, RW_READER); 359 curlwp->l_pflag &= ~LP_SYSCTLWRITE; 360 } 361 } 362 363 void 364 sysctl_relock(void) 365 { 366 367 if ((curlwp->l_pflag & LP_SYSCTLWRITE) != 0) { 368 rw_enter(&sysctl_treelock, RW_WRITER); 369 } else { 370 rw_enter(&sysctl_treelock, RW_READER); 371 } 372 } 373 374 /* 375 * ******************************************************************** 376 * the main sysctl dispatch routine. scans the given tree and picks a 377 * function to call based on what it finds. 378 * ******************************************************************** 379 */ 380 int 381 sysctl_dispatch(SYSCTLFN_ARGS) 382 { 383 int error; 384 sysctlfn fn; 385 int ni; 386 387 KASSERT(rw_lock_held(&sysctl_treelock)); 388 389 if (rnode && SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 390 printf("sysctl_dispatch: rnode %p wrong version\n", rnode); 391 error = EINVAL; 392 goto out; 393 } 394 395 fn = NULL; 396 error = sysctl_locate(l, name, namelen, &rnode, &ni); 397 398 if (rnode->sysctl_func != NULL) { 399 /* 400 * the node we ended up at has a function, so call it. it can 401 * hand off to query or create if it wants to. 402 */ 403 fn = rnode->sysctl_func; 404 } else if (error == 0) { 405 /* 406 * we found the node they were looking for, so do a lookup. 407 */ 408 fn = (sysctlfn)sysctl_lookup; /* XXX may write to rnode */ 409 } else if (error == ENOENT && (ni + 1) == namelen && name[ni] < 0) { 410 /* 411 * prospective parent node found, but the terminal node was 412 * not. generic operations associate with the parent. 413 */ 414 switch (name[ni]) { 415 case CTL_QUERY: 416 fn = sysctl_query; 417 break; 418 case CTL_CREATE: 419 #if NKSYMS > 0 420 case CTL_CREATESYM: 421 #endif /* NKSYMS > 0 */ 422 if (newp == NULL) { 423 error = EINVAL; 424 break; 425 } 426 KASSERT(rw_write_held(&sysctl_treelock)); 427 fn = (sysctlfn)sysctl_create; /* we own the rnode */ 428 break; 429 case CTL_DESTROY: 430 if (newp == NULL) { 431 error = EINVAL; 432 break; 433 } 434 KASSERT(rw_write_held(&sysctl_treelock)); 435 fn = (sysctlfn)sysctl_destroy; /* we own the rnode */ 436 break; 437 case CTL_MMAP: 438 fn = (sysctlfn)sysctl_mmap; /* we own the rnode */ 439 break; 440 case CTL_DESCRIBE: 441 fn = sysctl_describe; 442 break; 443 default: 444 error = EOPNOTSUPP; 445 break; 446 } 447 } 448 449 /* 450 * after all of that, maybe we found someone who knows how to 451 * get us what we want? 452 */ 453 if (fn != NULL) 454 error = (*fn)(name + ni, namelen - ni, oldp, oldlenp, 455 newp, newlen, name, l, rnode); 456 else if (error == 0) 457 error = EOPNOTSUPP; 458 459 out: 460 return (error); 461 } 462 463 /* 464 * ******************************************************************** 465 * Releases the tree lock. 466 * ******************************************************************** 467 */ 468 void 469 sysctl_unlock(void) 470 { 471 472 rw_exit(&sysctl_treelock); 473 } 474 475 /* 476 * ******************************************************************** 477 * Section 2: The main tree interfaces 478 * ******************************************************************** 479 * This is how sysctl_dispatch() does its work, and you can too, by 480 * calling these routines from helpers (though typically only 481 * sysctl_lookup() will be used). The tree MUST BE LOCKED when these 482 * are called. 483 * ******************************************************************** 484 */ 485 486 /* 487 * sysctl_locate -- Finds the node matching the given mib under the 488 * given tree (via rv). If no tree is given, we fall back to the 489 * native tree. The current process (via l) is used for access 490 * control on the tree (some nodes may be traversable only by root) and 491 * on return, nip will show how many numbers in the mib were consumed. 492 */ 493 int 494 sysctl_locate(struct lwp *l, const int *name, u_int namelen, 495 const struct sysctlnode **rnode, int *nip) 496 { 497 const struct sysctlnode *node, *pnode; 498 int tn, si, ni, error, alias; 499 500 KASSERT(rw_lock_held(&sysctl_treelock)); 501 502 /* 503 * basic checks and setup 504 */ 505 if (*rnode == NULL) 506 *rnode = &sysctl_root; 507 if (nip) 508 *nip = 0; 509 if (namelen == 0) 510 return (0); 511 512 /* 513 * search starts from "root" 514 */ 515 pnode = *rnode; 516 if (SYSCTL_VERS(pnode->sysctl_flags) != SYSCTL_VERSION) { 517 printf("sysctl_locate: pnode %p wrong version\n", pnode); 518 return (EINVAL); 519 } 520 node = pnode->sysctl_child; 521 error = 0; 522 523 /* 524 * scan for node to which new node should be attached 525 */ 526 for (ni = 0; ni < namelen; ni++) { 527 /* 528 * walked off bottom of tree 529 */ 530 if (node == NULL) { 531 if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE) 532 error = ENOENT; 533 else 534 error = ENOTDIR; 535 break; 536 } 537 /* 538 * can anyone traverse this node or only root? 539 */ 540 if (l != NULL && (pnode->sysctl_flags & CTLFLAG_PRIVATE) && 541 (error = kauth_authorize_system(l->l_cred, 542 KAUTH_SYSTEM_SYSCTL, KAUTH_REQ_SYSTEM_SYSCTL_PRVT, 543 NULL, NULL, NULL)) != 0) 544 return (error); 545 /* 546 * find a child node with the right number 547 */ 548 tn = name[ni]; 549 alias = 0; 550 551 si = 0; 552 /* 553 * Note: ANYNUMBER only matches positive integers. 554 * Since ANYNUMBER is only permitted on single-node 555 * sub-trees (eg proc), check before the loop and skip 556 * it if we can. 557 */ 558 if ((node[si].sysctl_flags & CTLFLAG_ANYNUMBER) && (tn >= 0)) 559 goto foundit; 560 for (; si < pnode->sysctl_clen; si++) { 561 if (node[si].sysctl_num == tn) { 562 if (node[si].sysctl_flags & CTLFLAG_ALIAS) { 563 if (alias++ == 4) 564 break; 565 else { 566 tn = node[si].sysctl_alias; 567 si = -1; 568 } 569 } else 570 goto foundit; 571 } 572 } 573 /* 574 * if we ran off the end, it obviously doesn't exist 575 */ 576 error = ENOENT; 577 break; 578 579 /* 580 * so far so good, move on down the line 581 */ 582 foundit: 583 pnode = &node[si]; 584 if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE) 585 node = node[si].sysctl_child; 586 else 587 node = NULL; 588 } 589 590 *rnode = pnode; 591 if (nip) 592 *nip = ni; 593 594 return (error); 595 } 596 597 /* 598 * sysctl_query -- The auto-discovery engine. Copies out the structs 599 * describing nodes under the given node and handles overlay trees. 600 */ 601 int 602 sysctl_query(SYSCTLFN_ARGS) 603 { 604 int error, ni, elim, v; 605 size_t out, left, t; 606 const struct sysctlnode *enode, *onode; 607 struct sysctlnode qnode; 608 609 KASSERT(rw_lock_held(&sysctl_treelock)); 610 611 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 612 printf("sysctl_query: rnode %p wrong version\n", rnode); 613 return (EINVAL); 614 } 615 616 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 617 return (ENOTDIR); 618 if (namelen != 1 || name[0] != CTL_QUERY) 619 return (EINVAL); 620 621 error = 0; 622 out = 0; 623 left = *oldlenp; 624 elim = 0; 625 enode = NULL; 626 627 /* 628 * translate the given request to a current node 629 */ 630 error = sysctl_cvt_in(l, &v, newp, newlen, &qnode); 631 if (error) 632 return (error); 633 634 /* 635 * if the request specifies a version, check it 636 */ 637 if (qnode.sysctl_ver != 0) { 638 enode = rnode; 639 if (qnode.sysctl_ver != enode->sysctl_ver && 640 qnode.sysctl_ver != sysctl_rootof(enode)->sysctl_ver) 641 return (EINVAL); 642 } 643 644 /* 645 * process has overlay tree 646 */ 647 if (l && l->l_proc->p_emul->e_sysctlovly) { 648 enode = l->l_proc->p_emul->e_sysctlovly; 649 elim = (name - oname); 650 error = sysctl_locate(l, oname, elim, &enode, NULL); 651 if (error == 0) { 652 /* ah, found parent in overlay */ 653 elim = enode->sysctl_clen; 654 enode = enode->sysctl_child; 655 } else { 656 error = 0; 657 elim = 0; 658 enode = NULL; 659 } 660 } 661 662 for (ni = 0; ni < rnode->sysctl_clen; ni++) { 663 onode = &rnode->sysctl_child[ni]; 664 if (enode && enode->sysctl_num == onode->sysctl_num) { 665 if (SYSCTL_TYPE(enode->sysctl_flags) != CTLTYPE_NODE) 666 onode = enode; 667 if (--elim > 0) 668 enode++; 669 else 670 enode = NULL; 671 } 672 error = sysctl_cvt_out(l, v, onode, oldp, left, &t); 673 if (error) 674 return (error); 675 if (oldp != NULL) 676 oldp = (char*)oldp + t; 677 out += t; 678 left -= MIN(left, t); 679 } 680 681 /* 682 * overlay trees *MUST* be entirely consumed 683 */ 684 KASSERT(enode == NULL); 685 686 *oldlenp = out; 687 688 return (error); 689 } 690 691 /* 692 * sysctl_create -- Adds a node (the description of which is taken 693 * from newp) to the tree, returning a copy of it in the space pointed 694 * to by oldp. In the event that the requested slot is already taken 695 * (either by name or by number), the offending node is returned 696 * instead. Yes, this is complex, but we want to make sure everything 697 * is proper. 698 */ 699 #ifdef SYSCTL_DEBUG_CREATE 700 int _sysctl_create(SYSCTLFN_ARGS); 701 int 702 _sysctl_create(SYSCTLFN_ARGS) 703 #else 704 int 705 sysctl_create(SYSCTLFN_ARGS) 706 #endif 707 { 708 struct sysctlnode nnode, *node, *pnode; 709 int error, ni, at, nm, type, nsz, sz, flags, anum, v; 710 void *own; 711 712 KASSERT(rw_write_held(&sysctl_treelock)); 713 714 error = 0; 715 own = NULL; 716 anum = -1; 717 718 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 719 printf("sysctl_create: rnode %p wrong version\n", rnode); 720 return (EINVAL); 721 } 722 723 if (namelen != 1 || (name[namelen - 1] != CTL_CREATE 724 #if NKSYMS > 0 725 && name[namelen - 1] != CTL_CREATESYM 726 #endif /* NKSYMS > 0 */ 727 )) 728 return (EINVAL); 729 730 /* 731 * processes can only add nodes at securelevel 0, must be 732 * root, and can't add nodes to a parent that's not writeable 733 */ 734 if (l != NULL) { 735 #ifndef SYSCTL_DISALLOW_CREATE 736 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 737 KAUTH_REQ_SYSTEM_SYSCTL_ADD, NULL, NULL, NULL); 738 if (error) 739 return (error); 740 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 741 #endif /* SYSCTL_DISALLOW_CREATE */ 742 return (EPERM); 743 } 744 745 /* 746 * nothing can add a node if: 747 * we've finished initial set up of this tree and 748 * (the tree itself is not writeable or 749 * the entire sysctl system is not writeable) 750 */ 751 if ((sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_PERMANENT) && 752 (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 753 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) 754 return (EPERM); 755 756 /* 757 * it must be a "node", not a "int" or something 758 */ 759 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 760 return (ENOTDIR); 761 if (rnode->sysctl_flags & CTLFLAG_ALIAS) { 762 printf("sysctl_create: attempt to add node to aliased " 763 "node %p\n", rnode); 764 return (EINVAL); 765 } 766 pnode = __UNCONST(rnode); /* we are adding children to this node */ 767 768 if (newp == NULL) 769 return (EINVAL); 770 error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 771 if (error) 772 return (error); 773 774 /* 775 * nodes passed in don't *have* parents 776 */ 777 if (nnode.sysctl_parent != NULL) 778 return (EINVAL); 779 780 /* 781 * if we are indeed adding it, it should be a "good" name and 782 * number 783 */ 784 nm = nnode.sysctl_num; 785 #if NKSYMS > 0 786 if (nm == CTL_CREATESYM) 787 nm = CTL_CREATE; 788 #endif /* NKSYMS > 0 */ 789 if (nm < 0 && nm != CTL_CREATE) 790 return (EINVAL); 791 792 /* 793 * the name can't start with a digit 794 */ 795 if (nnode.sysctl_name[0] >= '0' && 796 nnode.sysctl_name[0] <= '9') 797 return (EINVAL); 798 799 /* 800 * the name must be only alphanumerics or - or _, longer than 801 * 0 bytes and less than SYSCTL_NAMELEN 802 */ 803 nsz = 0; 804 while (nsz < SYSCTL_NAMELEN && nnode.sysctl_name[nsz] != '\0') { 805 if ((nnode.sysctl_name[nsz] >= '0' && 806 nnode.sysctl_name[nsz] <= '9') || 807 (nnode.sysctl_name[nsz] >= 'A' && 808 nnode.sysctl_name[nsz] <= 'Z') || 809 (nnode.sysctl_name[nsz] >= 'a' && 810 nnode.sysctl_name[nsz] <= 'z') || 811 nnode.sysctl_name[nsz] == '-' || 812 nnode.sysctl_name[nsz] == '_') 813 nsz++; 814 else 815 return (EINVAL); 816 } 817 if (nsz == 0 || nsz == SYSCTL_NAMELEN) 818 return (EINVAL); 819 820 /* 821 * various checks revolve around size vs type, etc 822 */ 823 type = SYSCTL_TYPE(nnode.sysctl_flags); 824 flags = SYSCTL_FLAGS(nnode.sysctl_flags); 825 sz = nnode.sysctl_size; 826 827 /* 828 * find out if there's a collision, and if so, let the caller 829 * know what they collided with 830 */ 831 node = pnode->sysctl_child; 832 at = 0; 833 if (node) { 834 if ((flags | node->sysctl_flags) & CTLFLAG_ANYNUMBER) 835 /* No siblings for a CTLFLAG_ANYNUMBER node */ 836 return EINVAL; 837 for (ni = 0; ni < pnode->sysctl_clen; ni++) { 838 if (nm == node[ni].sysctl_num || 839 strcmp(nnode.sysctl_name, node[ni].sysctl_name) == 0) { 840 /* 841 * ignore error here, since we 842 * are already fixed on EEXIST 843 */ 844 (void)sysctl_cvt_out(l, v, &node[ni], oldp, 845 *oldlenp, oldlenp); 846 return (EEXIST); 847 } 848 if (nm > node[ni].sysctl_num) 849 at++; 850 } 851 } 852 853 /* 854 * use sysctl_ver to add to the tree iff it hasn't changed 855 */ 856 if (nnode.sysctl_ver != 0) { 857 /* 858 * a specified value must match either the parent 859 * node's version or the root node's version 860 */ 861 if (nnode.sysctl_ver != sysctl_rootof(rnode)->sysctl_ver && 862 nnode.sysctl_ver != rnode->sysctl_ver) { 863 return (EINVAL); 864 } 865 } 866 867 /* 868 * only the kernel can assign functions to entries 869 */ 870 if (l != NULL && nnode.sysctl_func != NULL) 871 return (EPERM); 872 873 /* 874 * only the kernel can create permanent entries, and only then 875 * before the kernel is finished setting itself up 876 */ 877 if (l != NULL && (flags & ~SYSCTL_USERFLAGS)) 878 return (EPERM); 879 if ((flags & CTLFLAG_PERMANENT) & 880 (sysctl_root.sysctl_flags & CTLFLAG_PERMANENT)) 881 return (EPERM); 882 if ((flags & (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) == 883 (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) 884 return (EINVAL); 885 if ((flags & CTLFLAG_IMMEDIATE) && 886 type != CTLTYPE_INT && type != CTLTYPE_QUAD && type != CTLTYPE_BOOL) 887 return (EINVAL); 888 889 /* 890 * check size, or set it if unset and we can figure it out. 891 * kernel created nodes are allowed to have a function instead 892 * of a size (or a data pointer). 893 */ 894 switch (type) { 895 case CTLTYPE_NODE: 896 /* 897 * only *i* can assert the size of a node 898 */ 899 if (flags & CTLFLAG_ALIAS) { 900 anum = nnode.sysctl_alias; 901 if (anum < 0) 902 return (EINVAL); 903 nnode.sysctl_alias = 0; 904 } 905 if (sz != 0 || nnode.sysctl_data != NULL) 906 return (EINVAL); 907 if (nnode.sysctl_csize != 0 || 908 nnode.sysctl_clen != 0 || 909 nnode.sysctl_child != 0) 910 return (EINVAL); 911 if (flags & CTLFLAG_OWNDATA) 912 return (EINVAL); 913 sz = sizeof(struct sysctlnode); 914 break; 915 case CTLTYPE_INT: 916 /* 917 * since an int is an int, if the size is not given or 918 * is wrong, we can "int-uit" it. 919 */ 920 if (sz != 0 && sz != sizeof(int)) 921 return (EINVAL); 922 sz = sizeof(int); 923 break; 924 case CTLTYPE_STRING: 925 /* 926 * strings are a little more tricky 927 */ 928 if (sz == 0) { 929 if (l == NULL) { 930 if (nnode.sysctl_func == NULL) { 931 if (nnode.sysctl_data == NULL) 932 return (EINVAL); 933 else 934 sz = strlen(nnode.sysctl_data) + 935 1; 936 } 937 } else if (nnode.sysctl_data == NULL && 938 flags & CTLFLAG_OWNDATA) { 939 return (EINVAL); 940 } else { 941 char *vp, *e; 942 size_t s; 943 944 /* 945 * we want a rough idea of what the 946 * size is now 947 */ 948 vp = malloc(PAGE_SIZE, M_SYSCTLDATA, M_WAITOK); 949 if (vp == NULL) 950 return (ENOMEM); 951 e = nnode.sysctl_data; 952 do { 953 error = copyinstr(e, vp, PAGE_SIZE, &s); 954 if (error) { 955 if (error != ENAMETOOLONG) { 956 free(vp, M_SYSCTLDATA); 957 return (error); 958 } 959 e += PAGE_SIZE; 960 if ((e - 32 * PAGE_SIZE) > 961 (char*)nnode.sysctl_data) { 962 free(vp, M_SYSCTLDATA); 963 return (ERANGE); 964 } 965 } 966 } while (error != 0); 967 sz = s + (e - (char*)nnode.sysctl_data); 968 free(vp, M_SYSCTLDATA); 969 } 970 } 971 break; 972 case CTLTYPE_QUAD: 973 if (sz != 0 && sz != sizeof(u_quad_t)) 974 return (EINVAL); 975 sz = sizeof(u_quad_t); 976 break; 977 case CTLTYPE_BOOL: 978 /* 979 * since an bool is an bool, if the size is not given or 980 * is wrong, we can "intuit" it. 981 */ 982 if (sz != 0 && sz != sizeof(bool)) 983 return (EINVAL); 984 sz = sizeof(bool); 985 break; 986 case CTLTYPE_STRUCT: 987 if (sz == 0) { 988 if (l != NULL || nnode.sysctl_func == NULL) 989 return (EINVAL); 990 if (flags & CTLFLAG_OWNDATA) 991 return (EINVAL); 992 } 993 break; 994 default: 995 return (EINVAL); 996 } 997 998 /* 999 * at this point, if sz is zero, we *must* have a 1000 * function to go with it and we can't own it. 1001 */ 1002 1003 /* 1004 * l ptr own 1005 * 0 0 0 -> EINVAL (if no func) 1006 * 0 0 1 -> own 1007 * 0 1 0 -> kptr 1008 * 0 1 1 -> kptr 1009 * 1 0 0 -> EINVAL 1010 * 1 0 1 -> own 1011 * 1 1 0 -> kptr, no own (fault on lookup) 1012 * 1 1 1 -> uptr, own 1013 */ 1014 if (type != CTLTYPE_NODE) { 1015 if (sz != 0) { 1016 if (flags & CTLFLAG_OWNDATA) { 1017 own = malloc(sz, M_SYSCTLDATA, M_WAITOK); 1018 if (own == NULL) 1019 return ENOMEM; 1020 if (nnode.sysctl_data == NULL) 1021 memset(own, 0, sz); 1022 else { 1023 error = sysctl_copyin(l, 1024 nnode.sysctl_data, own, sz); 1025 if (error != 0) { 1026 free(own, M_SYSCTLDATA); 1027 return (error); 1028 } 1029 } 1030 } else if ((nnode.sysctl_data != NULL) && 1031 !(flags & CTLFLAG_IMMEDIATE)) { 1032 #if NKSYMS > 0 1033 if (name[namelen - 1] == CTL_CREATESYM) { 1034 char symname[128]; /* XXX enough? */ 1035 u_long symaddr; 1036 size_t symlen; 1037 1038 error = sysctl_copyinstr(l, 1039 nnode.sysctl_data, symname, 1040 sizeof(symname), &symlen); 1041 if (error) 1042 return (error); 1043 error = ksyms_getval(NULL, symname, 1044 &symaddr, KSYMS_EXTERN); 1045 if (error) 1046 return (error); /* EINVAL? */ 1047 nnode.sysctl_data = (void*)symaddr; 1048 } 1049 #endif /* NKSYMS > 0 */ 1050 /* 1051 * Ideally, we'd like to verify here 1052 * that this address is acceptable, 1053 * but... 1054 * 1055 * - it might be valid now, only to 1056 * become invalid later 1057 * 1058 * - it might be invalid only for the 1059 * moment and valid later 1060 * 1061 * - or something else. 1062 * 1063 * Since we can't get a good answer, 1064 * we'll just accept the address as 1065 * given, and fault on individual 1066 * lookups. 1067 */ 1068 } 1069 } else if (nnode.sysctl_func == NULL) 1070 return (EINVAL); 1071 } 1072 1073 /* 1074 * a process can't assign a function to a node, and the kernel 1075 * can't create a node that has no function or data. 1076 * (XXX somewhat redundant check) 1077 */ 1078 if (l != NULL || nnode.sysctl_func == NULL) { 1079 if (type != CTLTYPE_NODE && 1080 !(flags & CTLFLAG_IMMEDIATE) && 1081 nnode.sysctl_data == NULL && 1082 own == NULL) 1083 return (EINVAL); 1084 } 1085 1086 #ifdef SYSCTL_DISALLOW_KWRITE 1087 /* 1088 * a process can't create a writable node unless it refers to 1089 * new data. 1090 */ 1091 if (l != NULL && own == NULL && type != CTLTYPE_NODE && 1092 (flags & CTLFLAG_READWRITE) != CTLFLAG_READONLY && 1093 !(flags & CTLFLAG_IMMEDIATE)) 1094 return (EPERM); 1095 #endif /* SYSCTL_DISALLOW_KWRITE */ 1096 1097 /* 1098 * make sure there's somewhere to put the new stuff. 1099 */ 1100 if (pnode->sysctl_child == NULL) { 1101 if (flags & CTLFLAG_ANYNUMBER) 1102 error = sysctl_alloc(pnode, 1); 1103 else 1104 error = sysctl_alloc(pnode, 0); 1105 if (error) { 1106 if (own != NULL) 1107 free(own, M_SYSCTLDATA); 1108 return (error); 1109 } 1110 } 1111 node = pnode->sysctl_child; 1112 1113 /* 1114 * no collisions, so pick a good dynamic number if we need to. 1115 */ 1116 if (nm == CTL_CREATE) { 1117 nm = ++sysctl_root.sysctl_num; 1118 for (ni = 0; ni < pnode->sysctl_clen; ni++) { 1119 if (nm == node[ni].sysctl_num) { 1120 nm++; 1121 ni = -1; 1122 } else if (nm > node[ni].sysctl_num) 1123 at = ni + 1; 1124 } 1125 } 1126 1127 /* 1128 * oops...ran out of space 1129 */ 1130 if (pnode->sysctl_clen == pnode->sysctl_csize) { 1131 error = sysctl_realloc(pnode); 1132 if (error) { 1133 if (own != NULL) 1134 free(own, M_SYSCTLDATA); 1135 return (error); 1136 } 1137 node = pnode->sysctl_child; 1138 } 1139 1140 /* 1141 * insert new node data 1142 */ 1143 if (at < pnode->sysctl_clen) { 1144 int t; 1145 1146 /* 1147 * move the nodes that should come after the new one 1148 */ 1149 memmove(&node[at + 1], &node[at], 1150 (pnode->sysctl_clen - at) * sizeof(struct sysctlnode)); 1151 memset(&node[at], 0, sizeof(struct sysctlnode)); 1152 node[at].sysctl_parent = pnode; 1153 /* 1154 * and...reparent any children of any moved nodes 1155 */ 1156 for (ni = at; ni <= pnode->sysctl_clen; ni++) 1157 if (node[ni].sysctl_child != NULL) 1158 for (t = 0; t < node[ni].sysctl_csize; t++) 1159 node[ni].sysctl_child[t].sysctl_parent = 1160 &node[ni]; 1161 } 1162 node = &node[at]; 1163 pnode->sysctl_clen++; 1164 1165 strlcpy(node->sysctl_name, nnode.sysctl_name, 1166 sizeof(node->sysctl_name)); 1167 node->sysctl_num = nm; 1168 node->sysctl_size = sz; 1169 node->sysctl_flags = SYSCTL_VERSION|type|flags; /* XXX other trees */ 1170 node->sysctl_csize = 0; 1171 node->sysctl_clen = 0; 1172 if (own) { 1173 node->sysctl_data = own; 1174 node->sysctl_flags |= CTLFLAG_OWNDATA; 1175 } else if (flags & CTLFLAG_ALIAS) { 1176 node->sysctl_alias = anum; 1177 } else if (flags & CTLFLAG_IMMEDIATE) { 1178 switch (type) { 1179 case CTLTYPE_BOOL: 1180 node->sysctl_bdata = nnode.sysctl_bdata; 1181 break; 1182 case CTLTYPE_INT: 1183 node->sysctl_idata = nnode.sysctl_idata; 1184 break; 1185 case CTLTYPE_QUAD: 1186 node->sysctl_qdata = nnode.sysctl_qdata; 1187 break; 1188 } 1189 } else { 1190 node->sysctl_data = nnode.sysctl_data; 1191 node->sysctl_flags &= ~CTLFLAG_OWNDATA; 1192 } 1193 node->sysctl_func = nnode.sysctl_func; 1194 node->sysctl_child = NULL; 1195 /* node->sysctl_parent should already be done */ 1196 1197 /* 1198 * update "version" on path to "root" 1199 */ 1200 for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1201 ; 1202 pnode = node; 1203 for (nm = rnode->sysctl_ver + 1; pnode != NULL; 1204 pnode = pnode->sysctl_parent) 1205 pnode->sysctl_ver = nm; 1206 1207 /* If this fails, the node is already added - the user won't know! */ 1208 error = sysctl_cvt_out(l, v, node, oldp, *oldlenp, oldlenp); 1209 1210 return (error); 1211 } 1212 1213 /* 1214 * ******************************************************************** 1215 * A wrapper around sysctl_create() that prints the thing we're trying 1216 * to add. 1217 * ******************************************************************** 1218 */ 1219 #ifdef SYSCTL_DEBUG_CREATE 1220 int 1221 sysctl_create(SYSCTLFN_ARGS) 1222 { 1223 const struct sysctlnode *node; 1224 int k, rc, ni, nl = namelen + (name - oname); 1225 1226 node = newp; 1227 1228 printf("namelen %d (", nl); 1229 for (ni = 0; ni < nl - 1; ni++) 1230 printf(" %d", oname[ni]); 1231 printf(" %d )\t[%s]\tflags %08x (%08x %d %zu)\n", 1232 k = node->sysctl_num, 1233 node->sysctl_name, 1234 node->sysctl_flags, 1235 SYSCTL_FLAGS(node->sysctl_flags), 1236 SYSCTL_TYPE(node->sysctl_flags), 1237 node->sysctl_size); 1238 1239 node = rnode; 1240 rc = _sysctl_create(SYSCTLFN_CALL(rnode)); 1241 1242 printf("sysctl_create("); 1243 for (ni = 0; ni < nl - 1; ni++) 1244 printf(" %d", oname[ni]); 1245 printf(" %d ) returned %d\n", k, rc); 1246 1247 return (rc); 1248 } 1249 #endif /* SYSCTL_DEBUG_CREATE */ 1250 1251 /* 1252 * sysctl_destroy -- Removes a node (as described by newp) from the 1253 * given tree, returning (if successful) a copy of the dead node in 1254 * oldp. Since we're removing stuff, there's not much to check. 1255 */ 1256 int 1257 sysctl_destroy(SYSCTLFN_ARGS) 1258 { 1259 struct sysctlnode *node, *pnode, onode, nnode; 1260 int ni, error, v; 1261 1262 KASSERT(rw_write_held(&sysctl_treelock)); 1263 1264 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1265 printf("sysctl_destroy: rnode %p wrong version\n", rnode); 1266 return (EINVAL); 1267 } 1268 1269 error = 0; 1270 1271 if (namelen != 1 || name[namelen - 1] != CTL_DESTROY) 1272 return (EINVAL); 1273 1274 /* 1275 * processes can only destroy nodes at securelevel 0, must be 1276 * root, and can't remove nodes from a parent that's not 1277 * writeable 1278 */ 1279 if (l != NULL) { 1280 #ifndef SYSCTL_DISALLOW_CREATE 1281 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1282 KAUTH_REQ_SYSTEM_SYSCTL_DELETE, NULL, NULL, NULL); 1283 if (error) 1284 return (error); 1285 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 1286 #endif /* SYSCTL_DISALLOW_CREATE */ 1287 return (EPERM); 1288 } 1289 1290 /* 1291 * nothing can remove a node if: 1292 * the node is permanent (checked later) or 1293 * the tree itself is not writeable or 1294 * the entire sysctl system is not writeable 1295 * 1296 * note that we ignore whether setup is complete or not, 1297 * because these rules always apply. 1298 */ 1299 if (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 1300 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE)) 1301 return (EPERM); 1302 1303 if (newp == NULL) 1304 return (EINVAL); 1305 error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 1306 if (error) 1307 return (error); 1308 memset(&onode, 0, sizeof(struct sysctlnode)); 1309 1310 node = rnode->sysctl_child; 1311 for (ni = 0; ni < rnode->sysctl_clen; ni++) { 1312 if (nnode.sysctl_num == node[ni].sysctl_num) { 1313 /* 1314 * if name specified, must match 1315 */ 1316 if (nnode.sysctl_name[0] != '\0' && 1317 strcmp(nnode.sysctl_name, node[ni].sysctl_name)) 1318 continue; 1319 /* 1320 * if version specified, must match 1321 */ 1322 if (nnode.sysctl_ver != 0 && 1323 nnode.sysctl_ver != node[ni].sysctl_ver) 1324 continue; 1325 /* 1326 * this must be the one 1327 */ 1328 break; 1329 } 1330 } 1331 if (ni == rnode->sysctl_clen) 1332 return (ENOENT); 1333 node = &node[ni]; 1334 pnode = node->sysctl_parent; 1335 1336 /* 1337 * if the kernel says permanent, it is, so there. nyah. 1338 */ 1339 if (SYSCTL_FLAGS(node->sysctl_flags) & CTLFLAG_PERMANENT) 1340 return (EPERM); 1341 1342 /* 1343 * can't delete non-empty nodes 1344 */ 1345 if (SYSCTL_TYPE(node->sysctl_flags) == CTLTYPE_NODE && 1346 node->sysctl_clen != 0) 1347 return (ENOTEMPTY); 1348 1349 /* 1350 * if the node "owns" data, release it now 1351 */ 1352 if (node->sysctl_flags & CTLFLAG_OWNDATA) { 1353 if (node->sysctl_data != NULL) 1354 free(node->sysctl_data, M_SYSCTLDATA); 1355 node->sysctl_data = NULL; 1356 } 1357 if (node->sysctl_flags & CTLFLAG_OWNDESC) { 1358 if (node->sysctl_desc != NULL) 1359 /*XXXUNCONST*/ 1360 free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA); 1361 node->sysctl_desc = NULL; 1362 } 1363 1364 /* 1365 * if the node to be removed is not the last one on the list, 1366 * move the remaining nodes up, and reparent any grandchildren 1367 */ 1368 onode = *node; 1369 if (ni < pnode->sysctl_clen - 1) { 1370 int t; 1371 1372 memmove(&pnode->sysctl_child[ni], &pnode->sysctl_child[ni + 1], 1373 (pnode->sysctl_clen - ni - 1) * 1374 sizeof(struct sysctlnode)); 1375 for (; ni < pnode->sysctl_clen - 1; ni++) 1376 if (SYSCTL_TYPE(pnode->sysctl_child[ni].sysctl_flags) == 1377 CTLTYPE_NODE) 1378 for (t = 0; 1379 t < pnode->sysctl_child[ni].sysctl_clen; 1380 t++) 1381 pnode->sysctl_child[ni].sysctl_child[t]. 1382 sysctl_parent = 1383 &pnode->sysctl_child[ni]; 1384 ni = pnode->sysctl_clen - 1; 1385 node = &pnode->sysctl_child[ni]; 1386 } 1387 1388 /* 1389 * reset the space we just vacated 1390 */ 1391 memset(node, 0, sizeof(struct sysctlnode)); 1392 node->sysctl_parent = pnode; 1393 pnode->sysctl_clen--; 1394 1395 /* 1396 * if this parent just lost its last child, nuke the creche 1397 */ 1398 if (pnode->sysctl_clen == 0) { 1399 free(pnode->sysctl_child, M_SYSCTLNODE); 1400 pnode->sysctl_csize = 0; 1401 pnode->sysctl_child = NULL; 1402 } 1403 1404 /* 1405 * update "version" on path to "root" 1406 */ 1407 for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1408 ; 1409 for (ni = rnode->sysctl_ver + 1; pnode != NULL; 1410 pnode = pnode->sysctl_parent) 1411 pnode->sysctl_ver = ni; 1412 1413 error = sysctl_cvt_out(l, v, &onode, oldp, *oldlenp, oldlenp); 1414 1415 return (error); 1416 } 1417 1418 /* 1419 * sysctl_lookup -- Handles copyin/copyout of new and old values. 1420 * Partial reads are globally allowed. Only root can write to things 1421 * unless the node says otherwise. 1422 */ 1423 int 1424 sysctl_lookup(SYSCTLFN_ARGS) 1425 { 1426 int error, rw; 1427 size_t sz, len; 1428 void *d; 1429 1430 KASSERT(rw_lock_held(&sysctl_treelock)); 1431 1432 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1433 printf("%s: rnode %p wrong version\n", __func__, rnode); 1434 return EINVAL; 1435 } 1436 1437 if (newlen == 0) 1438 newp = NULL; 1439 1440 error = 0; 1441 1442 /* 1443 * you can't "look up" a node. you can "query" it, but you 1444 * can't "look it up". 1445 */ 1446 if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_NODE || namelen != 0) { 1447 DPRINTF(("%s: can't lookup a node\n", __func__)); 1448 return EINVAL; 1449 } 1450 1451 /* 1452 * some nodes are private, so only root can look into them. 1453 */ 1454 if (l != NULL && (rnode->sysctl_flags & CTLFLAG_PRIVATE) && 1455 (error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1456 KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL)) != 0) { 1457 DPRINTF(("%s: private node\n", __func__)); 1458 return error; 1459 } 1460 1461 /* 1462 * if a node wants to be writable according to different rules 1463 * other than "only root can write to stuff unless a flag is 1464 * set", then it needs its own function which should have been 1465 * called and not us. 1466 */ 1467 if (l != NULL && newp != NULL && 1468 !(rnode->sysctl_flags & CTLFLAG_ANYWRITE) && 1469 (error = kauth_authorize_system(l->l_cred, 1470 KAUTH_SYSTEM_SYSCTL, KAUTH_REQ_SYSTEM_SYSCTL_MODIFY, NULL, NULL, 1471 NULL)) != 0) { 1472 DPRINTF(("%s: can't modify\n", __func__)); 1473 return error; 1474 } 1475 1476 /* 1477 * is this node supposedly writable? 1478 */ 1479 rw = (rnode->sysctl_flags & CTLFLAG_READWRITE) ? 1 : 0; 1480 1481 /* 1482 * it appears not to be writable at this time, so if someone 1483 * tried to write to it, we must tell them to go away 1484 */ 1485 if (!rw && newp != NULL) { 1486 DPRINTF(("%s: not writable\n", __func__)); 1487 return EPERM; 1488 } 1489 1490 /* 1491 * step one, copy out the stuff we have presently 1492 */ 1493 if (rnode->sysctl_flags & CTLFLAG_IMMEDIATE) { 1494 /* 1495 * note that we discard const here because we are 1496 * modifying the contents of the node (which is okay 1497 * because it's ours) 1498 * 1499 * It also doesn't matter which field of the union we pick. 1500 */ 1501 d = __UNCONST(&rnode->sysctl_qdata); 1502 } else 1503 d = rnode->sysctl_data; 1504 1505 if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_STRING) 1506 sz = strlen(d) + 1; /* XXX@@@ possible fault here */ 1507 else 1508 sz = rnode->sysctl_size; 1509 if (oldp != NULL) { 1510 error = sysctl_copyout(l, d, oldp, MIN(sz, *oldlenp)); 1511 if (error) { 1512 DPRINTF(("%s: bad copyout %d\n", __func__, error)); 1513 return error; 1514 } 1515 } 1516 *oldlenp = sz; 1517 1518 /* 1519 * are we done? 1520 */ 1521 if (newp == NULL) 1522 return 0; 1523 1524 /* 1525 * hmm...not done. must now "copy in" new value. re-adjust 1526 * sz to maximum value (strings are "weird"). 1527 */ 1528 sz = rnode->sysctl_size; 1529 switch (SYSCTL_TYPE(rnode->sysctl_flags)) { 1530 case CTLTYPE_BOOL: { 1531 bool tmp; 1532 /* 1533 * these data must be *exactly* the same size coming 1534 * in. bool may only be true or false. 1535 */ 1536 if (newlen != sz) { 1537 DPRINTF(("%s: bad size %zu != %zu\n", __func__, newlen, 1538 sz)); 1539 return EINVAL; 1540 } 1541 error = sysctl_copyin(l, newp, &tmp, sz); 1542 if (error) 1543 break; 1544 if (tmp != true && tmp != false) { 1545 DPRINTF(("%s: tmp %d\n", __func__, tmp)); 1546 return EINVAL; 1547 } 1548 *(bool *)d = tmp; 1549 break; 1550 } 1551 case CTLTYPE_INT: 1552 case CTLTYPE_QUAD: 1553 case CTLTYPE_STRUCT: 1554 /* 1555 * these data must be *exactly* the same size coming 1556 * in. 1557 */ 1558 if (newlen != sz) 1559 goto bad_size; 1560 error = sysctl_copyin(l, newp, d, sz); 1561 rnd_add_data(NULL, d, sz, 0); 1562 break; 1563 case CTLTYPE_STRING: { 1564 /* 1565 * strings, on the other hand, can be shorter, and we 1566 * let userland be sloppy about the trailing nul. 1567 */ 1568 char *newbuf; 1569 1570 /* 1571 * too much new string? 1572 */ 1573 if (newlen > sz) 1574 goto bad_size; 1575 1576 /* 1577 * temporary copy of new inbound string 1578 */ 1579 len = MIN(sz, newlen); 1580 newbuf = malloc(len, M_SYSCTLDATA, M_WAITOK); 1581 if (newbuf == NULL) { 1582 DPRINTF(("%s: oomem %zu\n", __func__, len)); 1583 return ENOMEM; 1584 } 1585 error = sysctl_copyin(l, newp, newbuf, len); 1586 if (error) { 1587 free(newbuf, M_SYSCTLDATA); 1588 DPRINTF(("%s: copyin %d\n", __func__, error)); 1589 return error; 1590 } 1591 1592 /* 1593 * did they NUL terminate it, or do we have space 1594 * left to do it ourselves? 1595 */ 1596 if (newbuf[len - 1] != '\0' && len == sz) { 1597 free(newbuf, M_SYSCTLDATA); 1598 DPRINTF(("%s: string too long\n", __func__)); 1599 return EINVAL; 1600 } 1601 1602 /* 1603 * looks good, so pop it into place and zero the rest. 1604 */ 1605 if (len > 0) { 1606 memcpy(d, newbuf, len); 1607 rnd_add_data(NULL, d, len, 0); 1608 } 1609 if (sz != len) 1610 memset((char*)d + len, 0, sz - len); 1611 free(newbuf, M_SYSCTLDATA); 1612 break; 1613 } 1614 default: 1615 DPRINTF(("%s: bad type\n", __func__)); 1616 return EINVAL; 1617 } 1618 if (error) { 1619 DPRINTF(("%s: copyin %d\n", __func__, error)); 1620 } 1621 1622 return error; 1623 1624 bad_size: 1625 DPRINTF(("%s: bad size %zu > %zu\n", __func__, newlen, sz)); 1626 return EINVAL; 1627 } 1628 1629 /* 1630 * sysctl_mmap -- Dispatches sysctl mmap requests to those nodes that 1631 * purport to handle it. This interface isn't fully fleshed out yet, 1632 * unfortunately. 1633 */ 1634 static int 1635 sysctl_mmap(SYSCTLFN_ARGS) 1636 { 1637 const struct sysctlnode *node; 1638 struct sysctlnode nnode; 1639 int error; 1640 int sysctl_num; 1641 1642 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1643 printf("sysctl_mmap: rnode %p wrong version\n", rnode); 1644 return (EINVAL); 1645 } 1646 1647 /* 1648 * let's just pretend that didn't happen, m'kay? 1649 */ 1650 if (l == NULL) 1651 return (EPERM); 1652 1653 /* 1654 * is this a sysctlnode description of an mmap request? 1655 */ 1656 if (newp == NULL || newlen != sizeof(struct sysctlnode)) 1657 return (EINVAL); 1658 error = sysctl_copyin(l, newp, &nnode, sizeof(nnode)); 1659 if (error) 1660 return (error); 1661 1662 /* 1663 * does the node they asked for exist? 1664 */ 1665 if (namelen != 1) 1666 return (EOPNOTSUPP); 1667 node = rnode; 1668 sysctl_num = nnode.sysctl_num; 1669 error = sysctl_locate(l, &sysctl_num, 1, &node, NULL); 1670 if (error) 1671 return (error); 1672 1673 /* 1674 * does this node that we have found purport to handle mmap? 1675 */ 1676 if (node->sysctl_func == NULL || 1677 !(node->sysctl_flags & CTLFLAG_MMAP)) 1678 return (EOPNOTSUPP); 1679 1680 /* 1681 * well...okay, they asked for it. 1682 */ 1683 return ((*node->sysctl_func)(SYSCTLFN_CALL(node))); 1684 } 1685 1686 int 1687 sysctl_describe(SYSCTLFN_ARGS) 1688 { 1689 struct sysctldesc *d; 1690 void *bf; 1691 size_t sz, left, tot; 1692 int i, error, v = -1; 1693 struct sysctlnode *node; 1694 struct sysctlnode dnode; 1695 1696 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1697 printf("sysctl_query: rnode %p wrong version\n", rnode); 1698 return (EINVAL); 1699 } 1700 1701 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 1702 return (ENOTDIR); 1703 if (namelen != 1 || name[0] != CTL_DESCRIBE) 1704 return (EINVAL); 1705 1706 /* 1707 * get ready... 1708 */ 1709 error = 0; 1710 d = bf = malloc(MAXDESCLEN, M_TEMP, M_WAITOK); 1711 if (bf == NULL) 1712 return ENOMEM; 1713 tot = 0; 1714 node = rnode->sysctl_child; 1715 left = *oldlenp; 1716 1717 /* 1718 * no request -> all descriptions at this level 1719 * request with desc unset -> just this node 1720 * request with desc set -> set descr for this node 1721 */ 1722 if (newp != NULL) { 1723 error = sysctl_cvt_in(l, &v, newp, newlen, &dnode); 1724 if (error) 1725 goto out; 1726 if (dnode.sysctl_desc != NULL) { 1727 /* 1728 * processes cannot set descriptions above 1729 * securelevel 0. and must be root. blah 1730 * blah blah. a couple more checks are made 1731 * once we find the node we want. 1732 */ 1733 if (l != NULL) { 1734 #ifndef SYSCTL_DISALLOW_CREATE 1735 error = kauth_authorize_system(l->l_cred, 1736 KAUTH_SYSTEM_SYSCTL, 1737 KAUTH_REQ_SYSTEM_SYSCTL_DESC, NULL, 1738 NULL, NULL); 1739 if (error) 1740 goto out; 1741 #else /* SYSCTL_DISALLOW_CREATE */ 1742 error = EPERM; 1743 goto out; 1744 #endif /* SYSCTL_DISALLOW_CREATE */ 1745 } 1746 1747 /* 1748 * find node and try to set the description on it 1749 */ 1750 for (i = 0; i < rnode->sysctl_clen; i++) 1751 if (node[i].sysctl_num == dnode.sysctl_num) 1752 break; 1753 if (i == rnode->sysctl_clen) { 1754 error = ENOENT; 1755 goto out; 1756 } 1757 node = &node[i]; 1758 1759 /* 1760 * did the caller specify a node version? 1761 */ 1762 if (dnode.sysctl_ver != 0 && 1763 dnode.sysctl_ver != node->sysctl_ver) { 1764 error = EINVAL; 1765 goto out; 1766 } 1767 1768 /* 1769 * okay...some rules: 1770 * (1) if setup is done and the tree is 1771 * read-only or the whole system is 1772 * read-only 1773 * (2) no one can set a description on a 1774 * permanent node (it must be set when 1775 * using createv) 1776 * (3) processes cannot *change* a description 1777 * (4) processes *can*, however, set a 1778 * description on a read-only node so that 1779 * one can be created and then described 1780 * in two steps 1781 * anything else come to mind? 1782 */ 1783 if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) && 1784 (!(sysctl_rootof(node)->sysctl_flags & 1785 CTLFLAG_READWRITE) || 1786 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) { 1787 error = EPERM; 1788 goto out; 1789 } 1790 if (node->sysctl_flags & CTLFLAG_PERMANENT) { 1791 error = EPERM; 1792 goto out; 1793 } 1794 if (l != NULL && node->sysctl_desc != NULL) { 1795 error = EPERM; 1796 goto out; 1797 } 1798 1799 /* 1800 * right, let's go ahead. the first step is 1801 * making the description into something the 1802 * node can "own", if need be. 1803 */ 1804 if (l != NULL || 1805 dnode.sysctl_flags & CTLFLAG_OWNDESC) { 1806 char *nd, *k; 1807 1808 k = malloc(MAXDESCLEN, M_TEMP, M_WAITOK); 1809 if (k == NULL) { 1810 error = ENOMEM; 1811 goto out; 1812 } 1813 error = sysctl_copyinstr(l, dnode.sysctl_desc, 1814 k, MAXDESCLEN, &sz); 1815 if (error) { 1816 free(k, M_TEMP); 1817 goto out; 1818 } 1819 nd = malloc(sz, M_SYSCTLDATA, M_WAITOK); 1820 if (nd == NULL) { 1821 free(k, M_TEMP); 1822 error = ENOMEM; 1823 goto out; 1824 } 1825 memcpy(nd, k, sz); 1826 dnode.sysctl_flags |= CTLFLAG_OWNDESC; 1827 dnode.sysctl_desc = nd; 1828 free(k, M_TEMP); 1829 } 1830 1831 /* 1832 * now "release" the old description and 1833 * attach the new one. ta-da. 1834 */ 1835 if ((node->sysctl_flags & CTLFLAG_OWNDESC) && 1836 node->sysctl_desc != NULL) 1837 /*XXXUNCONST*/ 1838 free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA); 1839 node->sysctl_desc = dnode.sysctl_desc; 1840 node->sysctl_flags |= 1841 (dnode.sysctl_flags & CTLFLAG_OWNDESC); 1842 1843 /* 1844 * now we "fall out" and into the loop which 1845 * will copy the new description back out for 1846 * those interested parties 1847 */ 1848 } 1849 } 1850 1851 /* 1852 * scan for one description or just retrieve all descriptions 1853 */ 1854 for (i = 0; i < rnode->sysctl_clen; i++) { 1855 /* 1856 * did they ask for the description of only one node? 1857 */ 1858 if (v != -1 && node[i].sysctl_num != dnode.sysctl_num) 1859 continue; 1860 1861 /* 1862 * don't describe "private" nodes to non-suser users 1863 */ 1864 if ((node[i].sysctl_flags & CTLFLAG_PRIVATE) && (l != NULL) && 1865 !(kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1866 KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL))) 1867 continue; 1868 1869 /* 1870 * is this description "valid"? 1871 */ 1872 memset(bf, 0, MAXDESCLEN); 1873 if (node[i].sysctl_desc == NULL) 1874 sz = 1; 1875 else if (copystr(node[i].sysctl_desc, &d->descr_str[0], 1876 MAXDESCLEN - sizeof(*d), &sz) != 0) { 1877 /* 1878 * erase possible partial description 1879 */ 1880 memset(bf, 0, MAXDESCLEN); 1881 sz = 1; 1882 } 1883 1884 /* 1885 * we've got it, stuff it into the caller's buffer 1886 */ 1887 d->descr_num = node[i].sysctl_num; 1888 d->descr_ver = node[i].sysctl_ver; 1889 d->descr_len = sz; /* includes trailing nul */ 1890 sz = (char *)NEXT_DESCR(d) - (char *)d; 1891 if (oldp != NULL && left >= sz) { 1892 error = sysctl_copyout(l, d, oldp, sz); 1893 if (error) 1894 goto out; 1895 left -= sz; 1896 oldp = (void *)__sysc_desc_adv(oldp, d->descr_len); 1897 } 1898 tot += sz; 1899 1900 /* 1901 * if we get this far with v not "unset", they asked 1902 * for a specific node and we found it 1903 */ 1904 if (v != -1) 1905 break; 1906 } 1907 1908 /* 1909 * did we find it after all? 1910 */ 1911 if (v != -1 && tot == 0) 1912 error = ENOENT; 1913 else 1914 *oldlenp = tot; 1915 1916 out: 1917 free(bf, M_TEMP); 1918 return (error); 1919 } 1920 1921 /* 1922 * ******************************************************************** 1923 * Section 3: Create and destroy from inside the kernel 1924 * ******************************************************************** 1925 * sysctl_createv() and sysctl_destroyv() are simpler-to-use 1926 * interfaces for the kernel to fling new entries into the mib and rip 1927 * them out later. In the case of sysctl_createv(), the returned copy 1928 * of the node (see sysctl_create()) will be translated back into a 1929 * pointer to the actual node. 1930 * 1931 * Note that sysctl_createv() will return 0 if the create request 1932 * matches an existing node (ala mkdir -p), and that sysctl_destroyv() 1933 * will return 0 if the node to be destroyed already does not exist 1934 * (aka rm -f) or if it is a parent of other nodes. 1935 * 1936 * This allows two (or more) different subsystems to assert sub-tree 1937 * existence before populating their own nodes, and to remove their 1938 * own nodes without orphaning the others when they are done. 1939 * ******************************************************************** 1940 */ 1941 #undef sysctl_createv 1942 int 1943 sysctl_createv(struct sysctllog **log, int cflags, 1944 const struct sysctlnode **rnode, const struct sysctlnode **cnode, 1945 int flags, int type, const char *namep, const char *descr, 1946 sysctlfn func, u_quad_t qv, void *newp, size_t newlen, 1947 ...) 1948 { 1949 va_list ap; 1950 int error, ni, namelen, name[CTL_MAXNAME]; 1951 const struct sysctlnode *root, *pnode; 1952 struct sysctlnode nnode, onode, *dnode; 1953 size_t sz; 1954 const struct sysctlnode *snode __diagused; 1955 1956 /* 1957 * where are we putting this? 1958 */ 1959 if (rnode != NULL && *rnode == NULL) { 1960 printf("sysctl_createv: rnode NULL\n"); 1961 return (EINVAL); 1962 } 1963 root = rnode ? *rnode : NULL; 1964 if (cnode != NULL) 1965 *cnode = NULL; 1966 if (cflags != 0) 1967 return (EINVAL); 1968 1969 /* 1970 * what is it? 1971 */ 1972 flags = SYSCTL_VERSION|SYSCTL_TYPE(type)|SYSCTL_FLAGS(flags); 1973 if (log != NULL) 1974 flags &= ~CTLFLAG_PERMANENT; 1975 1976 /* 1977 * where do we put it? 1978 */ 1979 va_start(ap, newlen); 1980 namelen = 0; 1981 error = 0; 1982 ni = -1; 1983 do { 1984 if (++ni == CTL_MAXNAME) { 1985 error = ENAMETOOLONG; 1986 break; 1987 } 1988 name[ni] = va_arg(ap, int); 1989 /* 1990 * sorry, this is not supported from here 1991 */ 1992 if (name[ni] == CTL_CREATESYM) { 1993 error = EINVAL; 1994 break; 1995 } 1996 } while (name[ni] != CTL_EOL && name[ni] != CTL_CREATE); 1997 va_end(ap); 1998 if (error) 1999 return error; 2000 namelen = ni + (name[ni] == CTL_CREATE ? 1 : 0); 2001 2002 /* 2003 * what's it called 2004 */ 2005 if (strlcpy(nnode.sysctl_name, namep, sizeof(nnode.sysctl_name)) >= 2006 sizeof(nnode.sysctl_name)) 2007 return (ENAMETOOLONG); 2008 2009 /* 2010 * cons up the description of the new node 2011 */ 2012 nnode.sysctl_num = name[namelen - 1]; 2013 name[namelen - 1] = CTL_CREATE; 2014 nnode.sysctl_size = newlen; 2015 nnode.sysctl_flags = flags; 2016 if (type == CTLTYPE_NODE) { 2017 nnode.sysctl_csize = 0; 2018 nnode.sysctl_clen = 0; 2019 nnode.sysctl_child = NULL; 2020 if (flags & CTLFLAG_ALIAS) 2021 nnode.sysctl_alias = qv; 2022 } else if (flags & CTLFLAG_IMMEDIATE) { 2023 switch (type) { 2024 case CTLTYPE_BOOL: 2025 nnode.sysctl_bdata = qv; 2026 break; 2027 case CTLTYPE_INT: 2028 nnode.sysctl_idata = qv; 2029 break; 2030 case CTLTYPE_QUAD: 2031 nnode.sysctl_qdata = qv; 2032 break; 2033 default: 2034 return (EINVAL); 2035 } 2036 } else { 2037 nnode.sysctl_data = newp; 2038 } 2039 nnode.sysctl_func = func; 2040 nnode.sysctl_parent = NULL; 2041 nnode.sysctl_ver = 0; 2042 2043 /* 2044 * initialize lock state -- we need locks if the main tree has 2045 * been marked as complete, but since we could be called from 2046 * either there, or from a device driver (say, at device 2047 * insertion), or from a module (at module load time, say), we 2048 * don't really want to "wait"... 2049 */ 2050 sysctl_lock(true); 2051 2052 /* 2053 * locate the prospective parent of the new node, and if we 2054 * find it, add the new node. 2055 */ 2056 sz = sizeof(onode); 2057 pnode = root; 2058 error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 2059 if (error) { 2060 /* 2061 * XXX: If you are seeing this printf in early bringup 2062 * stages, perhaps your setfault is not functioning and 2063 * thus kcopy() is mis-behaving. 2064 */ 2065 printf("sysctl_createv: sysctl_locate(%s) returned %d\n", 2066 nnode.sysctl_name, error); 2067 sysctl_unlock(); 2068 return (error); 2069 } 2070 error = sysctl_create(&name[ni], namelen - ni, &onode, &sz, 2071 &nnode, sizeof(nnode), &name[0], NULL, 2072 pnode); 2073 2074 /* 2075 * unfortunately the node we wanted to create is already 2076 * there. if the node that's already there is a reasonable 2077 * facsimile of the node we wanted to create, just pretend 2078 * (for the caller's benefit) that we managed to create the 2079 * node they wanted. 2080 */ 2081 if (error == EEXIST) { 2082 /* name is the same as requested... */ 2083 if (strcmp(nnode.sysctl_name, onode.sysctl_name) == 0 && 2084 /* they want the same function... */ 2085 nnode.sysctl_func == onode.sysctl_func && 2086 /* number is the same as requested, or... */ 2087 (nnode.sysctl_num == onode.sysctl_num || 2088 /* they didn't pick a number... */ 2089 nnode.sysctl_num == CTL_CREATE)) { 2090 /* 2091 * collision here from trying to create 2092 * something that already existed; let's give 2093 * our customers a hand and tell them they got 2094 * what they wanted. 2095 */ 2096 #ifdef SYSCTL_DEBUG_CREATE 2097 printf("cleared\n"); 2098 #endif /* SYSCTL_DEBUG_CREATE */ 2099 error = 0; 2100 } 2101 } 2102 2103 if (error == 0 && 2104 (cnode != NULL || log != NULL || descr != NULL)) { 2105 /* 2106 * sysctl_create() gave us back a copy of the node, 2107 * but we need to know where it actually is... 2108 */ 2109 pnode = root; 2110 error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 2111 snode = pnode; 2112 2113 /* 2114 * manual scan of last layer so that aliased nodes 2115 * aren't followed. 2116 */ 2117 if (error == 0) { 2118 for (ni = 0; ni < pnode->sysctl_clen; ni++) 2119 if (pnode->sysctl_child[ni].sysctl_num == 2120 onode.sysctl_num) 2121 break; 2122 if (ni < pnode->sysctl_clen) 2123 pnode = &pnode->sysctl_child[ni]; 2124 else 2125 error = ENOENT; 2126 } 2127 2128 /* 2129 * not expecting an error here, but... 2130 */ 2131 if (error == 0) { 2132 KASSERTMSG(pnode->sysctl_parent == snode, 2133 "sysctl parent mis-match pnode %s, snode %s", 2134 pnode->sysctl_name, snode->sysctl_name); 2135 if (log != NULL) 2136 sysctl_log_add(log, pnode); 2137 if (cnode != NULL) 2138 *cnode = pnode; 2139 if (descr != NULL) { 2140 /* 2141 * allow first caller to *set* a 2142 * description actually to set it 2143 * 2144 * discard const here so we can attach 2145 * the description 2146 */ 2147 dnode = __UNCONST(pnode); 2148 if (pnode->sysctl_desc != NULL) 2149 /* skip it...we've got one */; 2150 else if (flags & CTLFLAG_OWNDESC) { 2151 size_t l = strlen(descr) + 1; 2152 char *d = malloc(l, M_SYSCTLDATA, 2153 M_WAITOK); 2154 if (d != NULL) { 2155 memcpy(d, descr, l); 2156 dnode->sysctl_desc = d; 2157 dnode->sysctl_flags |= 2158 CTLFLAG_OWNDESC; 2159 } 2160 } else 2161 dnode->sysctl_desc = descr; 2162 } 2163 } else { 2164 printf("sysctl_create succeeded but node not found?!\n"); 2165 /* 2166 * confusing, but the create said it 2167 * succeeded, so... 2168 */ 2169 error = 0; 2170 } 2171 } 2172 2173 /* 2174 * now it should be safe to release the lock state. note that 2175 * the pointer to the newly created node being passed back may 2176 * not be "good" for very long. 2177 */ 2178 sysctl_unlock(); 2179 2180 if (error != 0) { 2181 printf("sysctl_createv: sysctl_create(%s) returned %d\n", 2182 nnode.sysctl_name, error); 2183 #if 0 2184 if (error != ENOENT) 2185 sysctl_dump(&onode); 2186 #endif 2187 } 2188 2189 return (error); 2190 } 2191 2192 int 2193 sysctl_destroyv(struct sysctlnode *rnode, ...) 2194 { 2195 va_list ap; 2196 int error, name[CTL_MAXNAME], namelen, ni; 2197 const struct sysctlnode *pnode, *node; 2198 struct sysctlnode dnode, *onode; 2199 size_t sz; 2200 2201 va_start(ap, rnode); 2202 namelen = 0; 2203 ni = 0; 2204 do { 2205 if (ni == CTL_MAXNAME) { 2206 va_end(ap); 2207 return (ENAMETOOLONG); 2208 } 2209 name[ni] = va_arg(ap, int); 2210 } while (name[ni++] != CTL_EOL); 2211 namelen = ni - 1; 2212 va_end(ap); 2213 2214 /* 2215 * i can't imagine why we'd be destroying a node when the tree 2216 * wasn't complete, but who knows? 2217 */ 2218 sysctl_lock(true); 2219 2220 /* 2221 * where is it? 2222 */ 2223 node = rnode; 2224 error = sysctl_locate(NULL, &name[0], namelen - 1, &node, &ni); 2225 if (error) { 2226 /* they want it gone and it's not there, so... */ 2227 sysctl_unlock(); 2228 return (error == ENOENT ? 0 : error); 2229 } 2230 2231 /* 2232 * set up the deletion 2233 */ 2234 pnode = node; 2235 node = &dnode; 2236 memset(&dnode, 0, sizeof(dnode)); 2237 dnode.sysctl_flags = SYSCTL_VERSION; 2238 dnode.sysctl_num = name[namelen - 1]; 2239 2240 /* 2241 * we found it, now let's nuke it 2242 */ 2243 name[namelen - 1] = CTL_DESTROY; 2244 sz = 0; 2245 error = sysctl_destroy(&name[namelen - 1], 1, NULL, &sz, 2246 node, sizeof(*node), &name[0], NULL, 2247 pnode); 2248 if (error == ENOTEMPTY) { 2249 /* 2250 * think of trying to delete "foo" when "foo.bar" 2251 * (which someone else put there) is still in 2252 * existence 2253 */ 2254 error = 0; 2255 2256 /* 2257 * dunno who put the description there, but if this 2258 * node can ever be removed, we need to make sure the 2259 * string doesn't go out of context. that means we 2260 * need to find the node that's still there (don't use 2261 * sysctl_locate() because that follows aliasing). 2262 */ 2263 node = pnode->sysctl_child; 2264 for (ni = 0; ni < pnode->sysctl_clen; ni++) 2265 if (node[ni].sysctl_num == dnode.sysctl_num) 2266 break; 2267 node = (ni < pnode->sysctl_clen) ? &node[ni] : NULL; 2268 2269 /* 2270 * if we found it, and this node has a description, 2271 * and this node can be released, and it doesn't 2272 * already own its own description...sigh. :) 2273 */ 2274 if (node != NULL && node->sysctl_desc != NULL && 2275 !(node->sysctl_flags & CTLFLAG_PERMANENT) && 2276 !(node->sysctl_flags & CTLFLAG_OWNDESC)) { 2277 char *d; 2278 2279 sz = strlen(node->sysctl_desc) + 1; 2280 d = malloc(sz, M_SYSCTLDATA, M_WAITOK); 2281 if (d != NULL) { 2282 /* 2283 * discard const so that we can 2284 * re-attach the description 2285 */ 2286 memcpy(d, node->sysctl_desc, sz); 2287 onode = __UNCONST(node); 2288 onode->sysctl_desc = d; 2289 onode->sysctl_flags |= CTLFLAG_OWNDESC; 2290 } else { 2291 /* 2292 * XXX drop the description? be 2293 * afraid? don't care? 2294 */ 2295 } 2296 } 2297 } 2298 2299 sysctl_unlock(); 2300 2301 return (error); 2302 } 2303 2304 /* 2305 * ******************************************************************** 2306 * Deletes an entire n-ary tree. Not recommended unless you know why 2307 * you're doing it. Personally, I don't know why you'd even think 2308 * about it. 2309 * ******************************************************************** 2310 */ 2311 void 2312 sysctl_free(struct sysctlnode *rnode) 2313 { 2314 struct sysctlnode *node, *pnode; 2315 2316 rw_enter(&sysctl_treelock, RW_WRITER); 2317 2318 if (rnode == NULL) 2319 rnode = &sysctl_root; 2320 2321 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 2322 printf("sysctl_free: rnode %p wrong version\n", rnode); 2323 rw_exit(&sysctl_treelock); 2324 return; 2325 } 2326 2327 pnode = rnode; 2328 2329 node = pnode->sysctl_child; 2330 do { 2331 while (node != NULL && pnode->sysctl_csize > 0) { 2332 while (node < 2333 &pnode->sysctl_child[pnode->sysctl_clen] && 2334 (SYSCTL_TYPE(node->sysctl_flags) != 2335 CTLTYPE_NODE || 2336 node->sysctl_csize == 0)) { 2337 if (SYSCTL_FLAGS(node->sysctl_flags) & 2338 CTLFLAG_OWNDATA) { 2339 if (node->sysctl_data != NULL) { 2340 free(node->sysctl_data, 2341 M_SYSCTLDATA); 2342 node->sysctl_data = NULL; 2343 } 2344 } 2345 if (SYSCTL_FLAGS(node->sysctl_flags) & 2346 CTLFLAG_OWNDESC) { 2347 if (node->sysctl_desc != NULL) { 2348 /*XXXUNCONST*/ 2349 free(__UNCONST(node->sysctl_desc), 2350 M_SYSCTLDATA); 2351 node->sysctl_desc = NULL; 2352 } 2353 } 2354 node++; 2355 } 2356 if (node < &pnode->sysctl_child[pnode->sysctl_clen]) { 2357 pnode = node; 2358 node = node->sysctl_child; 2359 } else 2360 break; 2361 } 2362 if (pnode->sysctl_child != NULL) 2363 free(pnode->sysctl_child, M_SYSCTLNODE); 2364 pnode->sysctl_clen = 0; 2365 pnode->sysctl_csize = 0; 2366 pnode->sysctl_child = NULL; 2367 node = pnode; 2368 pnode = node->sysctl_parent; 2369 } while (pnode != NULL && node != rnode); 2370 2371 rw_exit(&sysctl_treelock); 2372 } 2373 2374 void 2375 sysctl_log_print(const struct sysctllog *slog) 2376 { 2377 int i, len; 2378 2379 printf("root %p left %d size %d content", (const void *)slog->log_root, 2380 slog->log_left, slog->log_size); 2381 2382 for (len = 0, i = slog->log_left; i < slog->log_size; i++) { 2383 switch (len) { 2384 case 0: 2385 len = -1; 2386 printf(" version %d", slog->log_num[i]); 2387 break; 2388 case -1: 2389 len = -2; 2390 printf(" type %d", slog->log_num[i]); 2391 break; 2392 case -2: 2393 len = slog->log_num[i]; 2394 printf(" len %d:", slog->log_num[i]); 2395 if (len <= 0) 2396 len = -1; 2397 break; 2398 default: 2399 len--; 2400 printf(" %d", slog->log_num[i]); 2401 break; 2402 } 2403 } 2404 printf(" end\n"); 2405 } 2406 2407 int 2408 sysctl_log_add(struct sysctllog **logp, const struct sysctlnode *node) 2409 { 2410 const int size0 = 16; 2411 int name[CTL_MAXNAME], namelen, i; 2412 const struct sysctlnode *pnode; 2413 struct sysctllog *log; 2414 2415 if (node->sysctl_flags & CTLFLAG_PERMANENT) 2416 return (0); 2417 2418 if (logp == NULL) 2419 return (0); 2420 2421 if (*logp == NULL) { 2422 log = malloc(sizeof(struct sysctllog), 2423 M_SYSCTLDATA, M_WAITOK); 2424 if (log == NULL) { 2425 /* XXX print error message? */ 2426 return (-1); 2427 } 2428 log->log_num = malloc(size0 * sizeof(int), 2429 M_SYSCTLDATA, M_WAITOK); 2430 if (log->log_num == NULL) { 2431 /* XXX print error message? */ 2432 free(log, M_SYSCTLDATA); 2433 return (-1); 2434 } 2435 memset(log->log_num, 0, size0 * sizeof(int)); 2436 log->log_root = NULL; 2437 log->log_size = size0; 2438 log->log_left = size0; 2439 *logp = log; 2440 } else 2441 log = *logp; 2442 2443 /* 2444 * check that the root is proper. it's okay to record the 2445 * address of the root of a tree. it's the only thing that's 2446 * guaranteed not to shift around as nodes come and go. 2447 */ 2448 if (log->log_root == NULL) 2449 log->log_root = sysctl_rootof(node); 2450 else if (log->log_root != sysctl_rootof(node)) { 2451 printf("sysctl: log %p root mismatch (%p)\n", 2452 log->log_root, sysctl_rootof(node)); 2453 return (-1); 2454 } 2455 2456 /* 2457 * we will copy out name in reverse order 2458 */ 2459 for (pnode = node, namelen = 0; 2460 pnode != NULL && !(pnode->sysctl_flags & CTLFLAG_ROOT); 2461 pnode = pnode->sysctl_parent) 2462 name[namelen++] = pnode->sysctl_num; 2463 2464 /* 2465 * do we have space? 2466 */ 2467 if (log->log_left < (namelen + 3)) 2468 sysctl_log_realloc(log); 2469 if (log->log_left < (namelen + 3)) 2470 return (-1); 2471 2472 /* 2473 * stuff name in, then namelen, then node type, and finally, 2474 * the version for non-node nodes. 2475 */ 2476 for (i = 0; i < namelen && i < CTL_MAXNAME; i++) 2477 log->log_num[--log->log_left] = name[i]; 2478 log->log_num[--log->log_left] = namelen; 2479 log->log_num[--log->log_left] = SYSCTL_TYPE(node->sysctl_flags); 2480 if (log->log_num[log->log_left] != CTLTYPE_NODE) 2481 log->log_num[--log->log_left] = node->sysctl_ver; 2482 else 2483 log->log_num[--log->log_left] = 0; 2484 2485 return (0); 2486 } 2487 2488 void 2489 sysctl_teardown(struct sysctllog **logp) 2490 { 2491 const struct sysctlnode *rnode; 2492 struct sysctlnode node; 2493 struct sysctllog *log; 2494 uint namelen; 2495 int *name, t, v, error, ni; 2496 size_t sz; 2497 2498 if (logp == NULL || *logp == NULL) 2499 return; 2500 log = *logp; 2501 2502 rw_enter(&sysctl_treelock, RW_WRITER); 2503 memset(&node, 0, sizeof(node)); 2504 2505 while (log->log_left < log->log_size) { 2506 KASSERT((log->log_left + 3 < log->log_size) && 2507 (log->log_left + log->log_num[log->log_left + 2] <= 2508 log->log_size)); 2509 v = log->log_num[log->log_left++]; 2510 t = log->log_num[log->log_left++]; 2511 namelen = log->log_num[log->log_left++]; 2512 name = &log->log_num[log->log_left]; 2513 2514 node.sysctl_num = name[namelen - 1]; 2515 node.sysctl_flags = SYSCTL_VERSION|t; 2516 node.sysctl_ver = v; 2517 2518 rnode = log->log_root; 2519 error = sysctl_locate(NULL, &name[0], namelen, &rnode, &ni); 2520 if (error == 0) { 2521 name[namelen - 1] = CTL_DESTROY; 2522 rnode = rnode->sysctl_parent; 2523 sz = 0; 2524 (void)sysctl_destroy(&name[namelen - 1], 1, NULL, 2525 &sz, &node, sizeof(node), 2526 &name[0], NULL, rnode); 2527 } 2528 2529 log->log_left += namelen; 2530 } 2531 2532 KASSERT(log->log_size == log->log_left); 2533 free(log->log_num, M_SYSCTLDATA); 2534 free(log, M_SYSCTLDATA); 2535 *logp = NULL; 2536 2537 rw_exit(&sysctl_treelock); 2538 } 2539 2540 /* 2541 * ******************************************************************** 2542 * old_sysctl -- A routine to bridge old-style internal calls to the 2543 * new infrastructure. 2544 * ******************************************************************** 2545 */ 2546 int 2547 old_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2548 void *newp, size_t newlen, struct lwp *l) 2549 { 2550 int error; 2551 size_t oldlen = 0; 2552 size_t savelen; 2553 2554 if (oldlenp) { 2555 oldlen = *oldlenp; 2556 } 2557 savelen = oldlen; 2558 2559 sysctl_lock(newp != NULL); 2560 error = sysctl_dispatch(name, namelen, oldp, &oldlen, 2561 newp, newlen, name, l, NULL); 2562 sysctl_unlock(); 2563 if (error == 0 && oldp != NULL && savelen < oldlen) 2564 error = ENOMEM; 2565 if (oldlenp) { 2566 *oldlenp = oldlen; 2567 } 2568 2569 return (error); 2570 } 2571 2572 /* 2573 * ******************************************************************** 2574 * Section 4: Generic helper routines 2575 * ******************************************************************** 2576 * "helper" routines that can do more finely grained access control, 2577 * construct structures from disparate information, create the 2578 * appearance of more nodes and sub-trees, etc. for example, if 2579 * CTL_PROC wanted a helper function, it could respond to a CTL_QUERY 2580 * with a dynamically created list of nodes that represented the 2581 * currently running processes at that instant. 2582 * ******************************************************************** 2583 */ 2584 2585 /* 2586 * first, a few generic helpers that provide: 2587 * 2588 * sysctl_needfunc() a readonly interface that emits a warning 2589 * sysctl_notavail() returns EOPNOTSUPP (generic error) 2590 * sysctl_null() an empty return buffer with no error 2591 */ 2592 int 2593 sysctl_needfunc(SYSCTLFN_ARGS) 2594 { 2595 int error; 2596 2597 printf("!!SYSCTL_NEEDFUNC!!\n"); 2598 2599 if (newp != NULL || namelen != 0) 2600 return (EOPNOTSUPP); 2601 2602 error = 0; 2603 if (oldp != NULL) 2604 error = sysctl_copyout(l, rnode->sysctl_data, oldp, 2605 MIN(rnode->sysctl_size, *oldlenp)); 2606 *oldlenp = rnode->sysctl_size; 2607 2608 return (error); 2609 } 2610 2611 int 2612 sysctl_notavail(SYSCTLFN_ARGS) 2613 { 2614 2615 if (namelen == 1 && name[0] == CTL_QUERY) 2616 return (sysctl_query(SYSCTLFN_CALL(rnode))); 2617 2618 return (EOPNOTSUPP); 2619 } 2620 2621 int 2622 sysctl_null(SYSCTLFN_ARGS) 2623 { 2624 2625 *oldlenp = 0; 2626 2627 return (0); 2628 } 2629 2630 u_int 2631 sysctl_map_flags(const u_int *map, u_int word) 2632 { 2633 u_int rv; 2634 2635 for (rv = 0; *map != 0; map += 2) 2636 if ((word & map[0]) != 0) 2637 rv |= map[1]; 2638 2639 return rv; 2640 } 2641 2642 /* 2643 * ******************************************************************** 2644 * Section 5: The machinery that makes it all go 2645 * ******************************************************************** 2646 * Memory "manglement" routines. Not much to this, eh? 2647 * ******************************************************************** 2648 */ 2649 static int 2650 sysctl_alloc(struct sysctlnode *p, int x) 2651 { 2652 int i; 2653 struct sysctlnode *n; 2654 2655 assert(p->sysctl_child == NULL); 2656 2657 if (x == 1) 2658 n = malloc(sizeof(struct sysctlnode), 2659 M_SYSCTLNODE, M_WAITOK); 2660 else 2661 n = malloc(SYSCTL_DEFSIZE * sizeof(struct sysctlnode), 2662 M_SYSCTLNODE, M_WAITOK); 2663 if (n == NULL) 2664 return (ENOMEM); 2665 2666 if (x == 1) { 2667 memset(n, 0, sizeof(struct sysctlnode)); 2668 p->sysctl_csize = 1; 2669 } else { 2670 memset(n, 0, SYSCTL_DEFSIZE * sizeof(struct sysctlnode)); 2671 p->sysctl_csize = SYSCTL_DEFSIZE; 2672 } 2673 p->sysctl_clen = 0; 2674 2675 for (i = 0; i < p->sysctl_csize; i++) 2676 n[i].sysctl_parent = p; 2677 2678 p->sysctl_child = n; 2679 return (0); 2680 } 2681 2682 static int 2683 sysctl_realloc(struct sysctlnode *p) 2684 { 2685 int i, j, olen; 2686 struct sysctlnode *n; 2687 2688 assert(p->sysctl_csize == p->sysctl_clen); 2689 2690 /* 2691 * how many do we have...how many should we make? 2692 */ 2693 olen = p->sysctl_clen; 2694 n = malloc(2 * olen * sizeof(struct sysctlnode), M_SYSCTLNODE, 2695 M_WAITOK); 2696 if (n == NULL) 2697 return (ENOMEM); 2698 2699 /* 2700 * move old children over...initialize new children 2701 */ 2702 memcpy(n, p->sysctl_child, olen * sizeof(struct sysctlnode)); 2703 memset(&n[olen], 0, olen * sizeof(struct sysctlnode)); 2704 p->sysctl_csize = 2 * olen; 2705 2706 /* 2707 * reattach moved (and new) children to parent; if a moved 2708 * child node has children, reattach the parent pointers of 2709 * grandchildren 2710 */ 2711 for (i = 0; i < p->sysctl_csize; i++) { 2712 n[i].sysctl_parent = p; 2713 if (n[i].sysctl_child != NULL) { 2714 for (j = 0; j < n[i].sysctl_csize; j++) 2715 n[i].sysctl_child[j].sysctl_parent = &n[i]; 2716 } 2717 } 2718 2719 /* 2720 * get out with the old and in with the new 2721 */ 2722 free(p->sysctl_child, M_SYSCTLNODE); 2723 p->sysctl_child = n; 2724 2725 return (0); 2726 } 2727 2728 static int 2729 sysctl_log_realloc(struct sysctllog *log) 2730 { 2731 int *n, s, d; 2732 2733 s = log->log_size * 2; 2734 d = log->log_size; 2735 2736 n = malloc(s * sizeof(int), M_SYSCTLDATA, M_WAITOK); 2737 if (n == NULL) 2738 return (-1); 2739 2740 memset(n, 0, s * sizeof(int)); 2741 memcpy(&n[d], log->log_num, d * sizeof(int)); 2742 free(log->log_num, M_SYSCTLDATA); 2743 log->log_num = n; 2744 if (d) 2745 log->log_left += d; 2746 else 2747 log->log_left = s; 2748 log->log_size = s; 2749 2750 return (0); 2751 } 2752 2753 /* 2754 * ******************************************************************** 2755 * Section 6: Conversion between API versions wrt the sysctlnode 2756 * ******************************************************************** 2757 */ 2758 static int 2759 sysctl_cvt_in(struct lwp *l, int *vp, const void *i, size_t sz, 2760 struct sysctlnode *node) 2761 { 2762 int error, flags; 2763 2764 if (i == NULL || sz < sizeof(flags)) 2765 return (EINVAL); 2766 2767 error = sysctl_copyin(l, i, &flags, sizeof(flags)); 2768 if (error) 2769 return (error); 2770 2771 #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2772 #error sysctl_cvt_in: no support for SYSCTL_VERSION 2773 #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2774 2775 if (sz == sizeof(*node) && 2776 SYSCTL_VERS(flags) == SYSCTL_VERSION) { 2777 error = sysctl_copyin(l, i, node, sizeof(*node)); 2778 if (error) 2779 return (error); 2780 *vp = SYSCTL_VERSION; 2781 return (0); 2782 } 2783 2784 return (EINVAL); 2785 } 2786 2787 static int 2788 sysctl_cvt_out(struct lwp *l, int v, const struct sysctlnode *i, 2789 void *ovp, size_t left, size_t *szp) 2790 { 2791 size_t sz = sizeof(*i); 2792 const void *src = i; 2793 int error; 2794 2795 switch (v) { 2796 case SYSCTL_VERS_0: 2797 return (EINVAL); 2798 2799 #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2800 #error sysctl_cvt_out: no support for SYSCTL_VERSION 2801 #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2802 2803 case SYSCTL_VERSION: 2804 /* nothing more to do here */ 2805 break; 2806 } 2807 2808 if (ovp != NULL && left >= sz) { 2809 error = sysctl_copyout(l, src, ovp, sz); 2810 if (error) 2811 return (error); 2812 } 2813 2814 if (szp != NULL) 2815 *szp = sz; 2816 2817 return (0); 2818 } 2819