1 /* $NetBSD: kern_sysctl.c,v 1.58 2000/02/27 06:13:40 itojun 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 extern int kern_logsigexit; 237 238 /* 239 * kernel related system variables. 240 */ 241 int 242 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 243 int *name; 244 u_int namelen; 245 void *oldp; 246 size_t *oldlenp; 247 void *newp; 248 size_t newlen; 249 struct proc *p; 250 { 251 int error, level, inthostid; 252 int old_autonicetime; 253 int old_vnodes; 254 extern char ostype[], osrelease[], version[]; 255 256 /* All sysctl names at this level, except for a few, are terminal. */ 257 switch (name[0]) { 258 case KERN_PROC: 259 case KERN_PROF: 260 case KERN_MBUF: 261 /* Not terminal. */ 262 break; 263 default: 264 if (namelen != 1) 265 return (ENOTDIR); /* overloaded */ 266 } 267 268 switch (name[0]) { 269 case KERN_OSTYPE: 270 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 271 case KERN_OSRELEASE: 272 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 273 case KERN_OSREV: 274 return (sysctl_rdint(oldp, oldlenp, newp, NetBSD)); 275 case KERN_VERSION: 276 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 277 case KERN_MAXVNODES: 278 old_vnodes = desiredvnodes; 279 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes); 280 if (old_vnodes > desiredvnodes) { 281 desiredvnodes = old_vnodes; 282 return (EINVAL); 283 } 284 return (error); 285 case KERN_MAXPROC: 286 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 287 case KERN_MAXFILES: 288 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 289 case KERN_ARGMAX: 290 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 291 case KERN_SECURELVL: 292 level = securelevel; 293 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 294 newp == NULL) 295 return (error); 296 if (level < securelevel && p->p_pid != 1) 297 return (EPERM); 298 securelevel = level; 299 return (0); 300 case KERN_HOSTNAME: 301 error = sysctl_string(oldp, oldlenp, newp, newlen, 302 hostname, sizeof(hostname)); 303 if (newp && !error) 304 hostnamelen = newlen; 305 return (error); 306 case KERN_DOMAINNAME: 307 error = sysctl_string(oldp, oldlenp, newp, newlen, 308 domainname, sizeof(domainname)); 309 if (newp && !error) 310 domainnamelen = newlen; 311 return (error); 312 case KERN_HOSTID: 313 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 314 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 315 hostid = inthostid; 316 return (error); 317 case KERN_CLOCKRATE: 318 return (sysctl_clockrate(oldp, oldlenp)); 319 case KERN_BOOTTIME: 320 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 321 sizeof(struct timeval))); 322 case KERN_VNODE: 323 return (sysctl_vnode(oldp, oldlenp, p)); 324 case KERN_PROC: 325 return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp)); 326 case KERN_FILE: 327 return (sysctl_file(oldp, oldlenp)); 328 #ifdef GPROF 329 case KERN_PROF: 330 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 331 newp, newlen)); 332 #endif 333 case KERN_POSIX1: 334 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 335 case KERN_NGROUPS: 336 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 337 case KERN_JOB_CONTROL: 338 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 339 case KERN_SAVED_IDS: 340 #ifdef _POSIX_SAVED_IDS 341 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 342 #else 343 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 344 #endif 345 case KERN_MAXPARTITIONS: 346 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 347 case KERN_RAWPARTITION: 348 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 349 #ifdef NTP 350 case KERN_NTPTIME: 351 return (sysctl_ntptime(oldp, oldlenp)); 352 #endif 353 case KERN_AUTONICETIME: 354 old_autonicetime = autonicetime; 355 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime); 356 if (autonicetime < 0) 357 autonicetime = old_autonicetime; 358 return (error); 359 case KERN_AUTONICEVAL: 360 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval); 361 if (autoniceval < PRIO_MIN) 362 autoniceval = PRIO_MIN; 363 if (autoniceval > PRIO_MAX) 364 autoniceval = PRIO_MAX; 365 return (error); 366 case KERN_RTC_OFFSET: 367 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset)); 368 case KERN_ROOT_DEVICE: 369 return (sysctl_rdstring(oldp, oldlenp, newp, 370 root_device->dv_xname)); 371 case KERN_MSGBUFSIZE: 372 /* 373 * deal with cases where the message buffer has 374 * become corrupted. 375 */ 376 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 377 msgbufenabled = 0; 378 return (ENXIO); 379 } 380 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 381 case KERN_FSYNC: 382 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 383 case KERN_SYSVMSG: 384 #ifdef SYSVMSG 385 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 386 #else 387 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 388 #endif 389 case KERN_SYSVSEM: 390 #ifdef SYSVSEM 391 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 392 #else 393 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 394 #endif 395 case KERN_SYSVSHM: 396 #ifdef SYSVSHM 397 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 398 #else 399 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 400 #endif 401 case KERN_DEFCORENAME: 402 if (newp && newlen < 1) 403 return (EINVAL); 404 error = sysctl_string(oldp, oldlenp, newp, newlen, 405 defcorename, sizeof(defcorename)); 406 if (newp && !error) 407 defcorenamelen = newlen; 408 return (error); 409 case KERN_SYNCHRONIZED_IO: 410 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 411 case KERN_IOV_MAX: 412 return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX)); 413 case KERN_MBUF: 414 return (sysctl_dombuf(name + 1, namelen - 1, oldp, oldlenp, 415 newp, newlen)); 416 case KERN_MAPPED_FILES: 417 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 418 case KERN_MEMLOCK: 419 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 420 case KERN_MEMLOCK_RANGE: 421 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 422 case KERN_MEMORY_PROTECTION: 423 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 424 case KERN_LOGIN_NAME_MAX: 425 return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX)); 426 case KERN_LOGSIGEXIT: 427 return (sysctl_int(oldp, oldlenp, newp, newlen, &kern_logsigexit)); 428 default: 429 return (EOPNOTSUPP); 430 } 431 /* NOTREACHED */ 432 } 433 434 /* 435 * hardware related system variables. 436 */ 437 int 438 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 439 int *name; 440 u_int namelen; 441 void *oldp; 442 size_t *oldlenp; 443 void *newp; 444 size_t newlen; 445 struct proc *p; 446 { 447 extern char machine[], machine_arch[], cpu_model[]; 448 449 /* all sysctl names at this level are terminal */ 450 if (namelen != 1) 451 return (ENOTDIR); /* overloaded */ 452 453 switch (name[0]) { 454 case HW_MACHINE: 455 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 456 case HW_MACHINE_ARCH: 457 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch)); 458 case HW_MODEL: 459 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 460 case HW_NCPU: 461 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 462 case HW_BYTEORDER: 463 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 464 case HW_PHYSMEM: 465 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 466 case HW_USERMEM: 467 return (sysctl_rdint(oldp, oldlenp, newp, 468 ctob(physmem - uvmexp.wired))); 469 case HW_PAGESIZE: 470 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 471 case HW_ALIGNBYTES: 472 return (sysctl_rdint(oldp, oldlenp, newp, ALIGNBYTES)); 473 default: 474 return (EOPNOTSUPP); 475 } 476 /* NOTREACHED */ 477 } 478 479 #ifdef DEBUG 480 /* 481 * Debugging related system variables. 482 */ 483 struct ctldebug debug0, debug1, debug2, debug3, debug4; 484 struct ctldebug debug5, debug6, debug7, debug8, debug9; 485 struct ctldebug debug10, debug11, debug12, debug13, debug14; 486 struct ctldebug debug15, debug16, debug17, debug18, debug19; 487 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 488 &debug0, &debug1, &debug2, &debug3, &debug4, 489 &debug5, &debug6, &debug7, &debug8, &debug9, 490 &debug10, &debug11, &debug12, &debug13, &debug14, 491 &debug15, &debug16, &debug17, &debug18, &debug19, 492 }; 493 int 494 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 495 int *name; 496 u_int namelen; 497 void *oldp; 498 size_t *oldlenp; 499 void *newp; 500 size_t newlen; 501 struct proc *p; 502 { 503 struct ctldebug *cdp; 504 505 /* all sysctl names at this level are name and field */ 506 if (namelen != 2) 507 return (ENOTDIR); /* overloaded */ 508 cdp = debugvars[name[0]]; 509 if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0) 510 return (EOPNOTSUPP); 511 switch (name[1]) { 512 case CTL_DEBUG_NAME: 513 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 514 case CTL_DEBUG_VALUE: 515 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 516 default: 517 return (EOPNOTSUPP); 518 } 519 /* NOTREACHED */ 520 } 521 #endif /* DEBUG */ 522 523 int 524 proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 525 int *name; 526 u_int namelen; 527 void *oldp; 528 size_t *oldlenp; 529 void *newp; 530 size_t newlen; 531 struct proc *p; 532 { 533 struct proc *ptmp=NULL; 534 const struct proclist_desc *pd; 535 int error = 0; 536 struct rlimit alim; 537 struct plimit *newplim; 538 char *tmps = NULL; 539 int i, curlen, len; 540 541 if (namelen < 2) 542 return EINVAL; 543 544 if (name[0] == PROC_CURPROC) { 545 ptmp = p; 546 } else { 547 proclist_lock_read(); 548 for (pd = proclists; pd->pd_list != NULL; pd++) { 549 for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL; 550 ptmp = LIST_NEXT(ptmp, p_list)) { 551 /* Skip embryonic processes. */ 552 if (ptmp->p_stat == SIDL) 553 continue; 554 if (ptmp->p_pid == (pid_t)name[0]) 555 break; 556 } 557 if (ptmp != NULL) 558 break; 559 } 560 proclist_unlock_read(); 561 if (ptmp == NULL) 562 return(ESRCH); 563 if (p->p_ucred->cr_uid != 0) { 564 if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid || 565 p->p_cred->p_ruid != ptmp->p_cred->p_svuid) 566 return EPERM; 567 if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid) 568 return EPERM; /* sgid proc */ 569 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 570 if (p->p_ucred->cr_groups[i] == 571 ptmp->p_cred->p_rgid) 572 break; 573 } 574 if (i == p->p_ucred->cr_ngroups) 575 return EPERM; 576 } 577 } 578 if (name[1] == PROC_PID_CORENAME) { 579 if (namelen != 2) 580 return EINVAL; 581 /* 582 * Can't use sysctl_string() here because we may malloc a new 583 * area during the process, so we have to do it by hand. 584 */ 585 curlen = strlen(ptmp->p_limit->pl_corename) + 1; 586 if (oldlenp && *oldlenp < curlen) { 587 if (!oldp) 588 *oldlenp = curlen; 589 return (ENOMEM); 590 } 591 if (newp) { 592 if (securelevel > 2) 593 return EPERM; 594 if (newlen > MAXPATHLEN) 595 return ENAMETOOLONG; 596 tmps = malloc(newlen + 1, M_TEMP, M_WAITOK); 597 if (tmps == NULL) 598 return ENOMEM; 599 error = copyin(newp, tmps, newlen + 1); 600 tmps[newlen] = '\0'; 601 if (error) 602 goto cleanup; 603 /* Enforce to be either 'core' for end with '.core' */ 604 if (newlen < 4) { /* c.o.r.e */ 605 error = EINVAL; 606 goto cleanup; 607 } 608 len = newlen - 4; 609 if (len > 0) { 610 if (tmps[len - 1] != '.' && 611 tmps[len - 1] != '/') { 612 error = EINVAL; 613 goto cleanup; 614 } 615 } 616 if (strcmp(&tmps[len], "core") != 0) { 617 error = EINVAL; 618 goto cleanup; 619 } 620 } 621 if (oldp && oldlenp) { 622 *oldlenp = curlen; 623 error = copyout(ptmp->p_limit->pl_corename, oldp, 624 curlen); 625 } 626 if (newp && error == 0) { 627 /* if the 2 strings are identical, don't limcopy() */ 628 if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) { 629 error = 0; 630 goto cleanup; 631 } 632 if (ptmp->p_limit->p_refcnt > 1 && 633 (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) { 634 newplim = limcopy(ptmp->p_limit); 635 limfree(ptmp->p_limit); 636 ptmp->p_limit = newplim; 637 } else if (ptmp->p_limit->pl_corename != defcorename) { 638 free(ptmp->p_limit->pl_corename, M_TEMP); 639 } 640 ptmp->p_limit->pl_corename = tmps; 641 return (0); 642 } 643 cleanup: 644 if (tmps) 645 free(tmps, M_TEMP); 646 return (error); 647 } 648 if (name[1] == PROC_PID_LIMIT) { 649 if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID) 650 return EINVAL; 651 memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim)); 652 if (name[3] == PROC_PID_LIMIT_TYPE_HARD) 653 error = sysctl_quad(oldp, oldlenp, newp, newlen, 654 &alim.rlim_max); 655 else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT) 656 error = sysctl_quad(oldp, oldlenp, newp, newlen, 657 &alim.rlim_cur); 658 else 659 error = EINVAL; 660 661 if (error) 662 return error; 663 664 if (newp) 665 error = dosetrlimit(ptmp, p->p_cred, 666 name[2] - 1, &alim); 667 return error; 668 } 669 return (EINVAL); 670 } 671 672 /* 673 * Convenience macros. 674 */ 675 676 #define SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, len) \ 677 if (oldlenp) { \ 678 if (!oldp) \ 679 *oldlenp = len; \ 680 else { \ 681 if (*oldlenp < len) \ 682 return(ENOMEM); \ 683 *oldlenp = len; \ 684 error = copyout((caddr_t)valp, oldp, len); \ 685 } \ 686 } 687 688 #define SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, typ) \ 689 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, sizeof(typ)) 690 691 #define SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) \ 692 if (newp && newlen != len) \ 693 return (EINVAL); 694 695 #define SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, typ) \ 696 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, sizeof(typ)) 697 698 #define SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, len) \ 699 if (error == 0 && newp) \ 700 error = copyin(newp, valp, len); 701 702 #define SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, typ) \ 703 SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, sizeof(typ)) 704 705 #define SYSCTL_STRING_CORE(oldp, oldlenp, str) \ 706 if (oldlenp) { \ 707 len = strlen(str) + 1; \ 708 if (!oldp) \ 709 *oldlenp = len; \ 710 else { \ 711 if (*oldlenp < len) { \ 712 err2 = ENOMEM; \ 713 len = *oldlenp; \ 714 } else \ 715 *oldlenp = len; \ 716 error = copyout(str, oldp, len);\ 717 if (error == 0) \ 718 error = err2; \ 719 } \ 720 } 721 722 /* 723 * Validate parameters and get old / set new parameters 724 * for an integer-valued sysctl function. 725 */ 726 int 727 sysctl_int(oldp, oldlenp, newp, newlen, valp) 728 void *oldp; 729 size_t *oldlenp; 730 void *newp; 731 size_t newlen; 732 int *valp; 733 { 734 int error = 0; 735 736 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 737 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, int) 738 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, int) 739 740 return (error); 741 } 742 743 744 /* 745 * As above, but read-only. 746 */ 747 int 748 sysctl_rdint(oldp, oldlenp, newp, val) 749 void *oldp; 750 size_t *oldlenp; 751 void *newp; 752 int val; 753 { 754 int error = 0; 755 756 if (newp) 757 return (EPERM); 758 759 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, int) 760 761 return (error); 762 } 763 764 /* 765 * Validate parameters and get old / set new parameters 766 * for an quad-valued sysctl function. 767 */ 768 int 769 sysctl_quad(oldp, oldlenp, newp, newlen, valp) 770 void *oldp; 771 size_t *oldlenp; 772 void *newp; 773 size_t newlen; 774 quad_t *valp; 775 { 776 int error = 0; 777 778 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, quad_t) 779 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, quad_t) 780 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, quad_t) 781 782 return (error); 783 } 784 785 /* 786 * As above, but read-only. 787 */ 788 int 789 sysctl_rdquad(oldp, oldlenp, newp, val) 790 void *oldp; 791 size_t *oldlenp; 792 void *newp; 793 quad_t val; 794 { 795 int error = 0; 796 797 if (newp) 798 return (EPERM); 799 800 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, quad_t) 801 802 return (error); 803 } 804 805 /* 806 * Validate parameters and get old / set new parameters 807 * for a string-valued sysctl function. 808 */ 809 int 810 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 811 void *oldp; 812 size_t *oldlenp; 813 void *newp; 814 size_t newlen; 815 char *str; 816 int maxlen; 817 { 818 int len, error = 0, err2 = 0; 819 820 if (newp && newlen >= maxlen) 821 return (EINVAL); 822 823 SYSCTL_STRING_CORE(oldp, oldlenp, str); 824 825 if (error == 0 && newp) { 826 error = copyin(newp, str, newlen); 827 str[newlen] = 0; 828 } 829 return (error); 830 } 831 832 /* 833 * As above, but read-only. 834 */ 835 int 836 sysctl_rdstring(oldp, oldlenp, newp, str) 837 void *oldp; 838 size_t *oldlenp; 839 void *newp; 840 char *str; 841 { 842 int len, error = 0, err2 = 0; 843 844 if (newp) 845 return (EPERM); 846 847 SYSCTL_STRING_CORE(oldp, oldlenp, str); 848 849 return (error); 850 } 851 852 /* 853 * Validate parameters and get old / set new parameters 854 * for a structure oriented sysctl function. 855 */ 856 int 857 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 858 void *oldp; 859 size_t *oldlenp; 860 void *newp; 861 size_t newlen; 862 void *sp; 863 int len; 864 { 865 int error = 0; 866 867 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) 868 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 869 SYSCTL_SCALAR_NEWPCOP_LEN(newp, sp, len) 870 871 return (error); 872 } 873 874 /* 875 * Validate parameters and get old parameters 876 * for a structure oriented sysctl function. 877 */ 878 int 879 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 880 void *oldp; 881 size_t *oldlenp; 882 void *newp, *sp; 883 int len; 884 { 885 int error = 0; 886 887 if (newp) 888 return (EPERM); 889 890 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 891 892 return (error); 893 } 894 895 /* 896 * Get file structures. 897 */ 898 int 899 sysctl_file(where, sizep) 900 char *where; 901 size_t *sizep; 902 { 903 int buflen, error; 904 struct file *fp; 905 char *start = where; 906 907 buflen = *sizep; 908 if (where == NULL) { 909 /* 910 * overestimate by 10 files 911 */ 912 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 913 return (0); 914 } 915 916 /* 917 * first copyout filehead 918 */ 919 if (buflen < sizeof(filehead)) { 920 *sizep = 0; 921 return (0); 922 } 923 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 924 if (error) 925 return (error); 926 buflen -= sizeof(filehead); 927 where += sizeof(filehead); 928 929 /* 930 * followed by an array of file structures 931 */ 932 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { 933 if (buflen < sizeof(struct file)) { 934 *sizep = where - start; 935 return (ENOMEM); 936 } 937 error = copyout((caddr_t)fp, where, sizeof(struct file)); 938 if (error) 939 return (error); 940 buflen -= sizeof(struct file); 941 where += sizeof(struct file); 942 } 943 *sizep = where - start; 944 return (0); 945 } 946 947 /* 948 * try over estimating by 5 procs 949 */ 950 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 951 952 int 953 sysctl_doeproc(name, namelen, where, sizep) 954 int *name; 955 u_int namelen; 956 char *where; 957 size_t *sizep; 958 { 959 register struct proc *p; 960 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 961 register int needed = 0; 962 int buflen = where != NULL ? *sizep : 0; 963 const struct proclist_desc *pd; 964 struct eproc eproc; 965 int error = 0; 966 967 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 968 return (EINVAL); 969 970 proclist_lock_read(); 971 972 pd = proclists; 973 again: 974 for (p = LIST_FIRST(pd->pd_list); p != NULL; 975 p = LIST_NEXT(p, p_list)) { 976 /* 977 * Skip embryonic processes. 978 */ 979 if (p->p_stat == SIDL) 980 continue; 981 /* 982 * TODO - make more efficient (see notes below). 983 * do by session. 984 */ 985 switch (name[0]) { 986 987 case KERN_PROC_PID: 988 /* could do this with just a lookup */ 989 if (p->p_pid != (pid_t)name[1]) 990 continue; 991 break; 992 993 case KERN_PROC_PGRP: 994 /* could do this by traversing pgrp */ 995 if (p->p_pgrp->pg_id != (pid_t)name[1]) 996 continue; 997 break; 998 999 case KERN_PROC_TTY: 1000 if ((p->p_flag & P_CONTROLT) == 0 || 1001 p->p_session->s_ttyp == NULL || 1002 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 1003 continue; 1004 break; 1005 1006 case KERN_PROC_UID: 1007 if (p->p_ucred->cr_uid != (uid_t)name[1]) 1008 continue; 1009 break; 1010 1011 case KERN_PROC_RUID: 1012 if (p->p_cred->p_ruid != (uid_t)name[1]) 1013 continue; 1014 break; 1015 } 1016 if (buflen >= sizeof(struct kinfo_proc)) { 1017 fill_eproc(p, &eproc); 1018 error = copyout((caddr_t)p, &dp->kp_proc, 1019 sizeof(struct proc)); 1020 if (error) 1021 goto cleanup; 1022 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1023 sizeof(eproc)); 1024 if (error) 1025 goto cleanup; 1026 dp++; 1027 buflen -= sizeof(struct kinfo_proc); 1028 } 1029 needed += sizeof(struct kinfo_proc); 1030 } 1031 pd++; 1032 if (pd->pd_list != NULL) 1033 goto again; 1034 proclist_unlock_read(); 1035 1036 if (where != NULL) { 1037 *sizep = (caddr_t)dp - where; 1038 if (needed > *sizep) 1039 return (ENOMEM); 1040 } else { 1041 needed += KERN_PROCSLOP; 1042 *sizep = needed; 1043 } 1044 return (0); 1045 cleanup: 1046 proclist_unlock_read(); 1047 return (error); 1048 } 1049 1050 /* 1051 * Fill in an eproc structure for the specified process. 1052 */ 1053 void 1054 fill_eproc(p, ep) 1055 register struct proc *p; 1056 register struct eproc *ep; 1057 { 1058 register struct tty *tp; 1059 1060 ep->e_paddr = p; 1061 ep->e_sess = p->p_pgrp->pg_session; 1062 ep->e_pcred = *p->p_cred; 1063 ep->e_ucred = *p->p_ucred; 1064 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1065 ep->e_vm.vm_rssize = 0; 1066 ep->e_vm.vm_tsize = 0; 1067 ep->e_vm.vm_dsize = 0; 1068 ep->e_vm.vm_ssize = 0; 1069 /* ep->e_vm.vm_pmap = XXX; */ 1070 } else { 1071 register struct vmspace *vm = p->p_vmspace; 1072 1073 ep->e_vm.vm_rssize = vm_resident_count(vm); 1074 ep->e_vm.vm_tsize = vm->vm_tsize; 1075 ep->e_vm.vm_dsize = vm->vm_dsize; 1076 ep->e_vm.vm_ssize = vm->vm_ssize; 1077 } 1078 if (p->p_pptr) 1079 ep->e_ppid = p->p_pptr->p_pid; 1080 else 1081 ep->e_ppid = 0; 1082 ep->e_pgid = p->p_pgrp->pg_id; 1083 ep->e_sid = ep->e_sess->s_sid; 1084 ep->e_jobc = p->p_pgrp->pg_jobc; 1085 if ((p->p_flag & P_CONTROLT) && 1086 (tp = ep->e_sess->s_ttyp)) { 1087 ep->e_tdev = tp->t_dev; 1088 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1089 ep->e_tsess = tp->t_session; 1090 } else 1091 ep->e_tdev = NODEV; 1092 if (p->p_wmesg) 1093 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1094 ep->e_xsize = ep->e_xrssize = 0; 1095 ep->e_xccount = ep->e_xswrss = 0; 1096 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1097 if (SESS_LEADER(p)) 1098 ep->e_flag |= EPROC_SLEADER; 1099 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 1100 } 1101