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