1 /* $OpenBSD: kern_sysctl.c,v 1.161 2008/06/09 07:07:16 djm 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)); 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)); 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) 927 { 928 int buflen, error; 929 struct file *fp; 930 char *start = where; 931 932 buflen = *sizep; 933 if (where == NULL) { 934 /* 935 * overestimate by 10 files 936 */ 937 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 938 return (0); 939 } 940 941 /* 942 * first copyout filehead 943 */ 944 if (buflen < sizeof(filehead)) { 945 *sizep = 0; 946 return (0); 947 } 948 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 949 if (error) 950 return (error); 951 buflen -= sizeof(filehead); 952 where += sizeof(filehead); 953 954 /* 955 * followed by an array of file structures 956 */ 957 LIST_FOREACH(fp, &filehead, f_list) { 958 if (buflen < sizeof(struct file)) { 959 *sizep = where - start; 960 return (ENOMEM); 961 } 962 error = copyout((caddr_t)fp, where, sizeof (struct file)); 963 if (error) 964 return (error); 965 buflen -= sizeof(struct file); 966 where += sizeof(struct file); 967 } 968 *sizep = where - start; 969 return (0); 970 } 971 972 #ifndef SMALL_KERNEL 973 974 /* 975 * try over estimating by 5 procs 976 */ 977 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 978 979 int 980 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) 981 { 982 struct kinfo_proc2 *kproc2 = NULL; 983 struct eproc *eproc = NULL; 984 struct proc *p; 985 char *dp; 986 int arg, buflen, doingzomb, elem_size, elem_count; 987 int error, needed, type, op; 988 989 dp = where; 990 buflen = where != NULL ? *sizep : 0; 991 needed = error = 0; 992 type = name[0]; 993 994 if (type == KERN_PROC) { 995 if (namelen != 3 && !(namelen == 2 && 996 (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD))) 997 return (EINVAL); 998 op = name[1]; 999 arg = op == KERN_PROC_ALL ? 0 : name[2]; 1000 elem_size = elem_count = 0; 1001 eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK); 1002 } else /* if (type == KERN_PROC2) */ { 1003 if (namelen != 5 || name[3] < 0 || name[4] < 0) 1004 return (EINVAL); 1005 op = name[1]; 1006 arg = name[2]; 1007 elem_size = name[3]; 1008 elem_count = name[4]; 1009 kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK); 1010 } 1011 p = LIST_FIRST(&allproc); 1012 doingzomb = 0; 1013 again: 1014 for (; p != 0; p = LIST_NEXT(p, p_list)) { 1015 /* 1016 * Skip embryonic processes. 1017 */ 1018 if (p->p_stat == SIDL) 1019 continue; 1020 /* 1021 * TODO - make more efficient (see notes below). 1022 */ 1023 switch (op) { 1024 1025 case KERN_PROC_PID: 1026 /* could do this with just a lookup */ 1027 if (p->p_pid != (pid_t)arg) 1028 continue; 1029 break; 1030 1031 case KERN_PROC_PGRP: 1032 /* could do this by traversing pgrp */ 1033 if (p->p_pgrp->pg_id != (pid_t)arg) 1034 continue; 1035 break; 1036 1037 case KERN_PROC_SESSION: 1038 if (p->p_session->s_leader == NULL || 1039 p->p_session->s_leader->p_pid != (pid_t)arg) 1040 continue; 1041 break; 1042 1043 case KERN_PROC_TTY: 1044 if ((p->p_flag & P_CONTROLT) == 0 || 1045 p->p_session->s_ttyp == NULL || 1046 p->p_session->s_ttyp->t_dev != (dev_t)arg) 1047 continue; 1048 break; 1049 1050 case KERN_PROC_UID: 1051 if (p->p_ucred->cr_uid != (uid_t)arg) 1052 continue; 1053 break; 1054 1055 case KERN_PROC_RUID: 1056 if (p->p_cred->p_ruid != (uid_t)arg) 1057 continue; 1058 break; 1059 1060 case KERN_PROC_ALL: 1061 if (p->p_flag & P_SYSTEM) 1062 continue; 1063 break; 1064 case KERN_PROC_KTHREAD: 1065 /* no filtering */ 1066 break; 1067 default: 1068 error = EINVAL; 1069 goto err; 1070 } 1071 if (type == KERN_PROC) { 1072 if (buflen >= sizeof(struct kinfo_proc)) { 1073 fill_eproc(p, eproc); 1074 error = copyout((caddr_t)p, 1075 &((struct kinfo_proc *)dp)->kp_proc, 1076 sizeof(struct proc)); 1077 if (error) 1078 goto err; 1079 error = copyout((caddr_t)eproc, 1080 &((struct kinfo_proc *)dp)->kp_eproc, 1081 sizeof(*eproc)); 1082 if (error) 1083 goto err; 1084 dp += sizeof(struct kinfo_proc); 1085 buflen -= sizeof(struct kinfo_proc); 1086 } 1087 needed += sizeof(struct kinfo_proc); 1088 } else /* if (type == KERN_PROC2) */ { 1089 if (buflen >= elem_size && elem_count > 0) { 1090 fill_kproc2(p, kproc2); 1091 /* 1092 * Copy out elem_size, but not larger than 1093 * the size of a struct kinfo_proc2. 1094 */ 1095 error = copyout(kproc2, dp, 1096 min(sizeof(*kproc2), elem_size)); 1097 if (error) 1098 goto err; 1099 dp += elem_size; 1100 buflen -= elem_size; 1101 elem_count--; 1102 } 1103 needed += elem_size; 1104 } 1105 } 1106 if (doingzomb == 0) { 1107 p = LIST_FIRST(&zombproc); 1108 doingzomb++; 1109 goto again; 1110 } 1111 if (where != NULL) { 1112 *sizep = dp - where; 1113 if (needed > *sizep) { 1114 error = ENOMEM; 1115 goto err; 1116 } 1117 } else { 1118 needed += KERN_PROCSLOP; 1119 *sizep = needed; 1120 } 1121 err: 1122 if (eproc) 1123 free(eproc, M_TEMP); 1124 if (kproc2) 1125 free(kproc2, M_TEMP); 1126 return (error); 1127 } 1128 1129 #endif /* SMALL_KERNEL */ 1130 1131 /* 1132 * Fill in an eproc structure for the specified process. 1133 */ 1134 void 1135 fill_eproc(struct proc *p, struct eproc *ep) 1136 { 1137 struct tty *tp; 1138 1139 ep->e_paddr = p; 1140 ep->e_sess = p->p_pgrp->pg_session; 1141 ep->e_pcred = *p->p_cred; 1142 ep->e_ucred = *p->p_ucred; 1143 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1144 ep->e_vm.vm_rssize = 0; 1145 ep->e_vm.vm_tsize = 0; 1146 ep->e_vm.vm_dsize = 0; 1147 ep->e_vm.vm_ssize = 0; 1148 bzero(&ep->e_pstats, sizeof(ep->e_pstats)); 1149 ep->e_pstats_valid = 0; 1150 } else { 1151 struct vmspace *vm = p->p_vmspace; 1152 1153 ep->e_vm.vm_rssize = vm_resident_count(vm); 1154 ep->e_vm.vm_tsize = vm->vm_tsize; 1155 ep->e_vm.vm_dsize = vm->vm_dused; 1156 ep->e_vm.vm_ssize = vm->vm_ssize; 1157 ep->e_pstats = *p->p_stats; 1158 ep->e_pstats_valid = 1; 1159 } 1160 if (p->p_pptr) 1161 ep->e_ppid = p->p_pptr->p_pid; 1162 else 1163 ep->e_ppid = 0; 1164 ep->e_pgid = p->p_pgrp->pg_id; 1165 ep->e_jobc = p->p_pgrp->pg_jobc; 1166 if ((p->p_flag & P_CONTROLT) && 1167 (tp = ep->e_sess->s_ttyp)) { 1168 ep->e_tdev = tp->t_dev; 1169 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1170 ep->e_tsess = tp->t_session; 1171 } else 1172 ep->e_tdev = NODEV; 1173 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1174 if (SESS_LEADER(p)) 1175 ep->e_flag |= EPROC_SLEADER; 1176 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN); 1177 ep->e_wmesg[WMESGLEN] = '\0'; 1178 ep->e_xsize = ep->e_xrssize = 0; 1179 ep->e_xccount = ep->e_xswrss = 0; 1180 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1); 1181 ep->e_login[MAXLOGNAME-1] = '\0'; 1182 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN); 1183 ep->e_emul[EMULNAMELEN] = '\0'; 1184 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0; 1185 ep->e_limit = p->p_p->ps_limit; 1186 } 1187 1188 #ifndef SMALL_KERNEL 1189 1190 /* 1191 * Fill in a kproc2 structure for the specified process. 1192 */ 1193 void 1194 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 1195 { 1196 struct tty *tp; 1197 struct timeval ut, st; 1198 1199 bzero(ki, sizeof(*ki)); 1200 1201 ki->p_paddr = PTRTOINT64(p); 1202 ki->p_fd = PTRTOINT64(p->p_fd); 1203 ki->p_stats = PTRTOINT64(p->p_stats); 1204 ki->p_limit = PTRTOINT64(p->p_p->ps_limit); 1205 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 1206 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 1207 ki->p_sess = PTRTOINT64(p->p_session); 1208 ki->p_tsess = 0; /* may be changed if controlling tty below */ 1209 ki->p_ru = PTRTOINT64(p->p_ru); 1210 1211 ki->p_eflag = 0; 1212 ki->p_exitsig = p->p_exitsig; 1213 ki->p_flag = p->p_flag | P_INMEM; 1214 1215 ki->p_pid = p->p_pid; 1216 if (p->p_pptr) 1217 ki->p_ppid = p->p_pptr->p_pid; 1218 else 1219 ki->p_ppid = 0; 1220 if (p->p_session->s_leader) 1221 ki->p_sid = p->p_session->s_leader->p_pid; 1222 else 1223 ki->p_sid = 0; 1224 ki->p__pgid = p->p_pgrp->pg_id; 1225 1226 ki->p_tpgid = -1; /* may be changed if controlling tty below */ 1227 1228 ki->p_uid = p->p_ucred->cr_uid; 1229 ki->p_ruid = p->p_cred->p_ruid; 1230 ki->p_gid = p->p_ucred->cr_gid; 1231 ki->p_rgid = p->p_cred->p_rgid; 1232 ki->p_svuid = p->p_cred->p_svuid; 1233 ki->p_svgid = p->p_cred->p_svgid; 1234 1235 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 1236 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 1237 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 1238 1239 ki->p_jobc = p->p_pgrp->pg_jobc; 1240 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 1241 ki->p_tdev = tp->t_dev; 1242 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; 1243 ki->p_tsess = PTRTOINT64(tp->t_session); 1244 } else { 1245 ki->p_tdev = NODEV; 1246 } 1247 1248 ki->p_estcpu = p->p_estcpu; 1249 ki->p_rtime_sec = p->p_rtime.tv_sec; 1250 ki->p_rtime_usec = p->p_rtime.tv_usec; 1251 ki->p_cpticks = p->p_cpticks; 1252 ki->p_pctcpu = p->p_pctcpu; 1253 1254 ki->p_uticks = p->p_uticks; 1255 ki->p_sticks = p->p_sticks; 1256 ki->p_iticks = p->p_iticks; 1257 1258 ki->p_tracep = PTRTOINT64(p->p_tracep); 1259 ki->p_traceflag = p->p_traceflag; 1260 1261 ki->p_siglist = p->p_siglist; 1262 ki->p_sigmask = p->p_sigmask; 1263 ki->p_sigignore = p->p_sigignore; 1264 ki->p_sigcatch = p->p_sigcatch; 1265 1266 ki->p_stat = p->p_stat; 1267 ki->p_nice = p->p_nice; 1268 1269 ki->p_xstat = p->p_xstat; 1270 ki->p_acflag = p->p_acflag; 1271 1272 strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul)); 1273 strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm)); 1274 strncpy(ki->p_login, p->p_session->s_login, 1275 min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login))); 1276 1277 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1278 ki->p_vm_rssize = 0; 1279 ki->p_vm_tsize = 0; 1280 ki->p_vm_dsize = 0; 1281 ki->p_vm_ssize = 0; 1282 } else { 1283 struct vmspace *vm = p->p_vmspace; 1284 1285 ki->p_vm_rssize = vm_resident_count(vm); 1286 ki->p_vm_tsize = vm->vm_tsize; 1287 ki->p_vm_dsize = vm->vm_dused; 1288 ki->p_vm_ssize = vm->vm_ssize; 1289 ki->p_forw = ki->p_back = 0; 1290 ki->p_addr = PTRTOINT64(p->p_addr); 1291 ki->p_stat = p->p_stat; 1292 ki->p_swtime = p->p_swtime; 1293 ki->p_slptime = p->p_slptime; 1294 ki->p_schedflags = 0; 1295 ki->p_holdcnt = 1; 1296 ki->p_priority = p->p_priority; 1297 ki->p_usrpri = p->p_usrpri; 1298 if (p->p_wmesg) 1299 strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg)); 1300 ki->p_wchan = PTRTOINT64(p->p_wchan); 1301 1302 } 1303 1304 if (p->p_session->s_ttyvp) 1305 ki->p_eflag |= EPROC_CTTY; 1306 if (SESS_LEADER(p)) 1307 ki->p_eflag |= EPROC_SLEADER; 1308 if (p->p_rlimit) 1309 ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur; 1310 1311 /* XXX Is this double check necessary? */ 1312 if (P_ZOMBIE(p)) { 1313 ki->p_uvalid = 0; 1314 } else { 1315 ki->p_uvalid = 1; 1316 1317 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 1318 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 1319 1320 calcru(p, &ut, &st, 0); 1321 ki->p_uutime_sec = ut.tv_sec; 1322 ki->p_uutime_usec = ut.tv_usec; 1323 ki->p_ustime_sec = st.tv_sec; 1324 ki->p_ustime_usec = st.tv_usec; 1325 1326 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 1327 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 1328 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 1329 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 1330 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 1331 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 1332 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 1333 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 1334 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 1335 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 1336 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 1337 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 1338 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 1339 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 1340 1341 timeradd(&p->p_stats->p_cru.ru_utime, 1342 &p->p_stats->p_cru.ru_stime, &ut); 1343 ki->p_uctime_sec = ut.tv_sec; 1344 ki->p_uctime_usec = ut.tv_usec; 1345 ki->p_cpuid = KI_NOCPU; 1346 #ifdef MULTIPROCESSOR 1347 if (p->p_cpu != NULL) 1348 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); 1349 #endif 1350 } 1351 } 1352 1353 int 1354 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1355 struct proc *cp) 1356 { 1357 struct proc *vp; 1358 pid_t pid; 1359 int op; 1360 struct ps_strings pss; 1361 struct iovec iov; 1362 struct uio uio; 1363 int error; 1364 size_t limit; 1365 int cnt; 1366 char **rargv, **vargv; /* reader vs. victim */ 1367 char *rarg, *varg; 1368 char *buf; 1369 1370 if (namelen > 2) 1371 return (ENOTDIR); 1372 if (namelen < 2) 1373 return (EINVAL); 1374 1375 pid = name[0]; 1376 op = name[1]; 1377 1378 switch (op) { 1379 case KERN_PROC_ARGV: 1380 case KERN_PROC_NARGV: 1381 case KERN_PROC_ENV: 1382 case KERN_PROC_NENV: 1383 break; 1384 default: 1385 return (EOPNOTSUPP); 1386 } 1387 1388 if ((vp = pfind(pid)) == NULL) 1389 return (ESRCH); 1390 1391 if (oldp == NULL) { 1392 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) 1393 *oldlenp = sizeof(int); 1394 else 1395 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1396 return (0); 1397 } 1398 1399 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM)) 1400 return (EINVAL); 1401 1402 /* Exiting - don't bother, it will be gone soon anyway */ 1403 if ((vp->p_flag & P_WEXIT)) 1404 return (ESRCH); 1405 1406 /* Execing - danger. */ 1407 if ((vp->p_flag & P_INEXEC)) 1408 return (EBUSY); 1409 1410 vp->p_vmspace->vm_refcnt++; /* XXX */ 1411 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1412 1413 iov.iov_base = &pss; 1414 iov.iov_len = sizeof(pss); 1415 uio.uio_iov = &iov; 1416 uio.uio_iovcnt = 1; 1417 uio.uio_offset = (off_t)PS_STRINGS; 1418 uio.uio_resid = sizeof(pss); 1419 uio.uio_segflg = UIO_SYSSPACE; 1420 uio.uio_rw = UIO_READ; 1421 uio.uio_procp = cp; 1422 1423 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0) 1424 goto out; 1425 1426 if (op == KERN_PROC_NARGV) { 1427 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 1428 goto out; 1429 } 1430 if (op == KERN_PROC_NENV) { 1431 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 1432 goto out; 1433 } 1434 1435 if (op == KERN_PROC_ARGV) { 1436 cnt = pss.ps_nargvstr; 1437 vargv = pss.ps_argvstr; 1438 } else { 1439 cnt = pss.ps_nenvstr; 1440 vargv = pss.ps_envstr; 1441 } 1442 1443 /* -1 to have space for a terminating NUL */ 1444 limit = *oldlenp - 1; 1445 *oldlenp = 0; 1446 1447 rargv = oldp; 1448 1449 /* 1450 * *oldlenp - number of bytes copied out into readers buffer. 1451 * limit - maximal number of bytes allowed into readers buffer. 1452 * rarg - pointer into readers buffer where next arg will be stored. 1453 * rargv - pointer into readers buffer where the next rarg pointer 1454 * will be stored. 1455 * vargv - pointer into victim address space where the next argument 1456 * will be read. 1457 */ 1458 1459 /* space for cnt pointers and a NULL */ 1460 rarg = (char *)(rargv + cnt + 1); 1461 *oldlenp += (cnt + 1) * sizeof(char **); 1462 1463 while (cnt > 0 && *oldlenp < limit) { 1464 size_t len, vstrlen; 1465 1466 /* Write to readers argv */ 1467 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 1468 goto out; 1469 1470 /* read the victim argv */ 1471 iov.iov_base = &varg; 1472 iov.iov_len = sizeof(varg); 1473 uio.uio_iov = &iov; 1474 uio.uio_iovcnt = 1; 1475 uio.uio_offset = (off_t)(vaddr_t)vargv; 1476 uio.uio_resid = sizeof(varg); 1477 uio.uio_segflg = UIO_SYSSPACE; 1478 uio.uio_rw = UIO_READ; 1479 uio.uio_procp = cp; 1480 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0) 1481 goto out; 1482 1483 if (varg == NULL) 1484 break; 1485 1486 /* 1487 * read the victim arg. We must jump through hoops to avoid 1488 * crossing a page boundary too much and returning an error. 1489 */ 1490 more: 1491 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 1492 /* leave space for the terminating NUL */ 1493 iov.iov_base = buf; 1494 iov.iov_len = len; 1495 uio.uio_iov = &iov; 1496 uio.uio_iovcnt = 1; 1497 uio.uio_offset = (off_t)(vaddr_t)varg; 1498 uio.uio_resid = len; 1499 uio.uio_segflg = UIO_SYSSPACE; 1500 uio.uio_rw = UIO_READ; 1501 uio.uio_procp = cp; 1502 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0) 1503 goto out; 1504 1505 for (vstrlen = 0; vstrlen < len; vstrlen++) { 1506 if (buf[vstrlen] == '\0') 1507 break; 1508 } 1509 1510 /* Don't overflow readers buffer. */ 1511 if (*oldlenp + vstrlen + 1 >= limit) { 1512 error = ENOMEM; 1513 goto out; 1514 } 1515 1516 if ((error = copyout(buf, rarg, vstrlen)) != 0) 1517 goto out; 1518 1519 *oldlenp += vstrlen; 1520 rarg += vstrlen; 1521 1522 /* The string didn't end in this page? */ 1523 if (vstrlen == len) { 1524 varg += vstrlen; 1525 goto more; 1526 } 1527 1528 /* End of string. Terminate it with a NUL */ 1529 buf[0] = '\0'; 1530 if ((error = copyout(buf, rarg, 1)) != 0) 1531 goto out; 1532 *oldlenp += 1; 1533 rarg += 1; 1534 1535 vargv++; 1536 rargv++; 1537 cnt--; 1538 } 1539 1540 if (*oldlenp >= limit) { 1541 error = ENOMEM; 1542 goto out; 1543 } 1544 1545 /* Write the terminating null */ 1546 rarg = NULL; 1547 error = copyout(&rarg, rargv, sizeof(rarg)); 1548 1549 out: 1550 uvmspace_free(vp->p_vmspace); 1551 free(buf, M_TEMP); 1552 return (error); 1553 } 1554 1555 #endif 1556 1557 /* 1558 * Initialize disknames/diskstats for export by sysctl. If update is set, 1559 * then we simply update the disk statistics information. 1560 */ 1561 int 1562 sysctl_diskinit(int update, struct proc *p) 1563 { 1564 struct diskstats *sdk; 1565 struct disk *dk; 1566 int i, tlen, l; 1567 1568 if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) 1569 return i; 1570 1571 if (disk_change) { 1572 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk; 1573 dk = TAILQ_NEXT(dk, dk_link)) 1574 tlen += strlen(dk->dk_name) + 1; 1575 tlen++; 1576 1577 if (disknames) 1578 free(disknames, M_SYSCTL); 1579 if (diskstats) 1580 free(diskstats, M_SYSCTL); 1581 diskstats = NULL; 1582 disknames = NULL; 1583 diskstats = malloc(disk_count * sizeof(struct diskstats), 1584 M_SYSCTL, M_WAITOK); 1585 disknames = malloc(tlen, M_SYSCTL, M_WAITOK); 1586 disknames[0] = '\0'; 1587 1588 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk; 1589 dk = TAILQ_NEXT(dk, dk_link), i++) { 1590 snprintf(disknames + l, tlen - l, "%s,", 1591 dk->dk_name ? dk->dk_name : ""); 1592 l += strlen(disknames + l); 1593 sdk = diskstats + i; 1594 strlcpy(sdk->ds_name, dk->dk_name, 1595 sizeof(sdk->ds_name)); 1596 mtx_enter(&dk->dk_mtx); 1597 sdk->ds_busy = dk->dk_busy; 1598 sdk->ds_rxfer = dk->dk_rxfer; 1599 sdk->ds_wxfer = dk->dk_wxfer; 1600 sdk->ds_seek = dk->dk_seek; 1601 sdk->ds_rbytes = dk->dk_rbytes; 1602 sdk->ds_wbytes = dk->dk_wbytes; 1603 sdk->ds_attachtime = dk->dk_attachtime; 1604 sdk->ds_timestamp = dk->dk_timestamp; 1605 sdk->ds_time = dk->dk_time; 1606 mtx_leave(&dk->dk_mtx); 1607 } 1608 1609 /* Eliminate trailing comma */ 1610 if (l != 0) 1611 disknames[l - 1] = '\0'; 1612 disk_change = 0; 1613 } else if (update) { 1614 /* Just update, number of drives hasn't changed */ 1615 for (dk = TAILQ_FIRST(&disklist), i = 0; dk; 1616 dk = TAILQ_NEXT(dk, dk_link), i++) { 1617 sdk = diskstats + i; 1618 strlcpy(sdk->ds_name, dk->dk_name, 1619 sizeof(sdk->ds_name)); 1620 mtx_enter(&dk->dk_mtx); 1621 sdk->ds_busy = dk->dk_busy; 1622 sdk->ds_rxfer = dk->dk_rxfer; 1623 sdk->ds_wxfer = dk->dk_wxfer; 1624 sdk->ds_seek = dk->dk_seek; 1625 sdk->ds_rbytes = dk->dk_rbytes; 1626 sdk->ds_wbytes = dk->dk_wbytes; 1627 sdk->ds_attachtime = dk->dk_attachtime; 1628 sdk->ds_timestamp = dk->dk_timestamp; 1629 sdk->ds_time = dk->dk_time; 1630 mtx_leave(&dk->dk_mtx); 1631 } 1632 } 1633 rw_exit_write(&sysctl_disklock); 1634 return 0; 1635 } 1636 1637 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1638 int 1639 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 1640 { 1641 #ifdef SYSVMSG 1642 struct msg_sysctl_info *msgsi; 1643 #endif 1644 #ifdef SYSVSEM 1645 struct sem_sysctl_info *semsi; 1646 #endif 1647 #ifdef SYSVSHM 1648 struct shm_sysctl_info *shmsi; 1649 #endif 1650 size_t infosize, dssize, tsize, buflen; 1651 int i, nds, error, ret; 1652 void *buf; 1653 1654 if (namelen != 1) 1655 return (EINVAL); 1656 1657 buflen = *sizep; 1658 1659 switch (*name) { 1660 case KERN_SYSVIPC_MSG_INFO: 1661 #ifdef SYSVMSG 1662 infosize = sizeof(msgsi->msginfo); 1663 nds = msginfo.msgmni; 1664 dssize = sizeof(msgsi->msgids[0]); 1665 break; 1666 #else 1667 return (EOPNOTSUPP); 1668 #endif 1669 case KERN_SYSVIPC_SEM_INFO: 1670 #ifdef SYSVSEM 1671 infosize = sizeof(semsi->seminfo); 1672 nds = seminfo.semmni; 1673 dssize = sizeof(semsi->semids[0]); 1674 break; 1675 #else 1676 return (EOPNOTSUPP); 1677 #endif 1678 case KERN_SYSVIPC_SHM_INFO: 1679 #ifdef SYSVSHM 1680 infosize = sizeof(shmsi->shminfo); 1681 nds = shminfo.shmmni; 1682 dssize = sizeof(shmsi->shmids[0]); 1683 break; 1684 #else 1685 return (EOPNOTSUPP); 1686 #endif 1687 default: 1688 return (EINVAL); 1689 } 1690 tsize = infosize + (nds * dssize); 1691 1692 /* Return just the total size required. */ 1693 if (where == NULL) { 1694 *sizep = tsize; 1695 return (0); 1696 } 1697 1698 /* Not enough room for even the info struct. */ 1699 if (buflen < infosize) { 1700 *sizep = 0; 1701 return (ENOMEM); 1702 } 1703 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK|M_ZERO); 1704 1705 switch (*name) { 1706 #ifdef SYSVMSG 1707 case KERN_SYSVIPC_MSG_INFO: 1708 msgsi = (struct msg_sysctl_info *)buf; 1709 msgsi->msginfo = msginfo; 1710 break; 1711 #endif 1712 #ifdef SYSVSEM 1713 case KERN_SYSVIPC_SEM_INFO: 1714 semsi = (struct sem_sysctl_info *)buf; 1715 semsi->seminfo = seminfo; 1716 break; 1717 #endif 1718 #ifdef SYSVSHM 1719 case KERN_SYSVIPC_SHM_INFO: 1720 shmsi = (struct shm_sysctl_info *)buf; 1721 shmsi->shminfo = shminfo; 1722 break; 1723 #endif 1724 } 1725 buflen -= infosize; 1726 1727 ret = 0; 1728 if (buflen > 0) { 1729 /* Fill in the IPC data structures. */ 1730 for (i = 0; i < nds; i++) { 1731 if (buflen < dssize) { 1732 ret = ENOMEM; 1733 break; 1734 } 1735 switch (*name) { 1736 #ifdef SYSVMSG 1737 case KERN_SYSVIPC_MSG_INFO: 1738 bcopy(&msqids[i], &msgsi->msgids[i], dssize); 1739 break; 1740 #endif 1741 #ifdef SYSVSEM 1742 case KERN_SYSVIPC_SEM_INFO: 1743 if (sema[i] != NULL) 1744 bcopy(sema[i], &semsi->semids[i], 1745 dssize); 1746 else 1747 bzero(&semsi->semids[i], dssize); 1748 break; 1749 #endif 1750 #ifdef SYSVSHM 1751 case KERN_SYSVIPC_SHM_INFO: 1752 if (shmsegs[i] != NULL) 1753 bcopy(shmsegs[i], &shmsi->shmids[i], 1754 dssize); 1755 else 1756 bzero(&shmsi->shmids[i], dssize); 1757 break; 1758 #endif 1759 } 1760 buflen -= dssize; 1761 } 1762 } 1763 *sizep -= buflen; 1764 error = copyout(buf, where, *sizep); 1765 free(buf, M_TEMP); 1766 /* If copyout succeeded, use return code set earlier. */ 1767 return (error ? error : ret); 1768 } 1769 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1770 1771 #ifndef SMALL_KERNEL 1772 1773 int 1774 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 1775 { 1776 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); 1777 } 1778 1779 1780 int 1781 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1782 void *newp, size_t newlen) 1783 { 1784 struct ksensor *ks; 1785 struct sensor *us; 1786 struct ksensordev *ksd; 1787 struct sensordev *usd; 1788 int dev, numt, ret; 1789 enum sensor_type type; 1790 1791 if (namelen != 1 && namelen != 3) 1792 return (ENOTDIR); 1793 1794 dev = name[0]; 1795 if (namelen == 1) { 1796 ksd = sensordev_get(dev); 1797 if (ksd == NULL) 1798 return (ENOENT); 1799 1800 /* Grab a copy, to clear the kernel pointers */ 1801 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); 1802 usd->num = ksd->num; 1803 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); 1804 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); 1805 usd->sensors_count = ksd->sensors_count; 1806 1807 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, 1808 sizeof(struct sensordev)); 1809 1810 free(usd, M_TEMP); 1811 return (ret); 1812 } 1813 1814 type = name[1]; 1815 numt = name[2]; 1816 1817 ks = sensor_find(dev, type, numt); 1818 if (ks == NULL) 1819 return (ENOENT); 1820 1821 /* Grab a copy, to clear the kernel pointers */ 1822 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); 1823 memcpy(us->desc, ks->desc, sizeof(us->desc)); 1824 us->tv = ks->tv; 1825 us->value = ks->value; 1826 us->type = ks->type; 1827 us->status = ks->status; 1828 us->numt = ks->numt; 1829 us->flags = ks->flags; 1830 1831 ret = sysctl_rdstruct(oldp, oldlenp, newp, us, 1832 sizeof(struct sensor)); 1833 free(us, M_TEMP); 1834 return (ret); 1835 } 1836 1837 int 1838 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1839 void *newp, size_t newlen) 1840 { 1841 int enabled, error; 1842 struct emul *e; 1843 1844 if (name[0] == KERN_EMUL_NUM) { 1845 if (namelen != 1) 1846 return (ENOTDIR); 1847 return (sysctl_rdint(oldp, oldlenp, newp, nexecs)); 1848 } 1849 1850 if (namelen != 2) 1851 return (ENOTDIR); 1852 if (name[0] > nexecs || name[0] < 0) 1853 return (EINVAL); 1854 e = execsw[name[0] - 1].es_emul; 1855 if (e == NULL) 1856 return (EINVAL); 1857 1858 switch (name[1]) { 1859 case KERN_EMUL_NAME: 1860 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name)); 1861 case KERN_EMUL_ENABLED: 1862 enabled = (e->e_flags & EMUL_ENABLED); 1863 error = sysctl_int(oldp, oldlenp, newp, newlen, 1864 &enabled); 1865 e->e_flags = (enabled & EMUL_ENABLED); 1866 return (error); 1867 default: 1868 return (EINVAL); 1869 } 1870 } 1871 1872 #endif /* SMALL_KERNEL */ 1873 1874 int 1875 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1876 void *newp, size_t newlen) 1877 { 1878 CPU_INFO_ITERATOR cii; 1879 struct cpu_info *ci; 1880 int i; 1881 1882 if (namelen != 1) 1883 return (ENOTDIR); 1884 1885 i = name[0]; 1886 1887 CPU_INFO_FOREACH(cii, ci) { 1888 if (i-- == 0) 1889 break; 1890 } 1891 if (i > 0) 1892 return (ENOENT); 1893 1894 return (sysctl_rdstruct(oldp, oldlenp, newp, 1895 &ci->ci_schedstate.spc_cp_time, 1896 sizeof(ci->ci_schedstate.spc_cp_time))); 1897 } 1898