1 /* $NetBSD: kern_sysctl.c,v 1.55 1999/11/17 23:24:54 is Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 39 */ 40 41 /* 42 * sysctl system call. 43 */ 44 45 #include "opt_ddb.h" 46 #include "opt_insecure.h" 47 #include "opt_defcorename.h" 48 #include "opt_sysv.h" 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/kernel.h> 53 #include <sys/malloc.h> 54 #include <sys/pool.h> 55 #include <sys/proc.h> 56 #include <sys/file.h> 57 #include <sys/vnode.h> 58 #include <sys/unistd.h> 59 #include <sys/buf.h> 60 #include <sys/ioctl.h> 61 #include <sys/tty.h> 62 #include <sys/disklabel.h> 63 #include <sys/device.h> 64 #include <vm/vm.h> 65 #include <sys/sysctl.h> 66 #include <sys/msgbuf.h> 67 68 #include <uvm/uvm_extern.h> 69 70 #include <sys/mount.h> 71 #include <sys/syscallargs.h> 72 #include <sys/resource.h> 73 #include <sys/resourcevar.h> 74 75 76 #if defined(DDB) 77 #include <ddb/ddbvar.h> 78 #endif 79 80 /* 81 * Locking and stats 82 */ 83 static struct sysctl_lock { 84 int sl_lock; 85 int sl_want; 86 int sl_locked; 87 } memlock; 88 89 int 90 sys___sysctl(p, v, retval) 91 struct proc *p; 92 void *v; 93 register_t *retval; 94 { 95 register struct sys___sysctl_args /* { 96 syscallarg(int *) name; 97 syscallarg(u_int) namelen; 98 syscallarg(void *) old; 99 syscallarg(size_t *) oldlenp; 100 syscallarg(void *) new; 101 syscallarg(size_t) newlen; 102 } */ *uap = v; 103 int error, dolock = 1; 104 size_t savelen = 0, oldlen = 0; 105 sysctlfn *fn; 106 int name[CTL_MAXNAME]; 107 size_t *oldlenp; 108 109 /* 110 * all top-level sysctl names are non-terminal 111 */ 112 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 113 return (EINVAL); 114 error = copyin(SCARG(uap, name), &name, 115 SCARG(uap, namelen) * sizeof(int)); 116 if (error) 117 return (error); 118 119 /* 120 * For all but CTL_PROC, must be root to change a value. 121 * For CTL_PROC, must be root, or owner of the proc (and not suid), 122 * this is checked in proc_sysctl() (once we know the targer proc). 123 */ 124 if (SCARG(uap, new) != NULL && name[0] != CTL_PROC && 125 (error = suser(p->p_ucred, &p->p_acflag))) 126 return error; 127 128 switch (name[0]) { 129 case CTL_KERN: 130 fn = kern_sysctl; 131 if (name[2] != KERN_VNODE) /* XXX */ 132 dolock = 0; 133 break; 134 case CTL_HW: 135 fn = hw_sysctl; 136 break; 137 case CTL_VM: 138 fn = uvm_sysctl; 139 break; 140 case CTL_NET: 141 fn = net_sysctl; 142 break; 143 case CTL_VFS: 144 fn = vfs_sysctl; 145 break; 146 case CTL_MACHDEP: 147 fn = cpu_sysctl; 148 break; 149 #ifdef DEBUG 150 case CTL_DEBUG: 151 fn = debug_sysctl; 152 break; 153 #endif 154 #ifdef DDB 155 case CTL_DDB: 156 fn = ddb_sysctl; 157 break; 158 #endif 159 case CTL_PROC: 160 fn = proc_sysctl; 161 break; 162 default: 163 return (EOPNOTSUPP); 164 } 165 166 oldlenp = SCARG(uap, oldlenp); 167 if (oldlenp) { 168 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 169 return (error); 170 oldlenp = &oldlen; 171 } 172 if (SCARG(uap, old) != NULL) { 173 if (!uvm_useracc(SCARG(uap, old), oldlen, B_WRITE)) 174 return (EFAULT); 175 while (memlock.sl_lock) { 176 memlock.sl_want = 1; 177 sleep((caddr_t)&memlock, PRIBIO+1); 178 memlock.sl_locked++; 179 } 180 memlock.sl_lock = 1; 181 if (dolock) { 182 /* 183 * XXX Um, this is kind of evil. What should we 184 * XXX be passing here? 185 */ 186 if (uvm_vslock(p, SCARG(uap, old), oldlen, 187 VM_PROT_NONE) != KERN_SUCCESS) { 188 memlock.sl_lock = 0; 189 if (memlock.sl_want) { 190 memlock.sl_want = 0; 191 wakeup((caddr_t)&memlock); 192 return (EFAULT); 193 } 194 } 195 } 196 savelen = oldlen; 197 } 198 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), 199 oldlenp, SCARG(uap, new), SCARG(uap, newlen), p); 200 if (SCARG(uap, old) != NULL) { 201 if (dolock) 202 uvm_vsunlock(p, SCARG(uap, old), savelen); 203 memlock.sl_lock = 0; 204 if (memlock.sl_want) { 205 memlock.sl_want = 0; 206 wakeup((caddr_t)&memlock); 207 } 208 } 209 if (error) 210 return (error); 211 if (SCARG(uap, oldlenp)) 212 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 213 return (error); 214 } 215 216 /* 217 * Attributes stored in the kernel. 218 */ 219 char hostname[MAXHOSTNAMELEN]; 220 int hostnamelen; 221 char domainname[MAXHOSTNAMELEN]; 222 int domainnamelen; 223 long hostid; 224 #ifdef INSECURE 225 int securelevel = -1; 226 #else 227 int securelevel = 0; 228 #endif 229 #ifdef DEFCORENAME 230 char defcorename[MAXPATHLEN] = DEFCORENAME; 231 int defcorenamelen = sizeof(DEFCORENAME); 232 #else 233 char defcorename[MAXPATHLEN] = "%n.core"; 234 int defcorenamelen = sizeof("%n.core"); 235 #endif 236 237 /* 238 * kernel related system variables. 239 */ 240 int 241 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 242 int *name; 243 u_int namelen; 244 void *oldp; 245 size_t *oldlenp; 246 void *newp; 247 size_t newlen; 248 struct proc *p; 249 { 250 int error, level, inthostid; 251 int old_autonicetime; 252 int old_vnodes; 253 extern char ostype[], osrelease[], version[]; 254 255 /* All sysctl names at this level, except for a few, are terminal. */ 256 switch (name[0]) { 257 case KERN_PROC: 258 case KERN_PROF: 259 case KERN_MBUF: 260 /* Not terminal. */ 261 break; 262 default: 263 if (namelen != 1) 264 return (ENOTDIR); /* overloaded */ 265 } 266 267 switch (name[0]) { 268 case KERN_OSTYPE: 269 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 270 case KERN_OSRELEASE: 271 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 272 case KERN_OSREV: 273 return (sysctl_rdint(oldp, oldlenp, newp, NetBSD)); 274 case KERN_VERSION: 275 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 276 case KERN_MAXVNODES: 277 old_vnodes = desiredvnodes; 278 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes); 279 if (old_vnodes > desiredvnodes) { 280 desiredvnodes = old_vnodes; 281 return (EINVAL); 282 } 283 return (error); 284 case KERN_MAXPROC: 285 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 286 case KERN_MAXFILES: 287 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 288 case KERN_ARGMAX: 289 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 290 case KERN_SECURELVL: 291 level = securelevel; 292 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 293 newp == NULL) 294 return (error); 295 if (level < securelevel && p->p_pid != 1) 296 return (EPERM); 297 securelevel = level; 298 return (0); 299 case KERN_HOSTNAME: 300 error = sysctl_string(oldp, oldlenp, newp, newlen, 301 hostname, sizeof(hostname)); 302 if (newp && !error) 303 hostnamelen = newlen; 304 return (error); 305 case KERN_DOMAINNAME: 306 error = sysctl_string(oldp, oldlenp, newp, newlen, 307 domainname, sizeof(domainname)); 308 if (newp && !error) 309 domainnamelen = newlen; 310 return (error); 311 case KERN_HOSTID: 312 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 313 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 314 hostid = inthostid; 315 return (error); 316 case KERN_CLOCKRATE: 317 return (sysctl_clockrate(oldp, oldlenp)); 318 case KERN_BOOTTIME: 319 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 320 sizeof(struct timeval))); 321 case KERN_VNODE: 322 return (sysctl_vnode(oldp, oldlenp, p)); 323 case KERN_PROC: 324 return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp)); 325 case KERN_FILE: 326 return (sysctl_file(oldp, oldlenp)); 327 #ifdef GPROF 328 case KERN_PROF: 329 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 330 newp, newlen)); 331 #endif 332 case KERN_POSIX1: 333 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 334 case KERN_NGROUPS: 335 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 336 case KERN_JOB_CONTROL: 337 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 338 case KERN_SAVED_IDS: 339 #ifdef _POSIX_SAVED_IDS 340 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 341 #else 342 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 343 #endif 344 case KERN_MAXPARTITIONS: 345 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 346 case KERN_RAWPARTITION: 347 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 348 #ifdef NTP 349 case KERN_NTPTIME: 350 return (sysctl_ntptime(oldp, oldlenp)); 351 #endif 352 case KERN_AUTONICETIME: 353 old_autonicetime = autonicetime; 354 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime); 355 if (autonicetime < 0) 356 autonicetime = old_autonicetime; 357 return (error); 358 case KERN_AUTONICEVAL: 359 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval); 360 if (autoniceval < PRIO_MIN) 361 autoniceval = PRIO_MIN; 362 if (autoniceval > PRIO_MAX) 363 autoniceval = PRIO_MAX; 364 return (error); 365 case KERN_RTC_OFFSET: 366 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset)); 367 case KERN_ROOT_DEVICE: 368 return (sysctl_rdstring(oldp, oldlenp, newp, 369 root_device->dv_xname)); 370 case KERN_MSGBUFSIZE: 371 /* 372 * deal with cases where the message buffer has 373 * become corrupted. 374 */ 375 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 376 msgbufenabled = 0; 377 return (ENXIO); 378 } 379 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 380 case KERN_FSYNC: 381 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 382 case KERN_SYSVMSG: 383 #ifdef SYSVMSG 384 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 385 #else 386 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 387 #endif 388 case KERN_SYSVSEM: 389 #ifdef SYSVSEM 390 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 391 #else 392 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 393 #endif 394 case KERN_SYSVSHM: 395 #ifdef SYSVSHM 396 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 397 #else 398 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 399 #endif 400 case KERN_DEFCORENAME: 401 if (newp && newlen < 1) 402 return (EINVAL); 403 error = sysctl_string(oldp, oldlenp, newp, newlen, 404 defcorename, sizeof(defcorename)); 405 if (newp && !error) 406 defcorenamelen = newlen; 407 return (error); 408 case KERN_SYNCHRONIZED_IO: 409 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 410 case KERN_IOV_MAX: 411 return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX)); 412 case KERN_MBUF: 413 return (sysctl_dombuf(name + 1, namelen - 1, oldp, oldlenp, 414 newp, newlen)); 415 case KERN_MAPPED_FILES: 416 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 417 case KERN_MEMLOCK: 418 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 419 case KERN_MEMLOCK_RANGE: 420 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 421 case KERN_MEMORY_PROTECTION: 422 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 423 case KERN_LOGIN_NAME_MAX: 424 return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX)); 425 default: 426 return (EOPNOTSUPP); 427 } 428 /* NOTREACHED */ 429 } 430 431 /* 432 * hardware related system variables. 433 */ 434 int 435 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 436 int *name; 437 u_int namelen; 438 void *oldp; 439 size_t *oldlenp; 440 void *newp; 441 size_t newlen; 442 struct proc *p; 443 { 444 extern char machine[], machine_arch[], cpu_model[]; 445 446 /* all sysctl names at this level are terminal */ 447 if (namelen != 1) 448 return (ENOTDIR); /* overloaded */ 449 450 switch (name[0]) { 451 case HW_MACHINE: 452 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 453 case HW_MACHINE_ARCH: 454 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch)); 455 case HW_MODEL: 456 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 457 case HW_NCPU: 458 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 459 case HW_BYTEORDER: 460 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 461 case HW_PHYSMEM: 462 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 463 case HW_USERMEM: 464 return (sysctl_rdint(oldp, oldlenp, newp, 465 ctob(physmem - uvmexp.wired))); 466 case HW_PAGESIZE: 467 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 468 default: 469 return (EOPNOTSUPP); 470 } 471 /* NOTREACHED */ 472 } 473 474 #ifdef DEBUG 475 /* 476 * Debugging related system variables. 477 */ 478 struct ctldebug debug0, debug1, debug2, debug3, debug4; 479 struct ctldebug debug5, debug6, debug7, debug8, debug9; 480 struct ctldebug debug10, debug11, debug12, debug13, debug14; 481 struct ctldebug debug15, debug16, debug17, debug18, debug19; 482 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 483 &debug0, &debug1, &debug2, &debug3, &debug4, 484 &debug5, &debug6, &debug7, &debug8, &debug9, 485 &debug10, &debug11, &debug12, &debug13, &debug14, 486 &debug15, &debug16, &debug17, &debug18, &debug19, 487 }; 488 int 489 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 490 int *name; 491 u_int namelen; 492 void *oldp; 493 size_t *oldlenp; 494 void *newp; 495 size_t newlen; 496 struct proc *p; 497 { 498 struct ctldebug *cdp; 499 500 /* all sysctl names at this level are name and field */ 501 if (namelen != 2) 502 return (ENOTDIR); /* overloaded */ 503 cdp = debugvars[name[0]]; 504 if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0) 505 return (EOPNOTSUPP); 506 switch (name[1]) { 507 case CTL_DEBUG_NAME: 508 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 509 case CTL_DEBUG_VALUE: 510 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 511 default: 512 return (EOPNOTSUPP); 513 } 514 /* NOTREACHED */ 515 } 516 #endif /* DEBUG */ 517 518 int 519 proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 520 int *name; 521 u_int namelen; 522 void *oldp; 523 size_t *oldlenp; 524 void *newp; 525 size_t newlen; 526 struct proc *p; 527 { 528 struct proc *ptmp=NULL; 529 const struct proclist_desc *pd; 530 int error = 0; 531 struct rlimit alim; 532 struct plimit *newplim; 533 char *tmps = NULL; 534 int i, curlen, len; 535 536 if (namelen < 2) 537 return EINVAL; 538 539 if (name[0] == PROC_CURPROC) { 540 ptmp = p; 541 } else { 542 proclist_lock_read(); 543 for (pd = proclists; pd->pd_list != NULL; pd++) { 544 for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL; 545 ptmp = LIST_NEXT(ptmp, p_list)) { 546 /* Skip embryonic processes. */ 547 if (ptmp->p_stat == SIDL) 548 continue; 549 if (ptmp->p_pid == (pid_t)name[0]) 550 break; 551 } 552 if (ptmp != NULL) 553 break; 554 } 555 proclist_unlock_read(); 556 if (ptmp == NULL) 557 return(ESRCH); 558 if (p->p_ucred->cr_uid != 0) { 559 if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid || 560 p->p_cred->p_ruid != ptmp->p_cred->p_svuid) 561 return EPERM; 562 if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid) 563 return EPERM; /* sgid proc */ 564 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 565 if (p->p_ucred->cr_groups[i] == 566 ptmp->p_cred->p_rgid) 567 break; 568 } 569 if (i == p->p_ucred->cr_ngroups) 570 return EPERM; 571 } 572 } 573 if (name[1] == PROC_PID_CORENAME) { 574 if (namelen != 2) 575 return EINVAL; 576 /* 577 * Can't use sysctl_string() here because we may malloc a new 578 * area during the process, so we have to do it by hand. 579 */ 580 curlen = strlen(ptmp->p_limit->pl_corename) + 1; 581 if (oldlenp && *oldlenp < curlen) { 582 if (!oldp) 583 *oldlenp = curlen; 584 return (ENOMEM); 585 } 586 if (newp) { 587 if (securelevel > 2) 588 return EPERM; 589 if (newlen > MAXPATHLEN) 590 return ENAMETOOLONG; 591 tmps = malloc(newlen + 1, M_TEMP, M_WAITOK); 592 if (tmps == NULL) 593 return ENOMEM; 594 error = copyin(newp, tmps, newlen + 1); 595 tmps[newlen] = '\0'; 596 if (error) 597 goto cleanup; 598 /* Enforce to be either 'core' for end with '.core' */ 599 if (newlen < 4) { /* c.o.r.e */ 600 error = EINVAL; 601 goto cleanup; 602 } 603 len = newlen - 4; 604 if (len > 0) { 605 if (tmps[len - 1] != '.' && 606 tmps[len - 1] != '/') { 607 error = EINVAL; 608 goto cleanup; 609 } 610 } 611 if (strcmp(&tmps[len], "core") != 0) { 612 error = EINVAL; 613 goto cleanup; 614 } 615 } 616 if (oldp && oldlenp) { 617 *oldlenp = curlen; 618 error = copyout(ptmp->p_limit->pl_corename, oldp, 619 curlen); 620 } 621 if (newp && error == 0) { 622 /* if the 2 strings are identical, don't limcopy() */ 623 if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) { 624 error = 0; 625 goto cleanup; 626 } 627 if (ptmp->p_limit->p_refcnt > 1 && 628 (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) { 629 newplim = limcopy(ptmp->p_limit); 630 limfree(ptmp->p_limit); 631 ptmp->p_limit = newplim; 632 } else if (ptmp->p_limit->pl_corename != defcorename) { 633 free(ptmp->p_limit->pl_corename, M_TEMP); 634 } 635 ptmp->p_limit->pl_corename = tmps; 636 return (0); 637 } 638 cleanup: 639 if (tmps) 640 free(tmps, M_TEMP); 641 return (error); 642 } 643 if (name[1] == PROC_PID_LIMIT) { 644 if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID) 645 return EINVAL; 646 memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim)); 647 if (name[3] == PROC_PID_LIMIT_TYPE_HARD) 648 error = sysctl_quad(oldp, oldlenp, newp, newlen, 649 &alim.rlim_max); 650 else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT) 651 error = sysctl_quad(oldp, oldlenp, newp, newlen, 652 &alim.rlim_cur); 653 else 654 error = EINVAL; 655 656 if (error) 657 return error; 658 659 if (newp) 660 error = dosetrlimit(ptmp, p->p_cred, 661 name[2] - 1, &alim); 662 return error; 663 } 664 return (EINVAL); 665 } 666 667 /* 668 * Convenience macros. 669 */ 670 671 #define SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, len) \ 672 if (oldlenp) { \ 673 if (!oldp) \ 674 *oldlenp = len; \ 675 else { \ 676 if (*oldlenp < len) \ 677 return(ENOMEM); \ 678 *oldlenp = len; \ 679 error = copyout((caddr_t)valp, oldp, len); \ 680 } \ 681 } 682 683 #define SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, typ) \ 684 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, sizeof(typ)) 685 686 #define SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) \ 687 if (newp && newlen != len) \ 688 return (EINVAL); 689 690 #define SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, typ) \ 691 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, sizeof(typ)) 692 693 #define SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, len) \ 694 if (error == 0 && newp) \ 695 error = copyin(newp, valp, len); 696 697 #define SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, typ) \ 698 SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, sizeof(typ)) 699 700 #define SYSCTL_STRING_CORE(oldp, oldlenp, str) \ 701 if (oldlenp) { \ 702 len = strlen(str) + 1; \ 703 if (!oldp) \ 704 *oldlenp = len; \ 705 else { \ 706 if (*oldlenp < len) { \ 707 err2 = ENOMEM; \ 708 len = *oldlenp; \ 709 } else \ 710 *oldlenp = len; \ 711 error = copyout(str, oldp, len);\ 712 if (error == 0) \ 713 error = err2; \ 714 } \ 715 } 716 717 /* 718 * Validate parameters and get old / set new parameters 719 * for an integer-valued sysctl function. 720 */ 721 int 722 sysctl_int(oldp, oldlenp, newp, newlen, valp) 723 void *oldp; 724 size_t *oldlenp; 725 void *newp; 726 size_t newlen; 727 int *valp; 728 { 729 int error = 0; 730 731 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 732 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, int) 733 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, int) 734 735 return (error); 736 } 737 738 739 /* 740 * As above, but read-only. 741 */ 742 int 743 sysctl_rdint(oldp, oldlenp, newp, val) 744 void *oldp; 745 size_t *oldlenp; 746 void *newp; 747 int val; 748 { 749 int error = 0; 750 751 if (newp) 752 return (EPERM); 753 754 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, int) 755 756 return (error); 757 } 758 759 /* 760 * Validate parameters and get old / set new parameters 761 * for an quad-valued sysctl function. 762 */ 763 int 764 sysctl_quad(oldp, oldlenp, newp, newlen, valp) 765 void *oldp; 766 size_t *oldlenp; 767 void *newp; 768 size_t newlen; 769 quad_t *valp; 770 { 771 int error = 0; 772 773 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, quad_t) 774 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, quad_t) 775 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, quad_t) 776 777 return (error); 778 } 779 780 /* 781 * As above, but read-only. 782 */ 783 int 784 sysctl_rdquad(oldp, oldlenp, newp, val) 785 void *oldp; 786 size_t *oldlenp; 787 void *newp; 788 quad_t val; 789 { 790 int error = 0; 791 792 if (newp) 793 return (EPERM); 794 795 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, quad_t) 796 797 return (error); 798 } 799 800 /* 801 * Validate parameters and get old / set new parameters 802 * for a string-valued sysctl function. 803 */ 804 int 805 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 806 void *oldp; 807 size_t *oldlenp; 808 void *newp; 809 size_t newlen; 810 char *str; 811 int maxlen; 812 { 813 int len, error = 0, err2 = 0; 814 815 if (newp && newlen >= maxlen) 816 return (EINVAL); 817 818 SYSCTL_STRING_CORE(oldp, oldlenp, str); 819 820 if (error == 0 && newp) { 821 error = copyin(newp, str, newlen); 822 str[newlen] = 0; 823 } 824 return (error); 825 } 826 827 /* 828 * As above, but read-only. 829 */ 830 int 831 sysctl_rdstring(oldp, oldlenp, newp, str) 832 void *oldp; 833 size_t *oldlenp; 834 void *newp; 835 char *str; 836 { 837 int len, error = 0, err2 = 0; 838 839 if (newp) 840 return (EPERM); 841 842 SYSCTL_STRING_CORE(oldp, oldlenp, str); 843 844 return (error); 845 } 846 847 /* 848 * Validate parameters and get old / set new parameters 849 * for a structure oriented sysctl function. 850 */ 851 int 852 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 853 void *oldp; 854 size_t *oldlenp; 855 void *newp; 856 size_t newlen; 857 void *sp; 858 int len; 859 { 860 int error = 0; 861 862 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) 863 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 864 SYSCTL_SCALAR_NEWPCOP_LEN(newp, sp, len) 865 866 return (error); 867 } 868 869 /* 870 * Validate parameters and get old parameters 871 * for a structure oriented sysctl function. 872 */ 873 int 874 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 875 void *oldp; 876 size_t *oldlenp; 877 void *newp, *sp; 878 int len; 879 { 880 int error = 0; 881 882 if (newp) 883 return (EPERM); 884 885 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 886 887 return (error); 888 } 889 890 /* 891 * Get file structures. 892 */ 893 int 894 sysctl_file(where, sizep) 895 char *where; 896 size_t *sizep; 897 { 898 int buflen, error; 899 struct file *fp; 900 char *start = where; 901 902 buflen = *sizep; 903 if (where == NULL) { 904 /* 905 * overestimate by 10 files 906 */ 907 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 908 return (0); 909 } 910 911 /* 912 * first copyout filehead 913 */ 914 if (buflen < sizeof(filehead)) { 915 *sizep = 0; 916 return (0); 917 } 918 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 919 if (error) 920 return (error); 921 buflen -= sizeof(filehead); 922 where += sizeof(filehead); 923 924 /* 925 * followed by an array of file structures 926 */ 927 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { 928 if (buflen < sizeof(struct file)) { 929 *sizep = where - start; 930 return (ENOMEM); 931 } 932 error = copyout((caddr_t)fp, where, sizeof(struct file)); 933 if (error) 934 return (error); 935 buflen -= sizeof(struct file); 936 where += sizeof(struct file); 937 } 938 *sizep = where - start; 939 return (0); 940 } 941 942 /* 943 * try over estimating by 5 procs 944 */ 945 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 946 947 int 948 sysctl_doeproc(name, namelen, where, sizep) 949 int *name; 950 u_int namelen; 951 char *where; 952 size_t *sizep; 953 { 954 register struct proc *p; 955 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 956 register int needed = 0; 957 int buflen = where != NULL ? *sizep : 0; 958 const struct proclist_desc *pd; 959 struct eproc eproc; 960 int error = 0; 961 962 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 963 return (EINVAL); 964 965 proclist_lock_read(); 966 967 pd = proclists; 968 again: 969 for (p = LIST_FIRST(pd->pd_list); p != NULL; 970 p = LIST_NEXT(p, p_list)) { 971 /* 972 * Skip embryonic processes. 973 */ 974 if (p->p_stat == SIDL) 975 continue; 976 /* 977 * TODO - make more efficient (see notes below). 978 * do by session. 979 */ 980 switch (name[0]) { 981 982 case KERN_PROC_PID: 983 /* could do this with just a lookup */ 984 if (p->p_pid != (pid_t)name[1]) 985 continue; 986 break; 987 988 case KERN_PROC_PGRP: 989 /* could do this by traversing pgrp */ 990 if (p->p_pgrp->pg_id != (pid_t)name[1]) 991 continue; 992 break; 993 994 case KERN_PROC_TTY: 995 if ((p->p_flag & P_CONTROLT) == 0 || 996 p->p_session->s_ttyp == NULL || 997 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 998 continue; 999 break; 1000 1001 case KERN_PROC_UID: 1002 if (p->p_ucred->cr_uid != (uid_t)name[1]) 1003 continue; 1004 break; 1005 1006 case KERN_PROC_RUID: 1007 if (p->p_cred->p_ruid != (uid_t)name[1]) 1008 continue; 1009 break; 1010 } 1011 if (buflen >= sizeof(struct kinfo_proc)) { 1012 fill_eproc(p, &eproc); 1013 error = copyout((caddr_t)p, &dp->kp_proc, 1014 sizeof(struct proc)); 1015 if (error) 1016 return (error); 1017 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1018 sizeof(eproc)); 1019 if (error) 1020 return (error); 1021 dp++; 1022 buflen -= sizeof(struct kinfo_proc); 1023 } 1024 needed += sizeof(struct kinfo_proc); 1025 } 1026 pd++; 1027 if (pd->pd_list != NULL) 1028 goto again; 1029 proclist_unlock_read(); 1030 1031 if (where != NULL) { 1032 *sizep = (caddr_t)dp - where; 1033 if (needed > *sizep) 1034 return (ENOMEM); 1035 } else { 1036 needed += KERN_PROCSLOP; 1037 *sizep = needed; 1038 } 1039 return (0); 1040 } 1041 1042 /* 1043 * Fill in an eproc structure for the specified process. 1044 */ 1045 void 1046 fill_eproc(p, ep) 1047 register struct proc *p; 1048 register struct eproc *ep; 1049 { 1050 register struct tty *tp; 1051 1052 ep->e_paddr = p; 1053 ep->e_sess = p->p_pgrp->pg_session; 1054 ep->e_pcred = *p->p_cred; 1055 ep->e_ucred = *p->p_ucred; 1056 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1057 ep->e_vm.vm_rssize = 0; 1058 ep->e_vm.vm_tsize = 0; 1059 ep->e_vm.vm_dsize = 0; 1060 ep->e_vm.vm_ssize = 0; 1061 /* ep->e_vm.vm_pmap = XXX; */ 1062 } else { 1063 register struct vmspace *vm = p->p_vmspace; 1064 1065 ep->e_vm.vm_rssize = vm_resident_count(vm); 1066 ep->e_vm.vm_tsize = vm->vm_tsize; 1067 ep->e_vm.vm_dsize = vm->vm_dsize; 1068 ep->e_vm.vm_ssize = vm->vm_ssize; 1069 } 1070 if (p->p_pptr) 1071 ep->e_ppid = p->p_pptr->p_pid; 1072 else 1073 ep->e_ppid = 0; 1074 ep->e_pgid = p->p_pgrp->pg_id; 1075 ep->e_sid = ep->e_sess->s_sid; 1076 ep->e_jobc = p->p_pgrp->pg_jobc; 1077 if ((p->p_flag & P_CONTROLT) && 1078 (tp = ep->e_sess->s_ttyp)) { 1079 ep->e_tdev = tp->t_dev; 1080 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1081 ep->e_tsess = tp->t_session; 1082 } else 1083 ep->e_tdev = NODEV; 1084 if (p->p_wmesg) 1085 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1086 ep->e_xsize = ep->e_xrssize = 0; 1087 ep->e_xccount = ep->e_xswrss = 0; 1088 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1089 if (SESS_LEADER(p)) 1090 ep->e_flag |= EPROC_SLEADER; 1091 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 1092 } 1093