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