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