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