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