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