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