1 /* $OpenBSD: kern_sysctl.c,v 1.168 2009/01/21 21:02:40 miod Exp $ */ 2 /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ 3 4 /*- 5 * Copyright (c) 1982, 1986, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Mike Karels at Berkeley Software Design, Inc. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 36 */ 37 38 /* 39 * sysctl system call. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/malloc.h> 46 #include <sys/proc.h> 47 #include <sys/resourcevar.h> 48 #include <sys/file.h> 49 #include <sys/vnode.h> 50 #include <sys/unistd.h> 51 #include <sys/buf.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 #include <sys/disklabel.h> 55 #include <sys/disk.h> 56 #include <uvm/uvm_extern.h> 57 #include <sys/sysctl.h> 58 #include <sys/msgbuf.h> 59 #include <sys/dkstat.h> 60 #include <sys/vmmeter.h> 61 #include <sys/namei.h> 62 #include <sys/exec.h> 63 #include <sys/mbuf.h> 64 #include <sys/sensors.h> 65 #ifdef __HAVE_TIMECOUNTER 66 #include <sys/timetc.h> 67 #endif 68 #include <sys/evcount.h> 69 70 #include <sys/mount.h> 71 #include <sys/syscallargs.h> 72 #include <dev/rndvar.h> 73 74 #ifdef DDB 75 #include <ddb/db_var.h> 76 #endif 77 78 #ifdef SYSVMSG 79 #include <sys/msg.h> 80 #endif 81 #ifdef SYSVSEM 82 #include <sys/sem.h> 83 #endif 84 #ifdef SYSVSHM 85 #include <sys/shm.h> 86 #endif 87 88 #define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x)) 89 90 extern struct forkstat forkstat; 91 extern struct nchstats nchstats; 92 extern int nselcoll, fscale; 93 extern struct disklist_head disklist; 94 extern fixpt_t ccpu; 95 extern long numvnodes; 96 97 extern void nmbclust_update(void); 98 99 int sysctl_diskinit(int, struct proc *); 100 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); 101 int sysctl_intrcnt(int *, u_int, void *, size_t *); 102 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); 103 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t); 104 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t); 105 106 int (*cpu_cpuspeed)(int *); 107 void (*cpu_setperf)(int); 108 int perflevel = 100; 109 110 /* 111 * Lock to avoid too many processes vslocking a large amount of memory 112 * at the same time. 113 */ 114 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk"); 115 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk"); 116 117 int 118 sys___sysctl(struct proc *p, void *v, register_t *retval) 119 { 120 struct sys___sysctl_args /* { 121 syscallarg(int *) name; 122 syscallarg(u_int) namelen; 123 syscallarg(void *) old; 124 syscallarg(size_t *) oldlenp; 125 syscallarg(void *) new; 126 syscallarg(size_t) newlen; 127 } */ *uap = v; 128 int error, dolock = 1; 129 size_t savelen = 0, oldlen = 0; 130 sysctlfn *fn; 131 int name[CTL_MAXNAME]; 132 133 if (SCARG(uap, new) != NULL && 134 (error = suser(p, 0))) 135 return (error); 136 /* 137 * all top-level sysctl names are non-terminal 138 */ 139 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 140 return (EINVAL); 141 error = copyin(SCARG(uap, name), name, 142 SCARG(uap, namelen) * sizeof(int)); 143 if (error) 144 return (error); 145 146 switch (name[0]) { 147 case CTL_KERN: 148 fn = kern_sysctl; 149 if (name[1] == KERN_VNODE) /* XXX */ 150 dolock = 0; 151 break; 152 case CTL_HW: 153 fn = hw_sysctl; 154 break; 155 case CTL_VM: 156 fn = uvm_sysctl; 157 break; 158 case CTL_NET: 159 fn = net_sysctl; 160 break; 161 case CTL_FS: 162 fn = fs_sysctl; 163 break; 164 case CTL_VFS: 165 fn = vfs_sysctl; 166 break; 167 case CTL_MACHDEP: 168 fn = cpu_sysctl; 169 break; 170 #ifdef DEBUG 171 case CTL_DEBUG: 172 fn = debug_sysctl; 173 break; 174 #endif 175 #ifdef DDB 176 case CTL_DDB: 177 fn = ddb_sysctl; 178 break; 179 #endif 180 default: 181 return (EOPNOTSUPP); 182 } 183 184 if (SCARG(uap, oldlenp) && 185 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) 186 return (error); 187 if (SCARG(uap, old) != NULL) { 188 if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0) 189 return (error); 190 if (dolock) { 191 if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) { 192 rw_exit_write(&sysctl_lock); 193 return (ENOMEM); 194 } 195 error = uvm_vslock(p, SCARG(uap, old), oldlen, 196 VM_PROT_READ|VM_PROT_WRITE); 197 if (error) { 198 rw_exit_write(&sysctl_lock); 199 return (error); 200 } 201 } 202 savelen = oldlen; 203 } 204 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old), 205 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); 206 if (SCARG(uap, old) != NULL) { 207 if (dolock) 208 uvm_vsunlock(p, SCARG(uap, old), savelen); 209 rw_exit_write(&sysctl_lock); 210 } 211 if (error) 212 return (error); 213 if (SCARG(uap, oldlenp)) 214 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 215 return (error); 216 } 217 218 /* 219 * Attributes stored in the kernel. 220 */ 221 char hostname[MAXHOSTNAMELEN]; 222 int hostnamelen; 223 char domainname[MAXHOSTNAMELEN]; 224 int domainnamelen; 225 long hostid; 226 char *disknames = NULL; 227 struct diskstats *diskstats = NULL; 228 #ifdef INSECURE 229 int securelevel = -1; 230 #else 231 int securelevel; 232 #endif 233 234 /* 235 * kernel related system variables. 236 */ 237 int 238 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 239 size_t newlen, struct proc *p) 240 { 241 int error, level, inthostid, stackgap; 242 extern int somaxconn, sominconn; 243 extern int usermount, nosuidcoredump; 244 extern long cp_time[CPUSTATES]; 245 extern int stackgap_random; 246 #ifdef CRYPTO 247 extern int usercrypto; 248 extern int userasymcrypto; 249 extern int cryptodevallowsoft; 250 #endif 251 extern int maxlocksperuid; 252 253 /* all sysctl names at this level are terminal except a ton of them */ 254 if (namelen != 1) { 255 switch (name[0]) { 256 case KERN_PROC: 257 case KERN_PROC2: 258 case KERN_PROF: 259 case KERN_MALLOCSTATS: 260 case KERN_TTY: 261 case KERN_POOL: 262 case KERN_PROC_ARGS: 263 case KERN_SYSVIPC_INFO: 264 case KERN_SEMINFO: 265 case KERN_SHMINFO: 266 case KERN_INTRCNT: 267 case KERN_WATCHDOG: 268 case KERN_EMUL: 269 case KERN_EVCOUNT: 270 #ifdef __HAVE_TIMECOUNTER 271 case KERN_TIMECOUNTER: 272 #endif 273 case KERN_CPTIME2: 274 break; 275 default: 276 return (ENOTDIR); /* overloaded */ 277 } 278 } 279 280 switch (name[0]) { 281 case KERN_OSTYPE: 282 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 283 case KERN_OSRELEASE: 284 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 285 case KERN_OSREV: 286 return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD)); 287 case KERN_OSVERSION: 288 return (sysctl_rdstring(oldp, oldlenp, newp, osversion)); 289 case KERN_VERSION: 290 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 291 case KERN_MAXVNODES: 292 return(sysctl_int(oldp, oldlenp, newp, newlen, &maxvnodes)); 293 case KERN_MAXPROC: 294 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 295 case KERN_MAXFILES: 296 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 297 case KERN_NFILES: 298 return (sysctl_rdint(oldp, oldlenp, newp, nfiles)); 299 case KERN_TTYCOUNT: 300 return (sysctl_rdint(oldp, oldlenp, newp, tty_count)); 301 case KERN_NUMVNODES: 302 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes)); 303 case KERN_ARGMAX: 304 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 305 case KERN_NSELCOLL: 306 return (sysctl_rdint(oldp, oldlenp, newp, nselcoll)); 307 case KERN_SECURELVL: 308 level = securelevel; 309 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 310 newp == NULL) 311 return (error); 312 if ((securelevel > 0 || level < -1) && 313 level < securelevel && p->p_pid != 1) 314 return (EPERM); 315 securelevel = level; 316 return (0); 317 case KERN_HOSTNAME: 318 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 319 hostname, sizeof(hostname)); 320 if (newp && !error) 321 hostnamelen = newlen; 322 return (error); 323 case KERN_DOMAINNAME: 324 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 325 domainname, sizeof(domainname)); 326 if (newp && !error) 327 domainnamelen = newlen; 328 return (error); 329 case KERN_HOSTID: 330 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 331 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 332 hostid = inthostid; 333 return (error); 334 case KERN_CLOCKRATE: 335 return (sysctl_clockrate(oldp, oldlenp, newp)); 336 case KERN_BOOTTIME: 337 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 338 sizeof(struct timeval))); 339 case KERN_VNODE: 340 return (sysctl_vnode(oldp, oldlenp, p)); 341 #ifndef SMALL_KERNEL 342 case KERN_PROC: 343 case KERN_PROC2: 344 return (sysctl_doproc(name, namelen, oldp, oldlenp)); 345 case KERN_PROC_ARGS: 346 return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp, 347 p)); 348 #endif 349 case KERN_FILE: 350 return (sysctl_file(oldp, oldlenp, p)); 351 case KERN_MBSTAT: 352 return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat, 353 sizeof(mbstat))); 354 #ifdef GPROF 355 case KERN_PROF: 356 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 357 newp, newlen)); 358 #endif 359 case KERN_POSIX1: 360 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 361 case KERN_NGROUPS: 362 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 363 case KERN_JOB_CONTROL: 364 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 365 case KERN_SAVED_IDS: 366 #ifdef _POSIX_SAVED_IDS 367 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 368 #else 369 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 370 #endif 371 case KERN_MAXPARTITIONS: 372 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 373 case KERN_RAWPARTITION: 374 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 375 case KERN_SOMAXCONN: 376 return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn)); 377 case KERN_SOMINCONN: 378 return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn)); 379 case KERN_USERMOUNT: 380 return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount)); 381 case KERN_RND: 382 return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats, 383 sizeof(rndstats))); 384 case KERN_ARND: { 385 char buf[256]; 386 387 if (*oldlenp > sizeof(buf)) 388 *oldlenp = sizeof(buf); 389 if (oldp) { 390 arc4random_buf(buf, *oldlenp); 391 if ((error = copyout(buf, oldp, *oldlenp))) 392 return (error); 393 } 394 return (0); 395 } 396 case KERN_NOSUIDCOREDUMP: 397 return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump)); 398 case KERN_FSYNC: 399 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 400 case KERN_SYSVMSG: 401 #ifdef SYSVMSG 402 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 403 #else 404 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 405 #endif 406 case KERN_SYSVSEM: 407 #ifdef SYSVSEM 408 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 409 #else 410 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 411 #endif 412 case KERN_SYSVSHM: 413 #ifdef SYSVSHM 414 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 415 #else 416 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 417 #endif 418 case KERN_MSGBUFSIZE: 419 /* 420 * deal with cases where the message buffer has 421 * become corrupted. 422 */ 423 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 424 return (ENXIO); 425 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 426 case KERN_MSGBUF: 427 /* see note above */ 428 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 429 return (ENXIO); 430 return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp, 431 msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); 432 case KERN_MALLOCSTATS: 433 return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp, 434 newp, newlen, p)); 435 case KERN_CPTIME: 436 { 437 CPU_INFO_ITERATOR cii; 438 struct cpu_info *ci; 439 int i; 440 441 bzero(cp_time, sizeof(cp_time)); 442 443 CPU_INFO_FOREACH(cii, ci) { 444 for (i = 0; i < CPUSTATES; i++) 445 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 446 } 447 448 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time, 449 sizeof(cp_time))); 450 } 451 case KERN_NCHSTATS: 452 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats, 453 sizeof(struct nchstats))); 454 case KERN_FORKSTAT: 455 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat, 456 sizeof(struct forkstat))); 457 case KERN_TTY: 458 return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp, 459 newp, newlen)); 460 case KERN_FSCALE: 461 return (sysctl_rdint(oldp, oldlenp, newp, fscale)); 462 case KERN_CCPU: 463 return (sysctl_rdint(oldp, oldlenp, newp, ccpu)); 464 case KERN_NPROCS: 465 return (sysctl_rdint(oldp, oldlenp, newp, nprocs)); 466 case KERN_POOL: 467 return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp)); 468 case KERN_STACKGAPRANDOM: 469 stackgap = stackgap_random; 470 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap); 471 if (error) 472 return (error); 473 /* 474 * Safety harness. 475 */ 476 if ((stackgap < ALIGNBYTES && stackgap != 0) || 477 !powerof2(stackgap) || stackgap >= MAXSSIZ) 478 return (EINVAL); 479 stackgap_random = stackgap; 480 return (0); 481 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 482 case KERN_SYSVIPC_INFO: 483 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp)); 484 #endif 485 #ifdef CRYPTO 486 case KERN_USERCRYPTO: 487 return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto)); 488 case KERN_USERASYMCRYPTO: 489 return (sysctl_int(oldp, oldlenp, newp, newlen, 490 &userasymcrypto)); 491 case KERN_CRYPTODEVALLOWSOFT: 492 return (sysctl_int(oldp, oldlenp, newp, newlen, 493 &cryptodevallowsoft)); 494 #endif 495 case KERN_SPLASSERT: 496 return (sysctl_int(oldp, oldlenp, newp, newlen, 497 &splassert_ctl)); 498 #ifdef SYSVSEM 499 case KERN_SEMINFO: 500 return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp, 501 newp, newlen)); 502 #endif 503 #ifdef SYSVSHM 504 case KERN_SHMINFO: 505 return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp, 506 newp, newlen)); 507 #endif 508 #ifndef SMALL_KERNEL 509 case KERN_INTRCNT: 510 return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp)); 511 case KERN_WATCHDOG: 512 return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp, 513 newp, newlen)); 514 case KERN_EMUL: 515 return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp, 516 newp, newlen)); 517 #endif 518 case KERN_MAXCLUSTERS: 519 error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust); 520 if (!error) 521 nmbclust_update(); 522 return (error); 523 #ifndef SMALL_KERNEL 524 case KERN_EVCOUNT: 525 return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp, 526 newp, newlen)); 527 #endif 528 #ifdef __HAVE_TIMECOUNTER 529 case KERN_TIMECOUNTER: 530 return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp, 531 newp, newlen)); 532 #endif 533 case KERN_MAXLOCKSPERUID: 534 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxlocksperuid)); 535 case KERN_CPTIME2: 536 return (sysctl_cptime2(name + 1, namelen -1, oldp, oldlenp, 537 newp, newlen)); 538 default: 539 return (EOPNOTSUPP); 540 } 541 /* NOTREACHED */ 542 } 543 544 /* 545 * hardware related system variables. 546 */ 547 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; 548 549 int 550 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 551 size_t newlen, struct proc *p) 552 { 553 extern char machine[], cpu_model[]; 554 int err, cpuspeed; 555 556 /* all sysctl names at this level except sensors are terminal */ 557 if (name[0] != HW_SENSORS && namelen != 1) 558 return (ENOTDIR); /* overloaded */ 559 560 switch (name[0]) { 561 case HW_MACHINE: 562 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 563 case HW_MODEL: 564 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 565 case HW_NCPU: 566 return (sysctl_rdint(oldp, oldlenp, newp, ncpus)); 567 case HW_BYTEORDER: 568 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 569 case HW_PHYSMEM: 570 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem))); 571 case HW_USERMEM: 572 return (sysctl_rdint(oldp, oldlenp, newp, 573 ptoa(physmem - uvmexp.wired))); 574 case HW_PAGESIZE: 575 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 576 case HW_DISKNAMES: 577 err = sysctl_diskinit(0, p); 578 if (err) 579 return err; 580 if (disknames) 581 return (sysctl_rdstring(oldp, oldlenp, newp, 582 disknames)); 583 else 584 return (sysctl_rdstring(oldp, oldlenp, newp, "")); 585 case HW_DISKSTATS: 586 err = sysctl_diskinit(1, p); 587 if (err) 588 return err; 589 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, 590 disk_count * sizeof(struct diskstats))); 591 case HW_DISKCOUNT: 592 return (sysctl_rdint(oldp, oldlenp, newp, disk_count)); 593 #ifndef SMALL_KERNEL 594 case HW_SENSORS: 595 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, 596 newp, newlen)); 597 #endif 598 case HW_CPUSPEED: 599 if (!cpu_cpuspeed) 600 return (EOPNOTSUPP); 601 err = cpu_cpuspeed(&cpuspeed); 602 if (err) 603 return err; 604 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 605 case HW_SETPERF: 606 if (!cpu_setperf) 607 return (EOPNOTSUPP); 608 err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel); 609 if (err) 610 return err; 611 if (perflevel > 100) 612 perflevel = 100; 613 if (perflevel < 0) 614 perflevel = 0; 615 if (newp) 616 cpu_setperf(perflevel); 617 return (0); 618 case HW_VENDOR: 619 if (hw_vendor) 620 return (sysctl_rdstring(oldp, oldlenp, newp, 621 hw_vendor)); 622 else 623 return (EOPNOTSUPP); 624 case HW_PRODUCT: 625 if (hw_prod) 626 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod)); 627 else 628 return (EOPNOTSUPP); 629 case HW_VERSION: 630 if (hw_ver) 631 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver)); 632 else 633 return (EOPNOTSUPP); 634 case HW_SERIALNO: 635 if (hw_serial) 636 return (sysctl_rdstring(oldp, oldlenp, newp, 637 hw_serial)); 638 else 639 return (EOPNOTSUPP); 640 case HW_UUID: 641 if (hw_uuid) 642 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid)); 643 else 644 return (EOPNOTSUPP); 645 case HW_PHYSMEM64: 646 return (sysctl_rdquad(oldp, oldlenp, newp, 647 ptoa((psize_t)physmem))); 648 case HW_USERMEM64: 649 return (sysctl_rdquad(oldp, oldlenp, newp, 650 ptoa((psize_t)physmem - uvmexp.wired))); 651 default: 652 return (EOPNOTSUPP); 653 } 654 /* NOTREACHED */ 655 } 656 657 #ifdef DEBUG 658 /* 659 * Debugging related system variables. 660 */ 661 extern struct ctldebug debug0, debug1; 662 struct ctldebug debug2, debug3, debug4; 663 struct ctldebug debug5, debug6, debug7, debug8, debug9; 664 struct ctldebug debug10, debug11, debug12, debug13, debug14; 665 struct ctldebug debug15, debug16, debug17, debug18, debug19; 666 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 667 &debug0, &debug1, &debug2, &debug3, &debug4, 668 &debug5, &debug6, &debug7, &debug8, &debug9, 669 &debug10, &debug11, &debug12, &debug13, &debug14, 670 &debug15, &debug16, &debug17, &debug18, &debug19, 671 }; 672 int 673 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 674 size_t newlen, struct proc *p) 675 { 676 struct ctldebug *cdp; 677 678 /* all sysctl names at this level are name and field */ 679 if (namelen != 2) 680 return (ENOTDIR); /* overloaded */ 681 cdp = debugvars[name[0]]; 682 if (cdp->debugname == 0) 683 return (EOPNOTSUPP); 684 switch (name[1]) { 685 case CTL_DEBUG_NAME: 686 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 687 case CTL_DEBUG_VALUE: 688 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 689 default: 690 return (EOPNOTSUPP); 691 } 692 /* NOTREACHED */ 693 } 694 #endif /* DEBUG */ 695 696 /* 697 * Reads, or writes that lower the value 698 */ 699 int 700 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 701 { 702 unsigned int oval = *valp, val = *valp; 703 int error; 704 705 if (newp == NULL) 706 return (sysctl_rdint(oldp, oldlenp, newp, *valp)); 707 708 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) 709 return (error); 710 if (val > oval) 711 return (EPERM); /* do not allow raising */ 712 *(unsigned int *)valp = val; 713 return (0); 714 } 715 716 /* 717 * Validate parameters and get old / set new parameters 718 * for an integer-valued sysctl function. 719 */ 720 int 721 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 722 { 723 int error = 0; 724 725 if (oldp && *oldlenp < sizeof(int)) 726 return (ENOMEM); 727 if (newp && newlen != sizeof(int)) 728 return (EINVAL); 729 *oldlenp = sizeof(int); 730 if (oldp) 731 error = copyout(valp, oldp, sizeof(int)); 732 if (error == 0 && newp) 733 error = copyin(newp, valp, sizeof(int)); 734 return (error); 735 } 736 737 /* 738 * As above, but read-only. 739 */ 740 int 741 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) 742 { 743 int error = 0; 744 745 if (oldp && *oldlenp < sizeof(int)) 746 return (ENOMEM); 747 if (newp) 748 return (EPERM); 749 *oldlenp = sizeof(int); 750 if (oldp) 751 error = copyout((caddr_t)&val, oldp, sizeof(int)); 752 return (error); 753 } 754 755 /* 756 * Array of integer values. 757 */ 758 int 759 sysctl_int_arr(int **valpp, int *name, u_int namelen, void *oldp, 760 size_t *oldlenp, void *newp, size_t newlen) 761 { 762 if (namelen > 1) 763 return (ENOTDIR); 764 if (name[0] < 0 || valpp[name[0]] == NULL) 765 return (EOPNOTSUPP); 766 return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]])); 767 } 768 769 /* 770 * Validate parameters and get old / set new parameters 771 * for an integer-valued sysctl function. 772 */ 773 int 774 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 775 int64_t *valp) 776 { 777 int error = 0; 778 779 if (oldp && *oldlenp < sizeof(int64_t)) 780 return (ENOMEM); 781 if (newp && newlen != sizeof(int64_t)) 782 return (EINVAL); 783 *oldlenp = sizeof(int64_t); 784 if (oldp) 785 error = copyout(valp, oldp, sizeof(int64_t)); 786 if (error == 0 && newp) 787 error = copyin(newp, valp, sizeof(int64_t)); 788 return (error); 789 } 790 791 /* 792 * As above, but read-only. 793 */ 794 int 795 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val) 796 { 797 int error = 0; 798 799 if (oldp && *oldlenp < sizeof(int64_t)) 800 return (ENOMEM); 801 if (newp) 802 return (EPERM); 803 *oldlenp = sizeof(int64_t); 804 if (oldp) 805 error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); 806 return (error); 807 } 808 809 /* 810 * Validate parameters and get old / set new parameters 811 * for a string-valued sysctl function. 812 */ 813 int 814 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, 815 int maxlen) 816 { 817 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); 818 } 819 820 int 821 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 822 char *str, int maxlen) 823 { 824 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); 825 } 826 827 int 828 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 829 char *str, int maxlen, int trunc) 830 { 831 int len, error = 0; 832 char c; 833 834 len = strlen(str) + 1; 835 if (oldp && *oldlenp < len) { 836 if (trunc == 0 || *oldlenp == 0) 837 return (ENOMEM); 838 } 839 if (newp && newlen >= maxlen) 840 return (EINVAL); 841 if (oldp) { 842 if (trunc && *oldlenp < len) { 843 /* save & zap NUL terminator while copying */ 844 c = str[*oldlenp-1]; 845 str[*oldlenp-1] = '\0'; 846 error = copyout(str, oldp, *oldlenp); 847 str[*oldlenp-1] = c; 848 } else { 849 *oldlenp = len; 850 error = copyout(str, oldp, len); 851 } 852 } 853 if (error == 0 && newp) { 854 error = copyin(newp, str, newlen); 855 str[newlen] = 0; 856 } 857 return (error); 858 } 859 860 /* 861 * As above, but read-only. 862 */ 863 int 864 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) 865 { 866 int len, error = 0; 867 868 len = strlen(str) + 1; 869 if (oldp && *oldlenp < len) 870 return (ENOMEM); 871 if (newp) 872 return (EPERM); 873 *oldlenp = len; 874 if (oldp) 875 error = copyout(str, oldp, len); 876 return (error); 877 } 878 879 /* 880 * Validate parameters and get old / set new parameters 881 * for a structure oriented sysctl function. 882 */ 883 int 884 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, 885 int len) 886 { 887 int error = 0; 888 889 if (oldp && *oldlenp < len) 890 return (ENOMEM); 891 if (newp && newlen > len) 892 return (EINVAL); 893 if (oldp) { 894 *oldlenp = len; 895 error = copyout(sp, oldp, len); 896 } 897 if (error == 0 && newp) 898 error = copyin(newp, sp, len); 899 return (error); 900 } 901 902 /* 903 * Validate parameters and get old parameters 904 * for a structure oriented sysctl function. 905 */ 906 int 907 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 908 int len) 909 { 910 int error = 0; 911 912 if (oldp && *oldlenp < len) 913 return (ENOMEM); 914 if (newp) 915 return (EPERM); 916 *oldlenp = len; 917 if (oldp) 918 error = copyout(sp, oldp, len); 919 return (error); 920 } 921 922 /* 923 * Get file structures. 924 */ 925 int 926 sysctl_file(char *where, size_t *sizep, struct proc *p) 927 { 928 int buflen, error; 929 struct file *fp, cfile; 930 char *start = where; 931 struct ucred *cred = p->p_ucred; 932 933 buflen = *sizep; 934 if (where == NULL) { 935 /* 936 * overestimate by 10 files 937 */ 938 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 939 return (0); 940 } 941 942 /* 943 * first copyout filehead 944 */ 945 if (buflen < sizeof(filehead)) { 946 *sizep = 0; 947 return (0); 948 } 949 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 950 if (error) 951 return (error); 952 buflen -= sizeof(filehead); 953 where += sizeof(filehead); 954 955 /* 956 * followed by an array of file structures 957 */ 958 LIST_FOREACH(fp, &filehead, f_list) { 959 if (buflen < sizeof(struct file)) { 960 *sizep = where - start; 961 return (ENOMEM); 962 } 963 964 /* Only let the superuser or the owner see some information */ 965 bcopy(fp, &cfile, sizeof (struct file)); 966 if (suser(p, 0) != 0 && cred->cr_uid != fp->f_cred->cr_uid) { 967 cfile.f_offset = (off_t)-1; 968 cfile.f_rxfer = 0; 969 cfile.f_wxfer = 0; 970 cfile.f_rbytes = 0; 971 cfile.f_wbytes = 0; 972 } 973 error = copyout(&cfile, where, sizeof (struct file)); 974 if (error) 975 return (error); 976 buflen -= sizeof(struct file); 977 where += sizeof(struct file); 978 } 979 *sizep = where - start; 980 return (0); 981 } 982 983 #ifndef SMALL_KERNEL 984 985 /* 986 * try over estimating by 5 procs 987 */ 988 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 989 990 int 991 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) 992 { 993 struct kinfo_proc2 *kproc2 = NULL; 994 struct eproc *eproc = NULL; 995 struct proc *p; 996 char *dp; 997 int arg, buflen, doingzomb, elem_size, elem_count; 998 int error, needed, type, op; 999 1000 dp = where; 1001 buflen = where != NULL ? *sizep : 0; 1002 needed = error = 0; 1003 type = name[0]; 1004 1005 if (type == KERN_PROC) { 1006 if (namelen != 3 && !(namelen == 2 && 1007 (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD))) 1008 return (EINVAL); 1009 op = name[1]; 1010 arg = op == KERN_PROC_ALL ? 0 : name[2]; 1011 elem_size = elem_count = 0; 1012 eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK); 1013 } else /* if (type == KERN_PROC2) */ { 1014 if (namelen != 5 || name[3] < 0 || name[4] < 0) 1015 return (EINVAL); 1016 op = name[1]; 1017 arg = name[2]; 1018 elem_size = name[3]; 1019 elem_count = name[4]; 1020 kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK); 1021 } 1022 p = LIST_FIRST(&allproc); 1023 doingzomb = 0; 1024 again: 1025 for (; p != 0; p = LIST_NEXT(p, p_list)) { 1026 /* 1027 * Skip embryonic processes. 1028 */ 1029 if (p->p_stat == SIDL) 1030 continue; 1031 /* 1032 * TODO - make more efficient (see notes below). 1033 */ 1034 switch (op) { 1035 1036 case KERN_PROC_PID: 1037 /* could do this with just a lookup */ 1038 if (p->p_pid != (pid_t)arg) 1039 continue; 1040 break; 1041 1042 case KERN_PROC_PGRP: 1043 /* could do this by traversing pgrp */ 1044 if (p->p_pgrp->pg_id != (pid_t)arg) 1045 continue; 1046 break; 1047 1048 case KERN_PROC_SESSION: 1049 if (p->p_session->s_leader == NULL || 1050 p->p_session->s_leader->p_pid != (pid_t)arg) 1051 continue; 1052 break; 1053 1054 case KERN_PROC_TTY: 1055 if ((p->p_flag & P_CONTROLT) == 0 || 1056 p->p_session->s_ttyp == NULL || 1057 p->p_session->s_ttyp->t_dev != (dev_t)arg) 1058 continue; 1059 break; 1060 1061 case KERN_PROC_UID: 1062 if (p->p_ucred->cr_uid != (uid_t)arg) 1063 continue; 1064 break; 1065 1066 case KERN_PROC_RUID: 1067 if (p->p_cred->p_ruid != (uid_t)arg) 1068 continue; 1069 break; 1070 1071 case KERN_PROC_ALL: 1072 if (p->p_flag & P_SYSTEM) 1073 continue; 1074 break; 1075 case KERN_PROC_KTHREAD: 1076 /* no filtering */ 1077 break; 1078 default: 1079 error = EINVAL; 1080 goto err; 1081 } 1082 if (type == KERN_PROC) { 1083 if (buflen >= sizeof(struct kinfo_proc)) { 1084 fill_eproc(p, eproc); 1085 error = copyout((caddr_t)p, 1086 &((struct kinfo_proc *)dp)->kp_proc, 1087 sizeof(struct proc)); 1088 if (error) 1089 goto err; 1090 error = copyout((caddr_t)eproc, 1091 &((struct kinfo_proc *)dp)->kp_eproc, 1092 sizeof(*eproc)); 1093 if (error) 1094 goto err; 1095 dp += sizeof(struct kinfo_proc); 1096 buflen -= sizeof(struct kinfo_proc); 1097 } 1098 needed += sizeof(struct kinfo_proc); 1099 } else /* if (type == KERN_PROC2) */ { 1100 if (buflen >= elem_size && elem_count > 0) { 1101 fill_kproc2(p, kproc2); 1102 /* 1103 * Copy out elem_size, but not larger than 1104 * the size of a struct kinfo_proc2. 1105 */ 1106 error = copyout(kproc2, dp, 1107 min(sizeof(*kproc2), elem_size)); 1108 if (error) 1109 goto err; 1110 dp += elem_size; 1111 buflen -= elem_size; 1112 elem_count--; 1113 } 1114 needed += elem_size; 1115 } 1116 } 1117 if (doingzomb == 0) { 1118 p = LIST_FIRST(&zombproc); 1119 doingzomb++; 1120 goto again; 1121 } 1122 if (where != NULL) { 1123 *sizep = dp - where; 1124 if (needed > *sizep) { 1125 error = ENOMEM; 1126 goto err; 1127 } 1128 } else { 1129 needed += KERN_PROCSLOP; 1130 *sizep = needed; 1131 } 1132 err: 1133 if (eproc) 1134 free(eproc, M_TEMP); 1135 if (kproc2) 1136 free(kproc2, M_TEMP); 1137 return (error); 1138 } 1139 1140 #endif /* SMALL_KERNEL */ 1141 1142 /* 1143 * Fill in an eproc structure for the specified process. 1144 */ 1145 void 1146 fill_eproc(struct proc *p, struct eproc *ep) 1147 { 1148 struct tty *tp; 1149 1150 ep->e_paddr = p; 1151 ep->e_sess = p->p_pgrp->pg_session; 1152 ep->e_pcred = *p->p_cred; 1153 ep->e_ucred = *p->p_ucred; 1154 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1155 ep->e_vm.vm_rssize = 0; 1156 ep->e_vm.vm_tsize = 0; 1157 ep->e_vm.vm_dsize = 0; 1158 ep->e_vm.vm_ssize = 0; 1159 bzero(&ep->e_pstats, sizeof(ep->e_pstats)); 1160 ep->e_pstats_valid = 0; 1161 } else { 1162 struct vmspace *vm = p->p_vmspace; 1163 1164 ep->e_vm.vm_rssize = vm_resident_count(vm); 1165 ep->e_vm.vm_tsize = vm->vm_tsize; 1166 ep->e_vm.vm_dsize = vm->vm_dused; 1167 ep->e_vm.vm_ssize = vm->vm_ssize; 1168 ep->e_pstats = *p->p_stats; 1169 ep->e_pstats_valid = 1; 1170 } 1171 if (p->p_pptr) 1172 ep->e_ppid = p->p_pptr->p_pid; 1173 else 1174 ep->e_ppid = 0; 1175 ep->e_pgid = p->p_pgrp->pg_id; 1176 ep->e_jobc = p->p_pgrp->pg_jobc; 1177 if ((p->p_flag & P_CONTROLT) && 1178 (tp = ep->e_sess->s_ttyp)) { 1179 ep->e_tdev = tp->t_dev; 1180 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1181 ep->e_tsess = tp->t_session; 1182 } else 1183 ep->e_tdev = NODEV; 1184 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1185 if (SESS_LEADER(p)) 1186 ep->e_flag |= EPROC_SLEADER; 1187 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN); 1188 ep->e_wmesg[WMESGLEN] = '\0'; 1189 ep->e_xsize = ep->e_xrssize = 0; 1190 ep->e_xccount = ep->e_xswrss = 0; 1191 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1); 1192 ep->e_login[MAXLOGNAME-1] = '\0'; 1193 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN); 1194 ep->e_emul[EMULNAMELEN] = '\0'; 1195 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0; 1196 ep->e_limit = p->p_p->ps_limit; 1197 } 1198 1199 #ifndef SMALL_KERNEL 1200 1201 /* 1202 * Fill in a kproc2 structure for the specified process. 1203 */ 1204 void 1205 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 1206 { 1207 struct tty *tp; 1208 struct timeval ut, st; 1209 1210 bzero(ki, sizeof(*ki)); 1211 1212 ki->p_paddr = PTRTOINT64(p); 1213 ki->p_fd = PTRTOINT64(p->p_fd); 1214 ki->p_stats = PTRTOINT64(p->p_stats); 1215 ki->p_limit = PTRTOINT64(p->p_p->ps_limit); 1216 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 1217 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 1218 ki->p_sess = PTRTOINT64(p->p_session); 1219 ki->p_tsess = 0; /* may be changed if controlling tty below */ 1220 ki->p_ru = PTRTOINT64(p->p_ru); 1221 1222 ki->p_eflag = 0; 1223 ki->p_exitsig = p->p_exitsig; 1224 ki->p_flag = p->p_flag | P_INMEM; 1225 1226 ki->p_pid = p->p_pid; 1227 if (p->p_pptr) 1228 ki->p_ppid = p->p_pptr->p_pid; 1229 else 1230 ki->p_ppid = 0; 1231 if (p->p_session->s_leader) 1232 ki->p_sid = p->p_session->s_leader->p_pid; 1233 else 1234 ki->p_sid = 0; 1235 ki->p__pgid = p->p_pgrp->pg_id; 1236 1237 ki->p_tpgid = -1; /* may be changed if controlling tty below */ 1238 1239 ki->p_uid = p->p_ucred->cr_uid; 1240 ki->p_ruid = p->p_cred->p_ruid; 1241 ki->p_gid = p->p_ucred->cr_gid; 1242 ki->p_rgid = p->p_cred->p_rgid; 1243 ki->p_svuid = p->p_cred->p_svuid; 1244 ki->p_svgid = p->p_cred->p_svgid; 1245 1246 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 1247 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 1248 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 1249 1250 ki->p_jobc = p->p_pgrp->pg_jobc; 1251 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 1252 ki->p_tdev = tp->t_dev; 1253 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; 1254 ki->p_tsess = PTRTOINT64(tp->t_session); 1255 } else { 1256 ki->p_tdev = NODEV; 1257 } 1258 1259 ki->p_estcpu = p->p_estcpu; 1260 ki->p_rtime_sec = p->p_rtime.tv_sec; 1261 ki->p_rtime_usec = p->p_rtime.tv_usec; 1262 ki->p_cpticks = p->p_cpticks; 1263 ki->p_pctcpu = p->p_pctcpu; 1264 1265 ki->p_uticks = p->p_uticks; 1266 ki->p_sticks = p->p_sticks; 1267 ki->p_iticks = p->p_iticks; 1268 1269 ki->p_tracep = PTRTOINT64(p->p_tracep); 1270 ki->p_traceflag = p->p_traceflag; 1271 1272 ki->p_siglist = p->p_siglist; 1273 ki->p_sigmask = p->p_sigmask; 1274 ki->p_sigignore = p->p_sigignore; 1275 ki->p_sigcatch = p->p_sigcatch; 1276 1277 ki->p_stat = p->p_stat; 1278 ki->p_nice = p->p_nice; 1279 1280 ki->p_xstat = p->p_xstat; 1281 ki->p_acflag = p->p_acflag; 1282 1283 strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul)); 1284 strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm)); 1285 strncpy(ki->p_login, p->p_session->s_login, 1286 min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login))); 1287 1288 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1289 ki->p_vm_rssize = 0; 1290 ki->p_vm_tsize = 0; 1291 ki->p_vm_dsize = 0; 1292 ki->p_vm_ssize = 0; 1293 } else { 1294 struct vmspace *vm = p->p_vmspace; 1295 1296 ki->p_vm_rssize = vm_resident_count(vm); 1297 ki->p_vm_tsize = vm->vm_tsize; 1298 ki->p_vm_dsize = vm->vm_dused; 1299 ki->p_vm_ssize = vm->vm_ssize; 1300 ki->p_forw = ki->p_back = 0; 1301 ki->p_addr = PTRTOINT64(p->p_addr); 1302 ki->p_stat = p->p_stat; 1303 ki->p_swtime = p->p_swtime; 1304 ki->p_slptime = p->p_slptime; 1305 ki->p_schedflags = 0; 1306 ki->p_holdcnt = 1; 1307 ki->p_priority = p->p_priority; 1308 ki->p_usrpri = p->p_usrpri; 1309 if (p->p_wmesg) 1310 strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg)); 1311 ki->p_wchan = PTRTOINT64(p->p_wchan); 1312 1313 } 1314 1315 if (p->p_session->s_ttyvp) 1316 ki->p_eflag |= EPROC_CTTY; 1317 if (SESS_LEADER(p)) 1318 ki->p_eflag |= EPROC_SLEADER; 1319 if (p->p_rlimit) 1320 ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur; 1321 1322 /* XXX Is this double check necessary? */ 1323 if (P_ZOMBIE(p)) { 1324 ki->p_uvalid = 0; 1325 } else { 1326 ki->p_uvalid = 1; 1327 1328 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 1329 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 1330 1331 calcru(p, &ut, &st, NULL); 1332 ki->p_uutime_sec = ut.tv_sec; 1333 ki->p_uutime_usec = ut.tv_usec; 1334 ki->p_ustime_sec = st.tv_sec; 1335 ki->p_ustime_usec = st.tv_usec; 1336 1337 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 1338 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 1339 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 1340 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 1341 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 1342 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 1343 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 1344 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 1345 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 1346 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 1347 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 1348 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 1349 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 1350 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 1351 1352 timeradd(&p->p_stats->p_cru.ru_utime, 1353 &p->p_stats->p_cru.ru_stime, &ut); 1354 ki->p_uctime_sec = ut.tv_sec; 1355 ki->p_uctime_usec = ut.tv_usec; 1356 ki->p_cpuid = KI_NOCPU; 1357 #ifdef MULTIPROCESSOR 1358 if (p->p_cpu != NULL) 1359 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); 1360 #endif 1361 } 1362 } 1363 1364 int 1365 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1366 struct proc *cp) 1367 { 1368 struct proc *vp; 1369 pid_t pid; 1370 struct ps_strings pss; 1371 struct iovec iov; 1372 struct uio uio; 1373 int error, cnt, op; 1374 size_t limit; 1375 char **rargv, **vargv; /* reader vs. victim */ 1376 char *rarg, *varg, *buf; 1377 struct vmspace *vm; 1378 1379 if (namelen > 2) 1380 return (ENOTDIR); 1381 if (namelen < 2) 1382 return (EINVAL); 1383 1384 pid = name[0]; 1385 op = name[1]; 1386 1387 switch (op) { 1388 case KERN_PROC_ARGV: 1389 case KERN_PROC_NARGV: 1390 case KERN_PROC_ENV: 1391 case KERN_PROC_NENV: 1392 break; 1393 default: 1394 return (EOPNOTSUPP); 1395 } 1396 1397 if ((vp = pfind(pid)) == NULL) 1398 return (ESRCH); 1399 1400 if (oldp == NULL) { 1401 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) 1402 *oldlenp = sizeof(int); 1403 else 1404 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1405 return (0); 1406 } 1407 1408 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM)) 1409 return (EINVAL); 1410 1411 /* Exiting - don't bother, it will be gone soon anyway */ 1412 if ((vp->p_flag & P_WEXIT)) 1413 return (ESRCH); 1414 1415 /* Execing - danger. */ 1416 if ((vp->p_flag & P_INEXEC)) 1417 return (EBUSY); 1418 1419 vm = vp->p_vmspace; 1420 vm->vm_refcnt++; 1421 vp = NULL; 1422 1423 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1424 1425 iov.iov_base = &pss; 1426 iov.iov_len = sizeof(pss); 1427 uio.uio_iov = &iov; 1428 uio.uio_iovcnt = 1; 1429 uio.uio_offset = (off_t)PS_STRINGS; 1430 uio.uio_resid = sizeof(pss); 1431 uio.uio_segflg = UIO_SYSSPACE; 1432 uio.uio_rw = UIO_READ; 1433 uio.uio_procp = cp; 1434 1435 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1436 goto out; 1437 1438 if (op == KERN_PROC_NARGV) { 1439 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 1440 goto out; 1441 } 1442 if (op == KERN_PROC_NENV) { 1443 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 1444 goto out; 1445 } 1446 1447 if (op == KERN_PROC_ARGV) { 1448 cnt = pss.ps_nargvstr; 1449 vargv = pss.ps_argvstr; 1450 } else { 1451 cnt = pss.ps_nenvstr; 1452 vargv = pss.ps_envstr; 1453 } 1454 1455 /* -1 to have space for a terminating NUL */ 1456 limit = *oldlenp - 1; 1457 *oldlenp = 0; 1458 1459 rargv = oldp; 1460 1461 /* 1462 * *oldlenp - number of bytes copied out into readers buffer. 1463 * limit - maximal number of bytes allowed into readers buffer. 1464 * rarg - pointer into readers buffer where next arg will be stored. 1465 * rargv - pointer into readers buffer where the next rarg pointer 1466 * will be stored. 1467 * vargv - pointer into victim address space where the next argument 1468 * will be read. 1469 */ 1470 1471 /* space for cnt pointers and a NULL */ 1472 rarg = (char *)(rargv + cnt + 1); 1473 *oldlenp += (cnt + 1) * sizeof(char **); 1474 1475 while (cnt > 0 && *oldlenp < limit) { 1476 size_t len, vstrlen; 1477 1478 /* Write to readers argv */ 1479 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 1480 goto out; 1481 1482 /* read the victim argv */ 1483 iov.iov_base = &varg; 1484 iov.iov_len = sizeof(varg); 1485 uio.uio_iov = &iov; 1486 uio.uio_iovcnt = 1; 1487 uio.uio_offset = (off_t)(vaddr_t)vargv; 1488 uio.uio_resid = sizeof(varg); 1489 uio.uio_segflg = UIO_SYSSPACE; 1490 uio.uio_rw = UIO_READ; 1491 uio.uio_procp = cp; 1492 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1493 goto out; 1494 1495 if (varg == NULL) 1496 break; 1497 1498 /* 1499 * read the victim arg. We must jump through hoops to avoid 1500 * crossing a page boundary too much and returning an error. 1501 */ 1502 more: 1503 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 1504 /* leave space for the terminating NUL */ 1505 iov.iov_base = buf; 1506 iov.iov_len = len; 1507 uio.uio_iov = &iov; 1508 uio.uio_iovcnt = 1; 1509 uio.uio_offset = (off_t)(vaddr_t)varg; 1510 uio.uio_resid = len; 1511 uio.uio_segflg = UIO_SYSSPACE; 1512 uio.uio_rw = UIO_READ; 1513 uio.uio_procp = cp; 1514 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1515 goto out; 1516 1517 for (vstrlen = 0; vstrlen < len; vstrlen++) { 1518 if (buf[vstrlen] == '\0') 1519 break; 1520 } 1521 1522 /* Don't overflow readers buffer. */ 1523 if (*oldlenp + vstrlen + 1 >= limit) { 1524 error = ENOMEM; 1525 goto out; 1526 } 1527 1528 if ((error = copyout(buf, rarg, vstrlen)) != 0) 1529 goto out; 1530 1531 *oldlenp += vstrlen; 1532 rarg += vstrlen; 1533 1534 /* The string didn't end in this page? */ 1535 if (vstrlen == len) { 1536 varg += vstrlen; 1537 goto more; 1538 } 1539 1540 /* End of string. Terminate it with a NUL */ 1541 buf[0] = '\0'; 1542 if ((error = copyout(buf, rarg, 1)) != 0) 1543 goto out; 1544 *oldlenp += 1; 1545 rarg += 1; 1546 1547 vargv++; 1548 rargv++; 1549 cnt--; 1550 } 1551 1552 if (*oldlenp >= limit) { 1553 error = ENOMEM; 1554 goto out; 1555 } 1556 1557 /* Write the terminating null */ 1558 rarg = NULL; 1559 error = copyout(&rarg, rargv, sizeof(rarg)); 1560 1561 out: 1562 uvmspace_free(vm); 1563 free(buf, M_TEMP); 1564 return (error); 1565 } 1566 1567 #endif 1568 1569 /* 1570 * Initialize disknames/diskstats for export by sysctl. If update is set, 1571 * then we simply update the disk statistics information. 1572 */ 1573 int 1574 sysctl_diskinit(int update, struct proc *p) 1575 { 1576 struct diskstats *sdk; 1577 struct disk *dk; 1578 int i, tlen, l; 1579 1580 if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) 1581 return i; 1582 1583 if (disk_change) { 1584 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk; 1585 dk = TAILQ_NEXT(dk, dk_link)) 1586 tlen += strlen(dk->dk_name) + 1; 1587 tlen++; 1588 1589 if (disknames) 1590 free(disknames, M_SYSCTL); 1591 if (diskstats) 1592 free(diskstats, M_SYSCTL); 1593 diskstats = NULL; 1594 disknames = NULL; 1595 diskstats = malloc(disk_count * sizeof(struct diskstats), 1596 M_SYSCTL, M_WAITOK); 1597 disknames = malloc(tlen, M_SYSCTL, M_WAITOK); 1598 disknames[0] = '\0'; 1599 1600 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk; 1601 dk = TAILQ_NEXT(dk, dk_link), i++) { 1602 snprintf(disknames + l, tlen - l, "%s,", 1603 dk->dk_name ? dk->dk_name : ""); 1604 l += strlen(disknames + l); 1605 sdk = diskstats + i; 1606 strlcpy(sdk->ds_name, dk->dk_name, 1607 sizeof(sdk->ds_name)); 1608 mtx_enter(&dk->dk_mtx); 1609 sdk->ds_busy = dk->dk_busy; 1610 sdk->ds_rxfer = dk->dk_rxfer; 1611 sdk->ds_wxfer = dk->dk_wxfer; 1612 sdk->ds_seek = dk->dk_seek; 1613 sdk->ds_rbytes = dk->dk_rbytes; 1614 sdk->ds_wbytes = dk->dk_wbytes; 1615 sdk->ds_attachtime = dk->dk_attachtime; 1616 sdk->ds_timestamp = dk->dk_timestamp; 1617 sdk->ds_time = dk->dk_time; 1618 mtx_leave(&dk->dk_mtx); 1619 } 1620 1621 /* Eliminate trailing comma */ 1622 if (l != 0) 1623 disknames[l - 1] = '\0'; 1624 disk_change = 0; 1625 } else if (update) { 1626 /* Just update, number of drives hasn't changed */ 1627 for (dk = TAILQ_FIRST(&disklist), i = 0; dk; 1628 dk = TAILQ_NEXT(dk, dk_link), i++) { 1629 sdk = diskstats + i; 1630 strlcpy(sdk->ds_name, dk->dk_name, 1631 sizeof(sdk->ds_name)); 1632 mtx_enter(&dk->dk_mtx); 1633 sdk->ds_busy = dk->dk_busy; 1634 sdk->ds_rxfer = dk->dk_rxfer; 1635 sdk->ds_wxfer = dk->dk_wxfer; 1636 sdk->ds_seek = dk->dk_seek; 1637 sdk->ds_rbytes = dk->dk_rbytes; 1638 sdk->ds_wbytes = dk->dk_wbytes; 1639 sdk->ds_attachtime = dk->dk_attachtime; 1640 sdk->ds_timestamp = dk->dk_timestamp; 1641 sdk->ds_time = dk->dk_time; 1642 mtx_leave(&dk->dk_mtx); 1643 } 1644 } 1645 rw_exit_write(&sysctl_disklock); 1646 return 0; 1647 } 1648 1649 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1650 int 1651 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 1652 { 1653 #ifdef SYSVMSG 1654 struct msg_sysctl_info *msgsi; 1655 #endif 1656 #ifdef SYSVSEM 1657 struct sem_sysctl_info *semsi; 1658 #endif 1659 #ifdef SYSVSHM 1660 struct shm_sysctl_info *shmsi; 1661 #endif 1662 size_t infosize, dssize, tsize, buflen; 1663 int i, nds, error, ret; 1664 void *buf; 1665 1666 if (namelen != 1) 1667 return (EINVAL); 1668 1669 buflen = *sizep; 1670 1671 switch (*name) { 1672 case KERN_SYSVIPC_MSG_INFO: 1673 #ifdef SYSVMSG 1674 infosize = sizeof(msgsi->msginfo); 1675 nds = msginfo.msgmni; 1676 dssize = sizeof(msgsi->msgids[0]); 1677 break; 1678 #else 1679 return (EOPNOTSUPP); 1680 #endif 1681 case KERN_SYSVIPC_SEM_INFO: 1682 #ifdef SYSVSEM 1683 infosize = sizeof(semsi->seminfo); 1684 nds = seminfo.semmni; 1685 dssize = sizeof(semsi->semids[0]); 1686 break; 1687 #else 1688 return (EOPNOTSUPP); 1689 #endif 1690 case KERN_SYSVIPC_SHM_INFO: 1691 #ifdef SYSVSHM 1692 infosize = sizeof(shmsi->shminfo); 1693 nds = shminfo.shmmni; 1694 dssize = sizeof(shmsi->shmids[0]); 1695 break; 1696 #else 1697 return (EOPNOTSUPP); 1698 #endif 1699 default: 1700 return (EINVAL); 1701 } 1702 tsize = infosize + (nds * dssize); 1703 1704 /* Return just the total size required. */ 1705 if (where == NULL) { 1706 *sizep = tsize; 1707 return (0); 1708 } 1709 1710 /* Not enough room for even the info struct. */ 1711 if (buflen < infosize) { 1712 *sizep = 0; 1713 return (ENOMEM); 1714 } 1715 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK|M_ZERO); 1716 1717 switch (*name) { 1718 #ifdef SYSVMSG 1719 case KERN_SYSVIPC_MSG_INFO: 1720 msgsi = (struct msg_sysctl_info *)buf; 1721 msgsi->msginfo = msginfo; 1722 break; 1723 #endif 1724 #ifdef SYSVSEM 1725 case KERN_SYSVIPC_SEM_INFO: 1726 semsi = (struct sem_sysctl_info *)buf; 1727 semsi->seminfo = seminfo; 1728 break; 1729 #endif 1730 #ifdef SYSVSHM 1731 case KERN_SYSVIPC_SHM_INFO: 1732 shmsi = (struct shm_sysctl_info *)buf; 1733 shmsi->shminfo = shminfo; 1734 break; 1735 #endif 1736 } 1737 buflen -= infosize; 1738 1739 ret = 0; 1740 if (buflen > 0) { 1741 /* Fill in the IPC data structures. */ 1742 for (i = 0; i < nds; i++) { 1743 if (buflen < dssize) { 1744 ret = ENOMEM; 1745 break; 1746 } 1747 switch (*name) { 1748 #ifdef SYSVMSG 1749 case KERN_SYSVIPC_MSG_INFO: 1750 bcopy(&msqids[i], &msgsi->msgids[i], dssize); 1751 break; 1752 #endif 1753 #ifdef SYSVSEM 1754 case KERN_SYSVIPC_SEM_INFO: 1755 if (sema[i] != NULL) 1756 bcopy(sema[i], &semsi->semids[i], 1757 dssize); 1758 else 1759 bzero(&semsi->semids[i], dssize); 1760 break; 1761 #endif 1762 #ifdef SYSVSHM 1763 case KERN_SYSVIPC_SHM_INFO: 1764 if (shmsegs[i] != NULL) 1765 bcopy(shmsegs[i], &shmsi->shmids[i], 1766 dssize); 1767 else 1768 bzero(&shmsi->shmids[i], dssize); 1769 break; 1770 #endif 1771 } 1772 buflen -= dssize; 1773 } 1774 } 1775 *sizep -= buflen; 1776 error = copyout(buf, where, *sizep); 1777 free(buf, M_TEMP); 1778 /* If copyout succeeded, use return code set earlier. */ 1779 return (error ? error : ret); 1780 } 1781 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1782 1783 #ifndef SMALL_KERNEL 1784 1785 int 1786 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 1787 { 1788 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); 1789 } 1790 1791 1792 int 1793 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1794 void *newp, size_t newlen) 1795 { 1796 struct ksensor *ks; 1797 struct sensor *us; 1798 struct ksensordev *ksd; 1799 struct sensordev *usd; 1800 int dev, numt, ret; 1801 enum sensor_type type; 1802 1803 if (namelen != 1 && namelen != 3) 1804 return (ENOTDIR); 1805 1806 dev = name[0]; 1807 if (namelen == 1) { 1808 ksd = sensordev_get(dev); 1809 if (ksd == NULL) 1810 return (ENOENT); 1811 1812 /* Grab a copy, to clear the kernel pointers */ 1813 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); 1814 usd->num = ksd->num; 1815 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); 1816 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); 1817 usd->sensors_count = ksd->sensors_count; 1818 1819 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, 1820 sizeof(struct sensordev)); 1821 1822 free(usd, M_TEMP); 1823 return (ret); 1824 } 1825 1826 type = name[1]; 1827 numt = name[2]; 1828 1829 ks = sensor_find(dev, type, numt); 1830 if (ks == NULL) 1831 return (ENOENT); 1832 1833 /* Grab a copy, to clear the kernel pointers */ 1834 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); 1835 memcpy(us->desc, ks->desc, sizeof(us->desc)); 1836 us->tv = ks->tv; 1837 us->value = ks->value; 1838 us->type = ks->type; 1839 us->status = ks->status; 1840 us->numt = ks->numt; 1841 us->flags = ks->flags; 1842 1843 ret = sysctl_rdstruct(oldp, oldlenp, newp, us, 1844 sizeof(struct sensor)); 1845 free(us, M_TEMP); 1846 return (ret); 1847 } 1848 1849 int 1850 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1851 void *newp, size_t newlen) 1852 { 1853 int enabled, error; 1854 struct emul *e; 1855 1856 if (name[0] == KERN_EMUL_NUM) { 1857 if (namelen != 1) 1858 return (ENOTDIR); 1859 return (sysctl_rdint(oldp, oldlenp, newp, nexecs)); 1860 } 1861 1862 if (namelen != 2) 1863 return (ENOTDIR); 1864 if (name[0] > nexecs || name[0] < 0) 1865 return (EINVAL); 1866 e = execsw[name[0] - 1].es_emul; 1867 if (e == NULL) 1868 return (EINVAL); 1869 1870 switch (name[1]) { 1871 case KERN_EMUL_NAME: 1872 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name)); 1873 case KERN_EMUL_ENABLED: 1874 enabled = (e->e_flags & EMUL_ENABLED); 1875 error = sysctl_int(oldp, oldlenp, newp, newlen, 1876 &enabled); 1877 e->e_flags = (enabled & EMUL_ENABLED); 1878 return (error); 1879 default: 1880 return (EINVAL); 1881 } 1882 } 1883 1884 #endif /* SMALL_KERNEL */ 1885 1886 int 1887 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1888 void *newp, size_t newlen) 1889 { 1890 CPU_INFO_ITERATOR cii; 1891 struct cpu_info *ci; 1892 int i; 1893 1894 if (namelen != 1) 1895 return (ENOTDIR); 1896 1897 i = name[0]; 1898 1899 CPU_INFO_FOREACH(cii, ci) { 1900 if (i-- == 0) 1901 break; 1902 } 1903 if (i > 0) 1904 return (ENOENT); 1905 1906 return (sysctl_rdstruct(oldp, oldlenp, newp, 1907 &ci->ci_schedstate.spc_cp_time, 1908 sizeof(ci->ci_schedstate.spc_cp_time))); 1909 } 1910