1 /* $NetBSD: kern_sysctl.c,v 1.88 2001/04/26 06:07:13 enami 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 #include "pty.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/kernel.h> 54 #include <sys/buf.h> 55 #include <sys/device.h> 56 #include <sys/disklabel.h> 57 #include <sys/dkstat.h> 58 #include <sys/exec.h> 59 #include <sys/file.h> 60 #include <sys/ioctl.h> 61 #include <sys/malloc.h> 62 #include <sys/mount.h> 63 #include <sys/msgbuf.h> 64 #include <sys/pool.h> 65 #include <sys/proc.h> 66 #include <sys/resource.h> 67 #include <sys/resourcevar.h> 68 #include <sys/syscallargs.h> 69 #include <sys/tty.h> 70 #include <sys/unistd.h> 71 #include <sys/vnode.h> 72 #define __SYSCTL_PRIVATE 73 #include <sys/sysctl.h> 74 #include <sys/lock.h> 75 76 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 77 #include <sys/ipc.h> 78 #endif 79 #ifdef SYSVMSG 80 #include <sys/msg.h> 81 #endif 82 #ifdef SYSVSEM 83 #include <sys/sem.h> 84 #endif 85 #ifdef SYSVSHM 86 #include <sys/shm.h> 87 #endif 88 89 #include <dev/cons.h> 90 91 #if defined(DDB) 92 #include <ddb/ddbvar.h> 93 #endif 94 95 #define PTRTOINT64(foo) ((u_int64_t)(uintptr_t)(foo)) 96 97 static int sysctl_file __P((void *, size_t *)); 98 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 99 static int sysctl_sysvipc __P((int *, u_int, void *, size_t *)); 100 #endif 101 static int sysctl_msgbuf __P((void *, size_t *)); 102 static int sysctl_doeproc __P((int *, u_int, void *, size_t *)); 103 #ifdef MULTIPROCESSOR 104 static int sysctl_docptime __P((void *, size_t *, void *)); 105 static int sysctl_ncpus __P((void)); 106 #endif 107 static void fill_kproc2 __P((struct proc *, struct kinfo_proc2 *)); 108 static int sysctl_procargs __P((int *, u_int, void *, size_t *, struct proc *)); 109 #if NPTY > 0 110 static int sysctl_pty __P((void *, size_t *, void *, size_t)); 111 #endif 112 113 /* 114 * The `sysctl_memlock' is intended to keep too many processes from 115 * locking down memory by doing sysctls at once. Whether or not this 116 * is really a good idea to worry about it probably a subject of some 117 * debate. 118 */ 119 struct lock sysctl_memlock; 120 121 void 122 sysctl_init(void) 123 { 124 125 lockinit(&sysctl_memlock, PRIBIO|PCATCH, "sysctl", 0, 0); 126 } 127 128 int 129 sys___sysctl(p, v, retval) 130 struct proc *p; 131 void *v; 132 register_t *retval; 133 { 134 struct sys___sysctl_args /* { 135 syscallarg(int *) name; 136 syscallarg(u_int) namelen; 137 syscallarg(void *) old; 138 syscallarg(size_t *) oldlenp; 139 syscallarg(void *) new; 140 syscallarg(size_t) newlen; 141 } */ *uap = v; 142 int error; 143 size_t savelen = 0, oldlen = 0; 144 sysctlfn *fn; 145 int name[CTL_MAXNAME]; 146 size_t *oldlenp; 147 148 /* 149 * all top-level sysctl names are non-terminal 150 */ 151 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 152 return (EINVAL); 153 error = copyin(SCARG(uap, name), &name, 154 SCARG(uap, namelen) * sizeof(int)); 155 if (error) 156 return (error); 157 158 /* 159 * For all but CTL_PROC, must be root to change a value. 160 * For CTL_PROC, must be root, or owner of the proc (and not suid), 161 * this is checked in proc_sysctl() (once we know the targer proc). 162 */ 163 if (SCARG(uap, new) != NULL && name[0] != CTL_PROC && 164 (error = suser(p->p_ucred, &p->p_acflag))) 165 return error; 166 167 switch (name[0]) { 168 case CTL_KERN: 169 fn = kern_sysctl; 170 break; 171 case CTL_HW: 172 fn = hw_sysctl; 173 break; 174 case CTL_VM: 175 fn = uvm_sysctl; 176 break; 177 case CTL_NET: 178 fn = net_sysctl; 179 break; 180 case CTL_VFS: 181 fn = vfs_sysctl; 182 break; 183 case CTL_MACHDEP: 184 fn = cpu_sysctl; 185 break; 186 #ifdef DEBUG 187 case CTL_DEBUG: 188 fn = debug_sysctl; 189 break; 190 #endif 191 #ifdef DDB 192 case CTL_DDB: 193 fn = ddb_sysctl; 194 break; 195 #endif 196 case CTL_PROC: 197 fn = proc_sysctl; 198 break; 199 default: 200 return (EOPNOTSUPP); 201 } 202 203 /* 204 * XXX Hey, we wire `old', but what about `new'? 205 */ 206 207 oldlenp = SCARG(uap, oldlenp); 208 if (oldlenp) { 209 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 210 return (error); 211 oldlenp = &oldlen; 212 } 213 if (SCARG(uap, old) != NULL) { 214 error = lockmgr(&sysctl_memlock, LK_EXCLUSIVE, NULL); 215 if (error) 216 return (error); 217 error = uvm_vslock(p, SCARG(uap, old), oldlen, 218 VM_PROT_READ|VM_PROT_WRITE); 219 if (error) { 220 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 221 return error; 222 } 223 savelen = oldlen; 224 } 225 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), 226 oldlenp, SCARG(uap, new), SCARG(uap, newlen), p); 227 if (SCARG(uap, old) != NULL) { 228 uvm_vsunlock(p, SCARG(uap, old), savelen); 229 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 230 } 231 if (error) 232 return (error); 233 if (SCARG(uap, oldlenp)) 234 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 235 return (error); 236 } 237 238 /* 239 * Attributes stored in the kernel. 240 */ 241 char hostname[MAXHOSTNAMELEN]; 242 int hostnamelen; 243 244 char domainname[MAXHOSTNAMELEN]; 245 int domainnamelen; 246 247 long hostid; 248 249 #ifdef INSECURE 250 int securelevel = -1; 251 #else 252 int securelevel = 0; 253 #endif 254 255 #ifndef DEFCORENAME 256 #define DEFCORENAME "%n.core" 257 #endif 258 char defcorename[MAXPATHLEN] = DEFCORENAME; 259 int defcorenamelen = sizeof(DEFCORENAME); 260 261 extern int kern_logsigexit; 262 extern fixpt_t ccpu; 263 264 #ifndef MULTIPROCESSOR 265 #define sysctl_ncpus() 1 266 #endif 267 268 #ifdef MULTIPROCESSOR 269 270 #ifndef CPU_INFO_FOREACH 271 #define CPU_INFO_ITERATOR int 272 #define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL 273 #endif 274 275 static int 276 sysctl_docptime(oldp, oldlenp, newp) 277 void *oldp; 278 size_t *oldlenp; 279 void *newp; 280 { 281 u_int64_t cp_time[CPUSTATES]; 282 int i; 283 struct cpu_info *ci; 284 CPU_INFO_ITERATOR cii; 285 286 for (i=0; i<CPUSTATES; i++) 287 cp_time[i] = 0; 288 289 for (CPU_INFO_FOREACH(cii, ci)) { 290 for (i=0; i<CPUSTATES; i++) 291 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 292 } 293 return (sysctl_rdstruct(oldp, oldlenp, newp, 294 cp_time, sizeof(cp_time))); 295 } 296 297 static int 298 sysctl_ncpus(void) 299 { 300 struct cpu_info *ci; 301 CPU_INFO_ITERATOR cii; 302 303 int ncpus = 0; 304 for (CPU_INFO_FOREACH(cii, ci)) 305 ncpus++; 306 return ncpus; 307 } 308 309 #endif 310 311 /* 312 * kernel related system variables. 313 */ 314 int 315 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 316 int *name; 317 u_int namelen; 318 void *oldp; 319 size_t *oldlenp; 320 void *newp; 321 size_t newlen; 322 struct proc *p; 323 { 324 int error, level, inthostid; 325 int old_autonicetime; 326 int old_vnodes; 327 dev_t consdev; 328 329 /* All sysctl names at this level, except for a few, are terminal. */ 330 switch (name[0]) { 331 case KERN_PROC: 332 case KERN_PROC2: 333 case KERN_PROF: 334 case KERN_MBUF: 335 case KERN_PROC_ARGS: 336 case KERN_SYSVIPC_INFO: 337 /* Not terminal. */ 338 break; 339 default: 340 if (namelen != 1) 341 return (ENOTDIR); /* overloaded */ 342 } 343 344 switch (name[0]) { 345 case KERN_OSTYPE: 346 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 347 case KERN_OSRELEASE: 348 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 349 case KERN_OSREV: 350 return (sysctl_rdint(oldp, oldlenp, newp, __NetBSD_Version__)); 351 case KERN_VERSION: 352 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 353 case KERN_MAXVNODES: 354 old_vnodes = desiredvnodes; 355 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes); 356 if (old_vnodes > desiredvnodes) { 357 desiredvnodes = old_vnodes; 358 return (EINVAL); 359 } 360 return (error); 361 case KERN_MAXPROC: 362 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 363 case KERN_MAXFILES: 364 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 365 case KERN_ARGMAX: 366 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 367 case KERN_SECURELVL: 368 level = securelevel; 369 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 370 newp == NULL) 371 return (error); 372 if (level < securelevel && p->p_pid != 1) 373 return (EPERM); 374 securelevel = level; 375 return (0); 376 case KERN_HOSTNAME: 377 error = sysctl_string(oldp, oldlenp, newp, newlen, 378 hostname, sizeof(hostname)); 379 if (newp && !error) 380 hostnamelen = newlen; 381 return (error); 382 case KERN_DOMAINNAME: 383 error = sysctl_string(oldp, oldlenp, newp, newlen, 384 domainname, sizeof(domainname)); 385 if (newp && !error) 386 domainnamelen = newlen; 387 return (error); 388 case KERN_HOSTID: 389 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 390 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 391 hostid = inthostid; 392 return (error); 393 case KERN_CLOCKRATE: 394 return (sysctl_clockrate(oldp, oldlenp)); 395 case KERN_BOOTTIME: 396 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 397 sizeof(struct timeval))); 398 case KERN_VNODE: 399 return (sysctl_vnode(oldp, oldlenp, p)); 400 case KERN_PROC: 401 case KERN_PROC2: 402 return (sysctl_doeproc(name, namelen, oldp, oldlenp)); 403 case KERN_PROC_ARGS: 404 return (sysctl_procargs(name + 1, namelen - 1, 405 oldp, oldlenp, p)); 406 case KERN_FILE: 407 return (sysctl_file(oldp, oldlenp)); 408 #ifdef GPROF 409 case KERN_PROF: 410 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 411 newp, newlen)); 412 #endif 413 case KERN_POSIX1: 414 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 415 case KERN_NGROUPS: 416 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 417 case KERN_JOB_CONTROL: 418 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 419 case KERN_SAVED_IDS: 420 #ifdef _POSIX_SAVED_IDS 421 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 422 #else 423 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 424 #endif 425 case KERN_MAXPARTITIONS: 426 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 427 case KERN_RAWPARTITION: 428 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 429 #ifdef NTP 430 case KERN_NTPTIME: 431 return (sysctl_ntptime(oldp, oldlenp)); 432 #endif 433 case KERN_AUTONICETIME: 434 old_autonicetime = autonicetime; 435 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime); 436 if (autonicetime < 0) 437 autonicetime = old_autonicetime; 438 return (error); 439 case KERN_AUTONICEVAL: 440 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval); 441 if (autoniceval < PRIO_MIN) 442 autoniceval = PRIO_MIN; 443 if (autoniceval > PRIO_MAX) 444 autoniceval = PRIO_MAX; 445 return (error); 446 case KERN_RTC_OFFSET: 447 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset)); 448 case KERN_ROOT_DEVICE: 449 return (sysctl_rdstring(oldp, oldlenp, newp, 450 root_device->dv_xname)); 451 case KERN_MSGBUFSIZE: 452 /* 453 * deal with cases where the message buffer has 454 * become corrupted. 455 */ 456 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 457 msgbufenabled = 0; 458 return (ENXIO); 459 } 460 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 461 case KERN_FSYNC: 462 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 463 case KERN_SYSVMSG: 464 #ifdef SYSVMSG 465 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 466 #else 467 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 468 #endif 469 case KERN_SYSVSEM: 470 #ifdef SYSVSEM 471 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 472 #else 473 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 474 #endif 475 case KERN_SYSVSHM: 476 #ifdef SYSVSHM 477 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 478 #else 479 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 480 #endif 481 case KERN_DEFCORENAME: 482 if (newp && newlen < 1) 483 return (EINVAL); 484 error = sysctl_string(oldp, oldlenp, newp, newlen, 485 defcorename, sizeof(defcorename)); 486 if (newp && !error) 487 defcorenamelen = newlen; 488 return (error); 489 case KERN_SYNCHRONIZED_IO: 490 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 491 case KERN_IOV_MAX: 492 return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX)); 493 case KERN_MBUF: 494 return (sysctl_dombuf(name + 1, namelen - 1, oldp, oldlenp, 495 newp, newlen)); 496 case KERN_MAPPED_FILES: 497 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 498 case KERN_MEMLOCK: 499 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 500 case KERN_MEMLOCK_RANGE: 501 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 502 case KERN_MEMORY_PROTECTION: 503 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 504 case KERN_LOGIN_NAME_MAX: 505 return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX)); 506 case KERN_LOGSIGEXIT: 507 return (sysctl_int(oldp, oldlenp, newp, newlen, 508 &kern_logsigexit)); 509 case KERN_FSCALE: 510 return (sysctl_rdint(oldp, oldlenp, newp, FSCALE)); 511 case KERN_CCPU: 512 return (sysctl_rdint(oldp, oldlenp, newp, ccpu)); 513 case KERN_CP_TIME: 514 #ifndef MULTIPROCESSOR 515 return (sysctl_rdstruct(oldp, oldlenp, newp, 516 curcpu()->ci_schedstate.spc_cp_time, 517 sizeof(curcpu()->ci_schedstate.spc_cp_time))); 518 #else 519 return (sysctl_docptime(oldp, oldlenp, newp)); 520 #endif 521 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 522 case KERN_SYSVIPC_INFO: 523 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp)); 524 #endif 525 case KERN_MSGBUF: 526 return (sysctl_msgbuf(oldp, oldlenp)); 527 case KERN_CONSDEV: 528 if (cn_tab != NULL) 529 consdev = cn_tab->cn_dev; 530 else 531 consdev = NODEV; 532 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 533 sizeof consdev)); 534 #if NPTY > 0 535 case KERN_MAXPTYS: 536 return sysctl_pty(oldp, oldlenp, newp, newlen); 537 #endif 538 default: 539 return (EOPNOTSUPP); 540 } 541 /* NOTREACHED */ 542 } 543 544 /* 545 * hardware related system variables. 546 */ 547 int 548 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 549 int *name; 550 u_int namelen; 551 void *oldp; 552 size_t *oldlenp; 553 void *newp; 554 size_t newlen; 555 struct proc *p; 556 { 557 558 /* all sysctl names at this level are terminal */ 559 if (namelen != 1) 560 return (ENOTDIR); /* overloaded */ 561 562 switch (name[0]) { 563 case HW_MACHINE: 564 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 565 case HW_MACHINE_ARCH: 566 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch)); 567 case HW_MODEL: 568 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 569 case HW_NCPU: 570 return (sysctl_rdint(oldp, oldlenp, newp, sysctl_ncpus())); 571 case HW_BYTEORDER: 572 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 573 case HW_PHYSMEM: 574 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 575 case HW_USERMEM: 576 return (sysctl_rdint(oldp, oldlenp, newp, 577 ctob(physmem - uvmexp.wired))); 578 case HW_PAGESIZE: 579 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 580 case HW_ALIGNBYTES: 581 return (sysctl_rdint(oldp, oldlenp, newp, ALIGNBYTES)); 582 case HW_CNMAGIC: { 583 char magic[CNS_LEN]; 584 int error; 585 586 if (oldp) 587 cn_get_magic(magic, CNS_LEN); 588 error = sysctl_string(oldp, oldlenp, newp, newlen, 589 magic, sizeof(magic)); 590 if (newp && !error) { 591 error = cn_set_magic(magic); 592 } 593 return (error); 594 } 595 default: 596 return (EOPNOTSUPP); 597 } 598 /* NOTREACHED */ 599 } 600 601 #ifdef DEBUG 602 /* 603 * Debugging related system variables. 604 */ 605 struct ctldebug debug0, debug1, debug2, debug3, debug4; 606 struct ctldebug debug5, debug6, debug7, debug8, debug9; 607 struct ctldebug debug10, debug11, debug12, debug13, debug14; 608 struct ctldebug debug15, debug16, debug17, debug18, debug19; 609 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 610 &debug0, &debug1, &debug2, &debug3, &debug4, 611 &debug5, &debug6, &debug7, &debug8, &debug9, 612 &debug10, &debug11, &debug12, &debug13, &debug14, 613 &debug15, &debug16, &debug17, &debug18, &debug19, 614 }; 615 int 616 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 617 int *name; 618 u_int namelen; 619 void *oldp; 620 size_t *oldlenp; 621 void *newp; 622 size_t newlen; 623 struct proc *p; 624 { 625 struct ctldebug *cdp; 626 627 /* all sysctl names at this level are name and field */ 628 if (namelen != 2) 629 return (ENOTDIR); /* overloaded */ 630 cdp = debugvars[name[0]]; 631 if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0) 632 return (EOPNOTSUPP); 633 switch (name[1]) { 634 case CTL_DEBUG_NAME: 635 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 636 case CTL_DEBUG_VALUE: 637 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 638 default: 639 return (EOPNOTSUPP); 640 } 641 /* NOTREACHED */ 642 } 643 #endif /* DEBUG */ 644 645 int 646 proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 647 int *name; 648 u_int namelen; 649 void *oldp; 650 size_t *oldlenp; 651 void *newp; 652 size_t newlen; 653 struct proc *p; 654 { 655 struct proc *ptmp = NULL; 656 const struct proclist_desc *pd; 657 int error = 0; 658 struct rlimit alim; 659 struct plimit *newplim; 660 char *tmps = NULL; 661 int i, curlen, len; 662 663 if (namelen < 2) 664 return EINVAL; 665 666 if (name[0] == PROC_CURPROC) { 667 ptmp = p; 668 } else { 669 proclist_lock_read(); 670 for (pd = proclists; pd->pd_list != NULL; pd++) { 671 for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL; 672 ptmp = LIST_NEXT(ptmp, p_list)) { 673 /* Skip embryonic processes. */ 674 if (ptmp->p_stat == SIDL) 675 continue; 676 if (ptmp->p_pid == (pid_t)name[0]) 677 break; 678 } 679 if (ptmp != NULL) 680 break; 681 } 682 proclist_unlock_read(); 683 if (ptmp == NULL) 684 return(ESRCH); 685 if (p->p_ucred->cr_uid != 0) { 686 if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid || 687 p->p_cred->p_ruid != ptmp->p_cred->p_svuid) 688 return EPERM; 689 if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid) 690 return EPERM; /* sgid proc */ 691 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 692 if (p->p_ucred->cr_groups[i] == 693 ptmp->p_cred->p_rgid) 694 break; 695 } 696 if (i == p->p_ucred->cr_ngroups) 697 return EPERM; 698 } 699 } 700 if (name[1] == PROC_PID_CORENAME) { 701 if (namelen != 2) 702 return EINVAL; 703 /* 704 * Can't use sysctl_string() here because we may malloc a new 705 * area during the process, so we have to do it by hand. 706 */ 707 curlen = strlen(ptmp->p_limit->pl_corename) + 1; 708 if (oldlenp && *oldlenp < curlen) { 709 if (!oldp) 710 *oldlenp = curlen; 711 return (ENOMEM); 712 } 713 if (newp) { 714 if (securelevel > 2) 715 return EPERM; 716 if (newlen > MAXPATHLEN) 717 return ENAMETOOLONG; 718 tmps = malloc(newlen + 1, M_TEMP, M_WAITOK); 719 if (tmps == NULL) 720 return ENOMEM; 721 error = copyin(newp, tmps, newlen + 1); 722 tmps[newlen] = '\0'; 723 if (error) 724 goto cleanup; 725 /* Enforce to be either 'core' for end with '.core' */ 726 if (newlen < 4) { /* c.o.r.e */ 727 error = EINVAL; 728 goto cleanup; 729 } 730 len = newlen - 4; 731 if (len > 0) { 732 if (tmps[len - 1] != '.' && 733 tmps[len - 1] != '/') { 734 error = EINVAL; 735 goto cleanup; 736 } 737 } 738 if (strcmp(&tmps[len], "core") != 0) { 739 error = EINVAL; 740 goto cleanup; 741 } 742 } 743 if (oldp && oldlenp) { 744 *oldlenp = curlen; 745 error = copyout(ptmp->p_limit->pl_corename, oldp, 746 curlen); 747 } 748 if (newp && error == 0) { 749 /* if the 2 strings are identical, don't limcopy() */ 750 if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) { 751 error = 0; 752 goto cleanup; 753 } 754 if (ptmp->p_limit->p_refcnt > 1 && 755 (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) { 756 newplim = limcopy(ptmp->p_limit); 757 limfree(ptmp->p_limit); 758 ptmp->p_limit = newplim; 759 } else if (ptmp->p_limit->pl_corename != defcorename) { 760 free(ptmp->p_limit->pl_corename, M_TEMP); 761 } 762 ptmp->p_limit->pl_corename = tmps; 763 return (0); 764 } 765 cleanup: 766 if (tmps) 767 free(tmps, M_TEMP); 768 return (error); 769 } 770 if (name[1] == PROC_PID_LIMIT) { 771 if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID) 772 return EINVAL; 773 memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim)); 774 if (name[3] == PROC_PID_LIMIT_TYPE_HARD) 775 error = sysctl_quad(oldp, oldlenp, newp, newlen, 776 &alim.rlim_max); 777 else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT) 778 error = sysctl_quad(oldp, oldlenp, newp, newlen, 779 &alim.rlim_cur); 780 else 781 error = EINVAL; 782 783 if (error) 784 return error; 785 786 if (newp) 787 error = dosetrlimit(ptmp, p->p_cred, 788 name[2] - 1, &alim); 789 return error; 790 } 791 return (EINVAL); 792 } 793 794 /* 795 * Convenience macros. 796 */ 797 798 #define SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, len) \ 799 if (oldlenp) { \ 800 if (!oldp) \ 801 *oldlenp = len; \ 802 else { \ 803 if (*oldlenp < len) \ 804 return(ENOMEM); \ 805 *oldlenp = len; \ 806 error = copyout((caddr_t)valp, oldp, len); \ 807 } \ 808 } 809 810 #define SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, typ) \ 811 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, sizeof(typ)) 812 813 #define SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) \ 814 if (newp && newlen != len) \ 815 return (EINVAL); 816 817 #define SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, typ) \ 818 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, sizeof(typ)) 819 820 #define SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, len) \ 821 if (error == 0 && newp) \ 822 error = copyin(newp, valp, len); 823 824 #define SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, typ) \ 825 SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, sizeof(typ)) 826 827 #define SYSCTL_STRING_CORE(oldp, oldlenp, str) \ 828 if (oldlenp) { \ 829 len = strlen(str) + 1; \ 830 if (!oldp) \ 831 *oldlenp = len; \ 832 else { \ 833 if (*oldlenp < len) { \ 834 err2 = ENOMEM; \ 835 len = *oldlenp; \ 836 } else \ 837 *oldlenp = len; \ 838 error = copyout(str, oldp, len);\ 839 if (error == 0) \ 840 error = err2; \ 841 } \ 842 } 843 844 /* 845 * Validate parameters and get old / set new parameters 846 * for an integer-valued sysctl function. 847 */ 848 int 849 sysctl_int(oldp, oldlenp, newp, newlen, valp) 850 void *oldp; 851 size_t *oldlenp; 852 void *newp; 853 size_t newlen; 854 int *valp; 855 { 856 int error = 0; 857 858 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 859 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, int) 860 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, int) 861 862 return (error); 863 } 864 865 866 /* 867 * As above, but read-only. 868 */ 869 int 870 sysctl_rdint(oldp, oldlenp, newp, val) 871 void *oldp; 872 size_t *oldlenp; 873 void *newp; 874 int val; 875 { 876 int error = 0; 877 878 if (newp) 879 return (EPERM); 880 881 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, int) 882 883 return (error); 884 } 885 886 /* 887 * Validate parameters and get old / set new parameters 888 * for an quad-valued sysctl function. 889 */ 890 int 891 sysctl_quad(oldp, oldlenp, newp, newlen, valp) 892 void *oldp; 893 size_t *oldlenp; 894 void *newp; 895 size_t newlen; 896 quad_t *valp; 897 { 898 int error = 0; 899 900 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, quad_t) 901 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, quad_t) 902 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, quad_t) 903 904 return (error); 905 } 906 907 /* 908 * As above, but read-only. 909 */ 910 int 911 sysctl_rdquad(oldp, oldlenp, newp, val) 912 void *oldp; 913 size_t *oldlenp; 914 void *newp; 915 quad_t val; 916 { 917 int error = 0; 918 919 if (newp) 920 return (EPERM); 921 922 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, quad_t) 923 924 return (error); 925 } 926 927 /* 928 * Validate parameters and get old / set new parameters 929 * for a string-valued sysctl function. 930 */ 931 int 932 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 933 void *oldp; 934 size_t *oldlenp; 935 void *newp; 936 size_t newlen; 937 char *str; 938 int maxlen; 939 { 940 int len, error = 0, err2 = 0; 941 942 if (newp && newlen >= maxlen) 943 return (EINVAL); 944 945 SYSCTL_STRING_CORE(oldp, oldlenp, str); 946 947 if (error == 0 && newp) { 948 error = copyin(newp, str, newlen); 949 str[newlen] = 0; 950 } 951 return (error); 952 } 953 954 /* 955 * As above, but read-only. 956 */ 957 int 958 sysctl_rdstring(oldp, oldlenp, newp, str) 959 void *oldp; 960 size_t *oldlenp; 961 void *newp; 962 const char *str; 963 { 964 int len, error = 0, err2 = 0; 965 966 if (newp) 967 return (EPERM); 968 969 SYSCTL_STRING_CORE(oldp, oldlenp, str); 970 971 return (error); 972 } 973 974 /* 975 * Validate parameters and get old / set new parameters 976 * for a structure oriented sysctl function. 977 */ 978 int 979 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 980 void *oldp; 981 size_t *oldlenp; 982 void *newp; 983 size_t newlen; 984 void *sp; 985 int len; 986 { 987 int error = 0; 988 989 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) 990 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 991 SYSCTL_SCALAR_NEWPCOP_LEN(newp, sp, len) 992 993 return (error); 994 } 995 996 /* 997 * Validate parameters and get old parameters 998 * for a structure oriented sysctl function. 999 */ 1000 int 1001 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 1002 void *oldp; 1003 size_t *oldlenp; 1004 void *newp; 1005 const void *sp; 1006 int len; 1007 { 1008 int error = 0; 1009 1010 if (newp) 1011 return (EPERM); 1012 1013 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 1014 1015 return (error); 1016 } 1017 1018 /* 1019 * As above, but can return a truncated result. 1020 */ 1021 int 1022 sysctl_rdminstruct(oldp, oldlenp, newp, sp, len) 1023 void *oldp; 1024 size_t *oldlenp; 1025 void *newp; 1026 const void *sp; 1027 int len; 1028 { 1029 int error = 0; 1030 1031 if (newp) 1032 return (EPERM); 1033 1034 len = min(*oldlenp, len); 1035 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 1036 1037 return (error); 1038 } 1039 1040 /* 1041 * Get file structures. 1042 */ 1043 static int 1044 sysctl_file(vwhere, sizep) 1045 void *vwhere; 1046 size_t *sizep; 1047 { 1048 int buflen, error; 1049 struct file *fp; 1050 char *start, *where; 1051 1052 start = where = vwhere; 1053 buflen = *sizep; 1054 if (where == NULL) { 1055 /* 1056 * overestimate by 10 files 1057 */ 1058 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 1059 return (0); 1060 } 1061 1062 /* 1063 * first copyout filehead 1064 */ 1065 if (buflen < sizeof(filehead)) { 1066 *sizep = 0; 1067 return (0); 1068 } 1069 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 1070 if (error) 1071 return (error); 1072 buflen -= sizeof(filehead); 1073 where += sizeof(filehead); 1074 1075 /* 1076 * followed by an array of file structures 1077 */ 1078 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { 1079 if (buflen < sizeof(struct file)) { 1080 *sizep = where - start; 1081 return (ENOMEM); 1082 } 1083 error = copyout((caddr_t)fp, where, sizeof(struct file)); 1084 if (error) 1085 return (error); 1086 buflen -= sizeof(struct file); 1087 where += sizeof(struct file); 1088 } 1089 *sizep = where - start; 1090 return (0); 1091 } 1092 1093 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1094 #define FILL_PERM(src, dst) do { \ 1095 (dst)._key = (src)._key; \ 1096 (dst).uid = (src).uid; \ 1097 (dst).gid = (src).gid; \ 1098 (dst).cuid = (src).cuid; \ 1099 (dst).cgid = (src).cgid; \ 1100 (dst).mode = (src).mode; \ 1101 (dst)._seq = (src)._seq; \ 1102 } while (0); 1103 #define FILL_MSG(src, dst) do { \ 1104 FILL_PERM((src).msg_perm, (dst).msg_perm); \ 1105 (dst).msg_qnum = (src).msg_qnum; \ 1106 (dst).msg_qbytes = (src).msg_qbytes; \ 1107 (dst)._msg_cbytes = (src)._msg_cbytes; \ 1108 (dst).msg_lspid = (src).msg_lspid; \ 1109 (dst).msg_lrpid = (src).msg_lrpid; \ 1110 (dst).msg_stime = (src).msg_stime; \ 1111 (dst).msg_rtime = (src).msg_rtime; \ 1112 (dst).msg_ctime = (src).msg_ctime; \ 1113 } while (0) 1114 #define FILL_SEM(src, dst) do { \ 1115 FILL_PERM((src).sem_perm, (dst).sem_perm); \ 1116 (dst).sem_nsems = (src).sem_nsems; \ 1117 (dst).sem_otime = (src).sem_otime; \ 1118 (dst).sem_ctime = (src).sem_ctime; \ 1119 } while (0) 1120 #define FILL_SHM(src, dst) do { \ 1121 FILL_PERM((src).shm_perm, (dst).shm_perm); \ 1122 (dst).shm_segsz = (src).shm_segsz; \ 1123 (dst).shm_lpid = (src).shm_lpid; \ 1124 (dst).shm_cpid = (src).shm_cpid; \ 1125 (dst).shm_atime = (src).shm_atime; \ 1126 (dst).shm_dtime = (src).shm_dtime; \ 1127 (dst).shm_ctime = (src).shm_ctime; \ 1128 (dst).shm_nattch = (src).shm_nattch; \ 1129 } while (0) 1130 1131 static int 1132 sysctl_sysvipc(name, namelen, where, sizep) 1133 int *name; 1134 u_int namelen; 1135 void *where; 1136 size_t *sizep; 1137 { 1138 #ifdef SYSVMSG 1139 struct msg_sysctl_info *msgsi; 1140 #endif 1141 #ifdef SYSVSEM 1142 struct sem_sysctl_info *semsi; 1143 #endif 1144 #ifdef SYSVSHM 1145 struct shm_sysctl_info *shmsi; 1146 #endif 1147 size_t infosize, dssize, tsize, buflen; 1148 void *buf = NULL, *buf2; 1149 char *start; 1150 int32_t nds; 1151 int i, error, ret; 1152 1153 if (namelen != 1) 1154 return (EINVAL); 1155 1156 start = where; 1157 buflen = *sizep; 1158 1159 switch (*name) { 1160 case KERN_SYSVIPC_MSG_INFO: 1161 #ifdef SYSVMSG 1162 infosize = sizeof(msgsi->msginfo); 1163 nds = msginfo.msgmni; 1164 dssize = sizeof(msgsi->msgids[0]); 1165 break; 1166 #else 1167 return (EINVAL); 1168 #endif 1169 case KERN_SYSVIPC_SEM_INFO: 1170 #ifdef SYSVSEM 1171 infosize = sizeof(semsi->seminfo); 1172 nds = seminfo.semmni; 1173 dssize = sizeof(semsi->semids[0]); 1174 break; 1175 #else 1176 return (EINVAL); 1177 #endif 1178 case KERN_SYSVIPC_SHM_INFO: 1179 #ifdef SYSVSHM 1180 infosize = sizeof(shmsi->shminfo); 1181 nds = shminfo.shmmni; 1182 dssize = sizeof(shmsi->shmids[0]); 1183 break; 1184 #else 1185 return (EINVAL); 1186 #endif 1187 default: 1188 return (EINVAL); 1189 } 1190 /* 1191 * Round infosize to 64 bit boundary if requesting more than just 1192 * the info structure or getting the total data size. 1193 */ 1194 if (where == NULL || *sizep > infosize) 1195 infosize = ((infosize + 7) / 8) * 8; 1196 tsize = infosize + nds * dssize; 1197 1198 /* Return just the total size required. */ 1199 if (where == NULL) { 1200 *sizep = tsize; 1201 return (0); 1202 } 1203 1204 /* Not enough room for even the info struct. */ 1205 if (buflen < infosize) { 1206 *sizep = 0; 1207 return (ENOMEM); 1208 } 1209 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK); 1210 memset(buf, 0, min(tsize, buflen)); 1211 1212 switch (*name) { 1213 #ifdef SYSVMSG 1214 case KERN_SYSVIPC_MSG_INFO: 1215 msgsi = (struct msg_sysctl_info *)buf; 1216 buf2 = &msgsi->msgids[0]; 1217 msgsi->msginfo = msginfo; 1218 break; 1219 #endif 1220 #ifdef SYSVSEM 1221 case KERN_SYSVIPC_SEM_INFO: 1222 semsi = (struct sem_sysctl_info *)buf; 1223 buf2 = &semsi->semids[0]; 1224 semsi->seminfo = seminfo; 1225 break; 1226 #endif 1227 #ifdef SYSVSHM 1228 case KERN_SYSVIPC_SHM_INFO: 1229 shmsi = (struct shm_sysctl_info *)buf; 1230 buf2 = &shmsi->shmids[0]; 1231 shmsi->shminfo = shminfo; 1232 break; 1233 #endif 1234 } 1235 buflen -= infosize; 1236 1237 ret = 0; 1238 if (buflen > 0) { 1239 /* Fill in the IPC data structures. */ 1240 for (i = 0; i < nds; i++) { 1241 if (buflen < dssize) { 1242 ret = ENOMEM; 1243 break; 1244 } 1245 switch (*name) { 1246 #ifdef SYSVMSG 1247 case KERN_SYSVIPC_MSG_INFO: 1248 FILL_MSG(msqids[i], msgsi->msgids[i]); 1249 break; 1250 #endif 1251 #ifdef SYSVSEM 1252 case KERN_SYSVIPC_SEM_INFO: 1253 FILL_SEM(sema[i], semsi->semids[i]); 1254 break; 1255 #endif 1256 #ifdef SYSVSHM 1257 case KERN_SYSVIPC_SHM_INFO: 1258 FILL_SHM(shmsegs[i], shmsi->shmids[i]); 1259 break; 1260 #endif 1261 } 1262 buflen -= dssize; 1263 } 1264 } 1265 *sizep -= buflen; 1266 error = copyout(buf, start, *sizep); 1267 /* If copyout succeeded, use return code set earlier. */ 1268 if (error == 0) 1269 error = ret; 1270 if (buf) 1271 free(buf, M_TEMP); 1272 return (error); 1273 } 1274 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1275 1276 static int 1277 sysctl_msgbuf(vwhere, sizep) 1278 void *vwhere; 1279 size_t *sizep; 1280 { 1281 char *where = vwhere; 1282 size_t len, maxlen = *sizep; 1283 long beg, end; 1284 int error; 1285 1286 /* 1287 * deal with cases where the message buffer has 1288 * become corrupted. 1289 */ 1290 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 1291 msgbufenabled = 0; 1292 return (ENXIO); 1293 } 1294 1295 if (where == NULL) { 1296 /* always return full buffer size */ 1297 *sizep = msgbufp->msg_bufs; 1298 return (0); 1299 } 1300 1301 error = 0; 1302 maxlen = min(msgbufp->msg_bufs, maxlen); 1303 1304 /* 1305 * First, copy from the write pointer to the end of 1306 * message buffer. 1307 */ 1308 beg = msgbufp->msg_bufx; 1309 end = msgbufp->msg_bufs; 1310 while (maxlen > 0) { 1311 len = min(end - beg, maxlen); 1312 if (len == 0) 1313 break; 1314 error = copyout(&msgbufp->msg_bufc[beg], where, len); 1315 if (error) 1316 break; 1317 where += len; 1318 maxlen -= len; 1319 1320 /* 1321 * ... then, copy from the beginning of message buffer to 1322 * the write pointer. 1323 */ 1324 beg = 0; 1325 end = msgbufp->msg_bufx; 1326 } 1327 return (error); 1328 } 1329 1330 /* 1331 * try over estimating by 5 procs 1332 */ 1333 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 1334 1335 static int 1336 sysctl_doeproc(name, namelen, vwhere, sizep) 1337 int *name; 1338 u_int namelen; 1339 void *vwhere; 1340 size_t *sizep; 1341 { 1342 struct eproc eproc; 1343 struct kinfo_proc2 kproc2; 1344 struct kinfo_proc *dp; 1345 struct proc *p; 1346 const struct proclist_desc *pd; 1347 char *where, *dp2; 1348 int type, op, arg, elem_size, elem_count; 1349 int buflen, needed, error; 1350 1351 dp = vwhere; 1352 dp2 = where = vwhere; 1353 buflen = where != NULL ? *sizep : 0; 1354 error = needed = 0; 1355 type = name[0]; 1356 1357 if (type == KERN_PROC) { 1358 if (namelen != 3 && !(namelen == 2 && name[1] == KERN_PROC_ALL)) 1359 return (EINVAL); 1360 op = name[1]; 1361 if (op != KERN_PROC_ALL) 1362 arg = name[2]; 1363 } else { 1364 if (namelen != 5) 1365 return (EINVAL); 1366 op = name[1]; 1367 arg = name[2]; 1368 elem_size = name[3]; 1369 elem_count = name[4]; 1370 } 1371 1372 proclist_lock_read(); 1373 1374 pd = proclists; 1375 again: 1376 for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) { 1377 /* 1378 * Skip embryonic processes. 1379 */ 1380 if (p->p_stat == SIDL) 1381 continue; 1382 /* 1383 * TODO - make more efficient (see notes below). 1384 * do by session. 1385 */ 1386 switch (op) { 1387 1388 case KERN_PROC_PID: 1389 /* could do this with just a lookup */ 1390 if (p->p_pid != (pid_t)arg) 1391 continue; 1392 break; 1393 1394 case KERN_PROC_PGRP: 1395 /* could do this by traversing pgrp */ 1396 if (p->p_pgrp->pg_id != (pid_t)arg) 1397 continue; 1398 break; 1399 1400 case KERN_PROC_SESSION: 1401 if (p->p_session->s_sid != (pid_t)arg) 1402 continue; 1403 break; 1404 1405 case KERN_PROC_TTY: 1406 if (arg == KERN_PROC_TTY_REVOKE) { 1407 if ((p->p_flag & P_CONTROLT) == 0 || 1408 p->p_session->s_ttyp == NULL || 1409 p->p_session->s_ttyvp != NULL) 1410 continue; 1411 } else if ((p->p_flag & P_CONTROLT) == 0 || 1412 p->p_session->s_ttyp == NULL) { 1413 if ((dev_t)arg != KERN_PROC_TTY_NODEV) 1414 continue; 1415 } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg) 1416 continue; 1417 break; 1418 1419 case KERN_PROC_UID: 1420 if (p->p_ucred->cr_uid != (uid_t)arg) 1421 continue; 1422 break; 1423 1424 case KERN_PROC_RUID: 1425 if (p->p_cred->p_ruid != (uid_t)arg) 1426 continue; 1427 break; 1428 1429 case KERN_PROC_GID: 1430 if (p->p_ucred->cr_gid != (uid_t)arg) 1431 continue; 1432 break; 1433 1434 case KERN_PROC_RGID: 1435 if (p->p_cred->p_rgid != (uid_t)arg) 1436 continue; 1437 break; 1438 1439 case KERN_PROC_ALL: 1440 /* allow everything */ 1441 break; 1442 1443 default: 1444 error = EINVAL; 1445 goto cleanup; 1446 } 1447 if (type == KERN_PROC) { 1448 if (buflen >= sizeof(struct kinfo_proc)) { 1449 fill_eproc(p, &eproc); 1450 error = copyout((caddr_t)p, &dp->kp_proc, 1451 sizeof(struct proc)); 1452 if (error) 1453 goto cleanup; 1454 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1455 sizeof(eproc)); 1456 if (error) 1457 goto cleanup; 1458 dp++; 1459 buflen -= sizeof(struct kinfo_proc); 1460 } 1461 needed += sizeof(struct kinfo_proc); 1462 } else { /* KERN_PROC2 */ 1463 if (buflen >= elem_size && elem_count > 0) { 1464 fill_kproc2(p, &kproc2); 1465 /* 1466 * Copy out elem_size, but not larger than 1467 * the size of a struct kinfo_proc2. 1468 */ 1469 error = copyout(&kproc2, dp2, 1470 min(sizeof(kproc2), elem_size)); 1471 if (error) 1472 goto cleanup; 1473 dp2 += elem_size; 1474 buflen -= elem_size; 1475 elem_count--; 1476 } 1477 needed += elem_size; 1478 } 1479 } 1480 pd++; 1481 if (pd->pd_list != NULL) 1482 goto again; 1483 proclist_unlock_read(); 1484 1485 if (where != NULL) { 1486 if (type == KERN_PROC) 1487 *sizep = (caddr_t)dp - where; 1488 else 1489 *sizep = dp2 - where; 1490 if (needed > *sizep) 1491 return (ENOMEM); 1492 } else { 1493 needed += KERN_PROCSLOP; 1494 *sizep = needed; 1495 } 1496 return (0); 1497 cleanup: 1498 proclist_unlock_read(); 1499 return (error); 1500 } 1501 1502 /* 1503 * Fill in an eproc structure for the specified process. 1504 */ 1505 void 1506 fill_eproc(p, ep) 1507 struct proc *p; 1508 struct eproc *ep; 1509 { 1510 struct tty *tp; 1511 1512 ep->e_paddr = p; 1513 ep->e_sess = p->p_session; 1514 ep->e_pcred = *p->p_cred; 1515 ep->e_ucred = *p->p_ucred; 1516 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1517 ep->e_vm.vm_rssize = 0; 1518 ep->e_vm.vm_tsize = 0; 1519 ep->e_vm.vm_dsize = 0; 1520 ep->e_vm.vm_ssize = 0; 1521 /* ep->e_vm.vm_pmap = XXX; */ 1522 } else { 1523 struct vmspace *vm = p->p_vmspace; 1524 1525 ep->e_vm.vm_rssize = vm_resident_count(vm); 1526 ep->e_vm.vm_tsize = vm->vm_tsize; 1527 ep->e_vm.vm_dsize = vm->vm_dsize; 1528 ep->e_vm.vm_ssize = vm->vm_ssize; 1529 } 1530 if (p->p_pptr) 1531 ep->e_ppid = p->p_pptr->p_pid; 1532 else 1533 ep->e_ppid = 0; 1534 ep->e_pgid = p->p_pgrp->pg_id; 1535 ep->e_sid = ep->e_sess->s_sid; 1536 ep->e_jobc = p->p_pgrp->pg_jobc; 1537 if ((p->p_flag & P_CONTROLT) && 1538 (tp = ep->e_sess->s_ttyp)) { 1539 ep->e_tdev = tp->t_dev; 1540 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1541 ep->e_tsess = tp->t_session; 1542 } else 1543 ep->e_tdev = NODEV; 1544 if (p->p_wmesg) 1545 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1546 ep->e_xsize = ep->e_xrssize = 0; 1547 ep->e_xccount = ep->e_xswrss = 0; 1548 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1549 if (SESS_LEADER(p)) 1550 ep->e_flag |= EPROC_SLEADER; 1551 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 1552 } 1553 1554 /* 1555 * Fill in an eproc structure for the specified process. 1556 */ 1557 static void 1558 fill_kproc2(p, ki) 1559 struct proc *p; 1560 struct kinfo_proc2 *ki; 1561 { 1562 struct tty *tp; 1563 1564 memset(ki, 0, sizeof(*ki)); 1565 1566 ki->p_forw = PTRTOINT64(p->p_forw); 1567 ki->p_back = PTRTOINT64(p->p_back); 1568 ki->p_paddr = PTRTOINT64(p); 1569 1570 ki->p_addr = PTRTOINT64(p->p_addr); 1571 ki->p_fd = PTRTOINT64(p->p_fd); 1572 ki->p_cwdi = PTRTOINT64(p->p_cwdi); 1573 ki->p_stats = PTRTOINT64(p->p_stats); 1574 ki->p_limit = PTRTOINT64(p->p_limit); 1575 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 1576 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 1577 ki->p_sess = PTRTOINT64(p->p_session); 1578 ki->p_tsess = 0; /* may be changed if controlling tty below */ 1579 ki->p_ru = PTRTOINT64(p->p_ru); 1580 1581 ki->p_eflag = 0; 1582 ki->p_exitsig = p->p_exitsig; 1583 ki->p_flag = p->p_flag; 1584 1585 ki->p_pid = p->p_pid; 1586 if (p->p_pptr) 1587 ki->p_ppid = p->p_pptr->p_pid; 1588 else 1589 ki->p_ppid = 0; 1590 ki->p_sid = p->p_session->s_sid; 1591 ki->p__pgid = p->p_pgrp->pg_id; 1592 1593 ki->p_tpgid = NO_PID; /* may be changed if controlling tty below */ 1594 1595 ki->p_uid = p->p_ucred->cr_uid; 1596 ki->p_ruid = p->p_cred->p_ruid; 1597 ki->p_gid = p->p_ucred->cr_gid; 1598 ki->p_rgid = p->p_cred->p_rgid; 1599 1600 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 1601 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 1602 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 1603 1604 ki->p_jobc = p->p_pgrp->pg_jobc; 1605 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 1606 ki->p_tdev = tp->t_dev; 1607 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1608 ki->p_tsess = PTRTOINT64(tp->t_session); 1609 } else { 1610 ki->p_tdev = NODEV; 1611 } 1612 1613 ki->p_estcpu = p->p_estcpu; 1614 ki->p_rtime_sec = p->p_rtime.tv_sec; 1615 ki->p_rtime_usec = p->p_rtime.tv_usec; 1616 ki->p_cpticks = p->p_cpticks; 1617 ki->p_pctcpu = p->p_pctcpu; 1618 ki->p_swtime = p->p_swtime; 1619 ki->p_slptime = p->p_slptime; 1620 if (p->p_stat == SONPROC) { 1621 KDASSERT(p->p_cpu != NULL); 1622 ki->p_schedflags = p->p_cpu->ci_schedstate.spc_flags; 1623 } else 1624 ki->p_schedflags = 0; 1625 1626 ki->p_uticks = p->p_uticks; 1627 ki->p_sticks = p->p_sticks; 1628 ki->p_iticks = p->p_iticks; 1629 1630 ki->p_tracep = PTRTOINT64(p->p_tracep); 1631 ki->p_traceflag = p->p_traceflag; 1632 1633 ki->p_holdcnt = p->p_holdcnt; 1634 1635 memcpy(&ki->p_siglist, &p->p_sigctx.ps_siglist, sizeof(ki_sigset_t)); 1636 memcpy(&ki->p_sigmask, &p->p_sigctx.ps_sigmask, sizeof(ki_sigset_t)); 1637 memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t)); 1638 memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t)); 1639 1640 ki->p_stat = p->p_stat; 1641 ki->p_priority = p->p_priority; 1642 ki->p_usrpri = p->p_usrpri; 1643 ki->p_nice = p->p_nice; 1644 1645 ki->p_xstat = p->p_xstat; 1646 ki->p_acflag = p->p_acflag; 1647 1648 strncpy(ki->p_comm, p->p_comm, 1649 min(sizeof(ki->p_comm), sizeof(p->p_comm))); 1650 1651 if (p->p_wmesg) 1652 strncpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg)); 1653 ki->p_wchan = PTRTOINT64(p->p_wchan); 1654 1655 strncpy(ki->p_login, p->p_session->s_login, sizeof(ki->p_login)); 1656 1657 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1658 ki->p_vm_rssize = 0; 1659 ki->p_vm_tsize = 0; 1660 ki->p_vm_dsize = 0; 1661 ki->p_vm_ssize = 0; 1662 } else { 1663 struct vmspace *vm = p->p_vmspace; 1664 1665 ki->p_vm_rssize = vm_resident_count(vm); 1666 ki->p_vm_tsize = vm->vm_tsize; 1667 ki->p_vm_dsize = vm->vm_dsize; 1668 ki->p_vm_ssize = vm->vm_ssize; 1669 } 1670 1671 if (p->p_session->s_ttyvp) 1672 ki->p_eflag |= EPROC_CTTY; 1673 if (SESS_LEADER(p)) 1674 ki->p_eflag |= EPROC_SLEADER; 1675 1676 /* XXX Is this double check necessary? */ 1677 if ((p->p_flag & P_INMEM) == 0 || P_ZOMBIE(p)) { 1678 ki->p_uvalid = 0; 1679 } else { 1680 ki->p_uvalid = 1; 1681 1682 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 1683 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 1684 1685 ki->p_uutime_sec = p->p_stats->p_ru.ru_utime.tv_sec; 1686 ki->p_uutime_usec = p->p_stats->p_ru.ru_utime.tv_usec; 1687 ki->p_ustime_sec = p->p_stats->p_ru.ru_stime.tv_sec; 1688 ki->p_ustime_usec = p->p_stats->p_ru.ru_stime.tv_usec; 1689 1690 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 1691 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 1692 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 1693 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 1694 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 1695 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 1696 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 1697 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 1698 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 1699 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 1700 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 1701 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 1702 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 1703 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 1704 1705 ki->p_uctime_sec = p->p_stats->p_cru.ru_utime.tv_sec + 1706 p->p_stats->p_cru.ru_stime.tv_sec; 1707 ki->p_uctime_usec = p->p_stats->p_cru.ru_utime.tv_usec + 1708 p->p_stats->p_cru.ru_stime.tv_usec; 1709 } 1710 #ifdef MULTIPROCESSOR 1711 if (p->p_cpu != NULL) 1712 ki->p_cpuid = p->p_cpu->ci_cpuid; 1713 else 1714 #endif 1715 ki->p_cpuid = KI_NOCPU; 1716 } 1717 1718 int 1719 sysctl_procargs(name, namelen, where, sizep, up) 1720 int *name; 1721 u_int namelen; 1722 void *where; 1723 size_t *sizep; 1724 struct proc *up; 1725 { 1726 struct ps_strings pss; 1727 struct proc *p; 1728 size_t len, upper_bound, xlen; 1729 struct uio auio; 1730 struct iovec aiov; 1731 vaddr_t argv; 1732 pid_t pid; 1733 int nargv, type, error, i; 1734 char *arg; 1735 char *tmp; 1736 1737 if (namelen != 2) 1738 return (EINVAL); 1739 pid = name[0]; 1740 type = name[1]; 1741 1742 switch (type) { 1743 case KERN_PROC_ARGV: 1744 case KERN_PROC_NARGV: 1745 case KERN_PROC_ENV: 1746 case KERN_PROC_NENV: 1747 /* ok */ 1748 break; 1749 default: 1750 return (EINVAL); 1751 } 1752 1753 /* check pid */ 1754 if ((p = pfind(pid)) == NULL) 1755 return (EINVAL); 1756 1757 /* only root or same user change look at the environment */ 1758 if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) { 1759 if (up->p_ucred->cr_uid != 0) { 1760 if (up->p_cred->p_ruid != p->p_cred->p_ruid || 1761 up->p_cred->p_ruid != p->p_cred->p_svuid) 1762 return (EPERM); 1763 } 1764 } 1765 1766 if (sizep != NULL && where == NULL) { 1767 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) 1768 *sizep = sizeof (int); 1769 else 1770 *sizep = ARG_MAX; /* XXX XXX XXX */ 1771 return (0); 1772 } 1773 if (where == NULL || sizep == NULL) 1774 return (EINVAL); 1775 1776 /* 1777 * Zombies don't have a stack, so we can't read their psstrings. 1778 * System processes also don't have a user stack. 1779 */ 1780 if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) 1781 return (EINVAL); 1782 1783 /* 1784 * Lock the process down in memory. 1785 */ 1786 /* XXXCDC: how should locking work here? */ 1787 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 1788 return (EFAULT); 1789 p->p_vmspace->vm_refcnt++; /* XXX */ 1790 1791 /* 1792 * Allocate a temporary buffer to hold the arguments. 1793 */ 1794 arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1795 1796 /* 1797 * Read in the ps_strings structure. 1798 */ 1799 aiov.iov_base = &pss; 1800 aiov.iov_len = sizeof(pss); 1801 auio.uio_iov = &aiov; 1802 auio.uio_iovcnt = 1; 1803 auio.uio_offset = (vaddr_t)p->p_psstr; 1804 auio.uio_resid = sizeof(pss); 1805 auio.uio_segflg = UIO_SYSSPACE; 1806 auio.uio_rw = UIO_READ; 1807 auio.uio_procp = NULL; 1808 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1809 if (error) 1810 goto done; 1811 1812 if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) 1813 memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv)); 1814 else 1815 memcpy(&nargv, (char *)&pss + p->p_psnenv, sizeof(nargv)); 1816 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) { 1817 error = copyout(&nargv, where, sizeof(nargv)); 1818 *sizep = sizeof(nargv); 1819 goto done; 1820 } 1821 /* 1822 * Now read the address of the argument vector. 1823 */ 1824 switch (type) { 1825 case KERN_PROC_ARGV: 1826 /* XXX compat32 stuff here */ 1827 memcpy(&tmp, (char *)&pss + p->p_psargv, sizeof(tmp)); 1828 break; 1829 case KERN_PROC_ENV: 1830 memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp)); 1831 break; 1832 default: 1833 return (EINVAL); 1834 } 1835 auio.uio_offset = (off_t)(long)tmp; 1836 aiov.iov_base = &argv; 1837 aiov.iov_len = sizeof(argv); 1838 auio.uio_iov = &aiov; 1839 auio.uio_iovcnt = 1; 1840 auio.uio_resid = sizeof(argv); 1841 auio.uio_segflg = UIO_SYSSPACE; 1842 auio.uio_rw = UIO_READ; 1843 auio.uio_procp = NULL; 1844 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1845 if (error) 1846 goto done; 1847 1848 /* 1849 * Now copy in the actual argument vector, one page at a time, 1850 * since we don't know how long the vector is (though, we do 1851 * know how many NUL-terminated strings are in the vector). 1852 */ 1853 len = 0; 1854 upper_bound = *sizep; 1855 for (; nargv != 0 && len < upper_bound; len += xlen) { 1856 aiov.iov_base = arg; 1857 aiov.iov_len = PAGE_SIZE; 1858 auio.uio_iov = &aiov; 1859 auio.uio_iovcnt = 1; 1860 auio.uio_offset = argv + len; 1861 xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK); 1862 auio.uio_resid = xlen; 1863 auio.uio_segflg = UIO_SYSSPACE; 1864 auio.uio_rw = UIO_READ; 1865 auio.uio_procp = NULL; 1866 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1867 if (error) 1868 goto done; 1869 1870 for (i = 0; i < xlen && nargv != 0; i++) { 1871 if (arg[i] == '\0') 1872 nargv--; /* one full string */ 1873 } 1874 1875 /* make sure we don't copyout past the end of the user's buffer */ 1876 if (len + i > upper_bound) 1877 i = upper_bound - len; 1878 1879 error = copyout(arg, (char *)where + len, i); 1880 if (error) 1881 break; 1882 1883 if (nargv == 0) { 1884 len += i; 1885 break; 1886 } 1887 } 1888 *sizep = len; 1889 1890 done: 1891 uvmspace_free(p->p_vmspace); 1892 1893 free(arg, M_TEMP); 1894 return (error); 1895 } 1896 1897 #if NPTY > 0 1898 int pty_maxptys __P((int, int)); /* defined in kern/tty_pty.c */ 1899 1900 /* 1901 * Validate parameters and get old / set new parameters 1902 * for pty sysctl function. 1903 */ 1904 static int 1905 sysctl_pty(oldp, oldlenp, newp, newlen) 1906 void *oldp; 1907 size_t *oldlenp; 1908 void *newp; 1909 size_t newlen; 1910 { 1911 int error = 0; 1912 int oldmax = 0, newmax = 0; 1913 1914 /* get current value of maxptys */ 1915 oldmax = pty_maxptys(0, 0); 1916 1917 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &oldmax, int) 1918 1919 if (!error && newp) { 1920 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 1921 SYSCTL_SCALAR_NEWPCOP_TYP(newp, &newmax, int) 1922 1923 if (newmax != pty_maxptys(newmax, (newp != NULL))) 1924 return (EINVAL); 1925 1926 } 1927 1928 return (error); 1929 } 1930 #endif /* NPTY > 0 */ 1931