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