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