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