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