1 /* $OpenBSD: kern_sysctl.c,v 1.169 2009/04/19 17:53:38 deraadt 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_NCPUFOUND: 568 return (sysctl_rdint(oldp, oldlenp, newp, ncpusfound)); 569 case HW_BYTEORDER: 570 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 571 case HW_PHYSMEM: 572 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem))); 573 case HW_USERMEM: 574 return (sysctl_rdint(oldp, oldlenp, newp, 575 ptoa(physmem - uvmexp.wired))); 576 case HW_PAGESIZE: 577 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 578 case HW_DISKNAMES: 579 err = sysctl_diskinit(0, p); 580 if (err) 581 return err; 582 if (disknames) 583 return (sysctl_rdstring(oldp, oldlenp, newp, 584 disknames)); 585 else 586 return (sysctl_rdstring(oldp, oldlenp, newp, "")); 587 case HW_DISKSTATS: 588 err = sysctl_diskinit(1, p); 589 if (err) 590 return err; 591 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, 592 disk_count * sizeof(struct diskstats))); 593 case HW_DISKCOUNT: 594 return (sysctl_rdint(oldp, oldlenp, newp, disk_count)); 595 #ifndef SMALL_KERNEL 596 case HW_SENSORS: 597 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, 598 newp, newlen)); 599 #endif 600 case HW_CPUSPEED: 601 if (!cpu_cpuspeed) 602 return (EOPNOTSUPP); 603 err = cpu_cpuspeed(&cpuspeed); 604 if (err) 605 return err; 606 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 607 case HW_SETPERF: 608 if (!cpu_setperf) 609 return (EOPNOTSUPP); 610 err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel); 611 if (err) 612 return err; 613 if (perflevel > 100) 614 perflevel = 100; 615 if (perflevel < 0) 616 perflevel = 0; 617 if (newp) 618 cpu_setperf(perflevel); 619 return (0); 620 case HW_VENDOR: 621 if (hw_vendor) 622 return (sysctl_rdstring(oldp, oldlenp, newp, 623 hw_vendor)); 624 else 625 return (EOPNOTSUPP); 626 case HW_PRODUCT: 627 if (hw_prod) 628 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod)); 629 else 630 return (EOPNOTSUPP); 631 case HW_VERSION: 632 if (hw_ver) 633 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver)); 634 else 635 return (EOPNOTSUPP); 636 case HW_SERIALNO: 637 if (hw_serial) 638 return (sysctl_rdstring(oldp, oldlenp, newp, 639 hw_serial)); 640 else 641 return (EOPNOTSUPP); 642 case HW_UUID: 643 if (hw_uuid) 644 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid)); 645 else 646 return (EOPNOTSUPP); 647 case HW_PHYSMEM64: 648 return (sysctl_rdquad(oldp, oldlenp, newp, 649 ptoa((psize_t)physmem))); 650 case HW_USERMEM64: 651 return (sysctl_rdquad(oldp, oldlenp, newp, 652 ptoa((psize_t)physmem - uvmexp.wired))); 653 default: 654 return (EOPNOTSUPP); 655 } 656 /* NOTREACHED */ 657 } 658 659 #ifdef DEBUG 660 /* 661 * Debugging related system variables. 662 */ 663 extern struct ctldebug debug0, debug1; 664 struct ctldebug debug2, debug3, debug4; 665 struct ctldebug debug5, debug6, debug7, debug8, debug9; 666 struct ctldebug debug10, debug11, debug12, debug13, debug14; 667 struct ctldebug debug15, debug16, debug17, debug18, debug19; 668 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 669 &debug0, &debug1, &debug2, &debug3, &debug4, 670 &debug5, &debug6, &debug7, &debug8, &debug9, 671 &debug10, &debug11, &debug12, &debug13, &debug14, 672 &debug15, &debug16, &debug17, &debug18, &debug19, 673 }; 674 int 675 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 676 size_t newlen, struct proc *p) 677 { 678 struct ctldebug *cdp; 679 680 /* all sysctl names at this level are name and field */ 681 if (namelen != 2) 682 return (ENOTDIR); /* overloaded */ 683 cdp = debugvars[name[0]]; 684 if (cdp->debugname == 0) 685 return (EOPNOTSUPP); 686 switch (name[1]) { 687 case CTL_DEBUG_NAME: 688 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 689 case CTL_DEBUG_VALUE: 690 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 691 default: 692 return (EOPNOTSUPP); 693 } 694 /* NOTREACHED */ 695 } 696 #endif /* DEBUG */ 697 698 /* 699 * Reads, or writes that lower the value 700 */ 701 int 702 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 703 { 704 unsigned int oval = *valp, val = *valp; 705 int error; 706 707 if (newp == NULL) 708 return (sysctl_rdint(oldp, oldlenp, newp, *valp)); 709 710 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) 711 return (error); 712 if (val > oval) 713 return (EPERM); /* do not allow raising */ 714 *(unsigned int *)valp = val; 715 return (0); 716 } 717 718 /* 719 * Validate parameters and get old / set new parameters 720 * for an integer-valued sysctl function. 721 */ 722 int 723 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 724 { 725 int error = 0; 726 727 if (oldp && *oldlenp < sizeof(int)) 728 return (ENOMEM); 729 if (newp && newlen != sizeof(int)) 730 return (EINVAL); 731 *oldlenp = sizeof(int); 732 if (oldp) 733 error = copyout(valp, oldp, sizeof(int)); 734 if (error == 0 && newp) 735 error = copyin(newp, valp, sizeof(int)); 736 return (error); 737 } 738 739 /* 740 * As above, but read-only. 741 */ 742 int 743 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) 744 { 745 int error = 0; 746 747 if (oldp && *oldlenp < sizeof(int)) 748 return (ENOMEM); 749 if (newp) 750 return (EPERM); 751 *oldlenp = sizeof(int); 752 if (oldp) 753 error = copyout((caddr_t)&val, oldp, sizeof(int)); 754 return (error); 755 } 756 757 /* 758 * Array of integer values. 759 */ 760 int 761 sysctl_int_arr(int **valpp, int *name, u_int namelen, void *oldp, 762 size_t *oldlenp, void *newp, size_t newlen) 763 { 764 if (namelen > 1) 765 return (ENOTDIR); 766 if (name[0] < 0 || valpp[name[0]] == NULL) 767 return (EOPNOTSUPP); 768 return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]])); 769 } 770 771 /* 772 * Validate parameters and get old / set new parameters 773 * for an integer-valued sysctl function. 774 */ 775 int 776 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 777 int64_t *valp) 778 { 779 int error = 0; 780 781 if (oldp && *oldlenp < sizeof(int64_t)) 782 return (ENOMEM); 783 if (newp && newlen != sizeof(int64_t)) 784 return (EINVAL); 785 *oldlenp = sizeof(int64_t); 786 if (oldp) 787 error = copyout(valp, oldp, sizeof(int64_t)); 788 if (error == 0 && newp) 789 error = copyin(newp, valp, sizeof(int64_t)); 790 return (error); 791 } 792 793 /* 794 * As above, but read-only. 795 */ 796 int 797 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val) 798 { 799 int error = 0; 800 801 if (oldp && *oldlenp < sizeof(int64_t)) 802 return (ENOMEM); 803 if (newp) 804 return (EPERM); 805 *oldlenp = sizeof(int64_t); 806 if (oldp) 807 error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); 808 return (error); 809 } 810 811 /* 812 * Validate parameters and get old / set new parameters 813 * for a string-valued sysctl function. 814 */ 815 int 816 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, 817 int maxlen) 818 { 819 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); 820 } 821 822 int 823 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 824 char *str, int maxlen) 825 { 826 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); 827 } 828 829 int 830 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 831 char *str, int maxlen, int trunc) 832 { 833 int len, error = 0; 834 char c; 835 836 len = strlen(str) + 1; 837 if (oldp && *oldlenp < len) { 838 if (trunc == 0 || *oldlenp == 0) 839 return (ENOMEM); 840 } 841 if (newp && newlen >= maxlen) 842 return (EINVAL); 843 if (oldp) { 844 if (trunc && *oldlenp < len) { 845 /* save & zap NUL terminator while copying */ 846 c = str[*oldlenp-1]; 847 str[*oldlenp-1] = '\0'; 848 error = copyout(str, oldp, *oldlenp); 849 str[*oldlenp-1] = c; 850 } else { 851 *oldlenp = len; 852 error = copyout(str, oldp, len); 853 } 854 } 855 if (error == 0 && newp) { 856 error = copyin(newp, str, newlen); 857 str[newlen] = 0; 858 } 859 return (error); 860 } 861 862 /* 863 * As above, but read-only. 864 */ 865 int 866 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) 867 { 868 int len, error = 0; 869 870 len = strlen(str) + 1; 871 if (oldp && *oldlenp < len) 872 return (ENOMEM); 873 if (newp) 874 return (EPERM); 875 *oldlenp = len; 876 if (oldp) 877 error = copyout(str, oldp, len); 878 return (error); 879 } 880 881 /* 882 * Validate parameters and get old / set new parameters 883 * for a structure oriented sysctl function. 884 */ 885 int 886 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, 887 int len) 888 { 889 int error = 0; 890 891 if (oldp && *oldlenp < len) 892 return (ENOMEM); 893 if (newp && newlen > len) 894 return (EINVAL); 895 if (oldp) { 896 *oldlenp = len; 897 error = copyout(sp, oldp, len); 898 } 899 if (error == 0 && newp) 900 error = copyin(newp, sp, len); 901 return (error); 902 } 903 904 /* 905 * Validate parameters and get old parameters 906 * for a structure oriented sysctl function. 907 */ 908 int 909 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 910 int len) 911 { 912 int error = 0; 913 914 if (oldp && *oldlenp < len) 915 return (ENOMEM); 916 if (newp) 917 return (EPERM); 918 *oldlenp = len; 919 if (oldp) 920 error = copyout(sp, oldp, len); 921 return (error); 922 } 923 924 /* 925 * Get file structures. 926 */ 927 int 928 sysctl_file(char *where, size_t *sizep, struct proc *p) 929 { 930 int buflen, error; 931 struct file *fp, cfile; 932 char *start = where; 933 struct ucred *cred = p->p_ucred; 934 935 buflen = *sizep; 936 if (where == NULL) { 937 /* 938 * overestimate by 10 files 939 */ 940 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 941 return (0); 942 } 943 944 /* 945 * first copyout filehead 946 */ 947 if (buflen < sizeof(filehead)) { 948 *sizep = 0; 949 return (0); 950 } 951 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 952 if (error) 953 return (error); 954 buflen -= sizeof(filehead); 955 where += sizeof(filehead); 956 957 /* 958 * followed by an array of file structures 959 */ 960 LIST_FOREACH(fp, &filehead, f_list) { 961 if (buflen < sizeof(struct file)) { 962 *sizep = where - start; 963 return (ENOMEM); 964 } 965 966 /* Only let the superuser or the owner see some information */ 967 bcopy(fp, &cfile, sizeof (struct file)); 968 if (suser(p, 0) != 0 && cred->cr_uid != fp->f_cred->cr_uid) { 969 cfile.f_offset = (off_t)-1; 970 cfile.f_rxfer = 0; 971 cfile.f_wxfer = 0; 972 cfile.f_rbytes = 0; 973 cfile.f_wbytes = 0; 974 } 975 error = copyout(&cfile, where, sizeof (struct file)); 976 if (error) 977 return (error); 978 buflen -= sizeof(struct file); 979 where += sizeof(struct file); 980 } 981 *sizep = where - start; 982 return (0); 983 } 984 985 #ifndef SMALL_KERNEL 986 987 /* 988 * try over estimating by 5 procs 989 */ 990 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 991 992 int 993 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) 994 { 995 struct kinfo_proc2 *kproc2 = NULL; 996 struct eproc *eproc = NULL; 997 struct proc *p; 998 char *dp; 999 int arg, buflen, doingzomb, elem_size, elem_count; 1000 int error, needed, type, op; 1001 1002 dp = where; 1003 buflen = where != NULL ? *sizep : 0; 1004 needed = error = 0; 1005 type = name[0]; 1006 1007 if (type == KERN_PROC) { 1008 if (namelen != 3 && !(namelen == 2 && 1009 (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD))) 1010 return (EINVAL); 1011 op = name[1]; 1012 arg = op == KERN_PROC_ALL ? 0 : name[2]; 1013 elem_size = elem_count = 0; 1014 eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK); 1015 } else /* if (type == KERN_PROC2) */ { 1016 if (namelen != 5 || name[3] < 0 || name[4] < 0) 1017 return (EINVAL); 1018 op = name[1]; 1019 arg = name[2]; 1020 elem_size = name[3]; 1021 elem_count = name[4]; 1022 kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK); 1023 } 1024 p = LIST_FIRST(&allproc); 1025 doingzomb = 0; 1026 again: 1027 for (; p != 0; p = LIST_NEXT(p, p_list)) { 1028 /* 1029 * Skip embryonic processes. 1030 */ 1031 if (p->p_stat == SIDL) 1032 continue; 1033 /* 1034 * TODO - make more efficient (see notes below). 1035 */ 1036 switch (op) { 1037 1038 case KERN_PROC_PID: 1039 /* could do this with just a lookup */ 1040 if (p->p_pid != (pid_t)arg) 1041 continue; 1042 break; 1043 1044 case KERN_PROC_PGRP: 1045 /* could do this by traversing pgrp */ 1046 if (p->p_pgrp->pg_id != (pid_t)arg) 1047 continue; 1048 break; 1049 1050 case KERN_PROC_SESSION: 1051 if (p->p_session->s_leader == NULL || 1052 p->p_session->s_leader->p_pid != (pid_t)arg) 1053 continue; 1054 break; 1055 1056 case KERN_PROC_TTY: 1057 if ((p->p_flag & P_CONTROLT) == 0 || 1058 p->p_session->s_ttyp == NULL || 1059 p->p_session->s_ttyp->t_dev != (dev_t)arg) 1060 continue; 1061 break; 1062 1063 case KERN_PROC_UID: 1064 if (p->p_ucred->cr_uid != (uid_t)arg) 1065 continue; 1066 break; 1067 1068 case KERN_PROC_RUID: 1069 if (p->p_cred->p_ruid != (uid_t)arg) 1070 continue; 1071 break; 1072 1073 case KERN_PROC_ALL: 1074 if (p->p_flag & P_SYSTEM) 1075 continue; 1076 break; 1077 case KERN_PROC_KTHREAD: 1078 /* no filtering */ 1079 break; 1080 default: 1081 error = EINVAL; 1082 goto err; 1083 } 1084 if (type == KERN_PROC) { 1085 if (buflen >= sizeof(struct kinfo_proc)) { 1086 fill_eproc(p, eproc); 1087 error = copyout((caddr_t)p, 1088 &((struct kinfo_proc *)dp)->kp_proc, 1089 sizeof(struct proc)); 1090 if (error) 1091 goto err; 1092 error = copyout((caddr_t)eproc, 1093 &((struct kinfo_proc *)dp)->kp_eproc, 1094 sizeof(*eproc)); 1095 if (error) 1096 goto err; 1097 dp += sizeof(struct kinfo_proc); 1098 buflen -= sizeof(struct kinfo_proc); 1099 } 1100 needed += sizeof(struct kinfo_proc); 1101 } else /* if (type == KERN_PROC2) */ { 1102 if (buflen >= elem_size && elem_count > 0) { 1103 fill_kproc2(p, kproc2); 1104 /* 1105 * Copy out elem_size, but not larger than 1106 * the size of a struct kinfo_proc2. 1107 */ 1108 error = copyout(kproc2, dp, 1109 min(sizeof(*kproc2), elem_size)); 1110 if (error) 1111 goto err; 1112 dp += elem_size; 1113 buflen -= elem_size; 1114 elem_count--; 1115 } 1116 needed += elem_size; 1117 } 1118 } 1119 if (doingzomb == 0) { 1120 p = LIST_FIRST(&zombproc); 1121 doingzomb++; 1122 goto again; 1123 } 1124 if (where != NULL) { 1125 *sizep = dp - where; 1126 if (needed > *sizep) { 1127 error = ENOMEM; 1128 goto err; 1129 } 1130 } else { 1131 needed += KERN_PROCSLOP; 1132 *sizep = needed; 1133 } 1134 err: 1135 if (eproc) 1136 free(eproc, M_TEMP); 1137 if (kproc2) 1138 free(kproc2, M_TEMP); 1139 return (error); 1140 } 1141 1142 #endif /* SMALL_KERNEL */ 1143 1144 /* 1145 * Fill in an eproc structure for the specified process. 1146 */ 1147 void 1148 fill_eproc(struct proc *p, struct eproc *ep) 1149 { 1150 struct tty *tp; 1151 1152 ep->e_paddr = p; 1153 ep->e_sess = p->p_pgrp->pg_session; 1154 ep->e_pcred = *p->p_cred; 1155 ep->e_ucred = *p->p_ucred; 1156 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1157 ep->e_vm.vm_rssize = 0; 1158 ep->e_vm.vm_tsize = 0; 1159 ep->e_vm.vm_dsize = 0; 1160 ep->e_vm.vm_ssize = 0; 1161 bzero(&ep->e_pstats, sizeof(ep->e_pstats)); 1162 ep->e_pstats_valid = 0; 1163 } else { 1164 struct vmspace *vm = p->p_vmspace; 1165 1166 ep->e_vm.vm_rssize = vm_resident_count(vm); 1167 ep->e_vm.vm_tsize = vm->vm_tsize; 1168 ep->e_vm.vm_dsize = vm->vm_dused; 1169 ep->e_vm.vm_ssize = vm->vm_ssize; 1170 ep->e_pstats = *p->p_stats; 1171 ep->e_pstats_valid = 1; 1172 } 1173 if (p->p_pptr) 1174 ep->e_ppid = p->p_pptr->p_pid; 1175 else 1176 ep->e_ppid = 0; 1177 ep->e_pgid = p->p_pgrp->pg_id; 1178 ep->e_jobc = p->p_pgrp->pg_jobc; 1179 if ((p->p_flag & P_CONTROLT) && 1180 (tp = ep->e_sess->s_ttyp)) { 1181 ep->e_tdev = tp->t_dev; 1182 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1183 ep->e_tsess = tp->t_session; 1184 } else 1185 ep->e_tdev = NODEV; 1186 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1187 if (SESS_LEADER(p)) 1188 ep->e_flag |= EPROC_SLEADER; 1189 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN); 1190 ep->e_wmesg[WMESGLEN] = '\0'; 1191 ep->e_xsize = ep->e_xrssize = 0; 1192 ep->e_xccount = ep->e_xswrss = 0; 1193 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1); 1194 ep->e_login[MAXLOGNAME-1] = '\0'; 1195 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN); 1196 ep->e_emul[EMULNAMELEN] = '\0'; 1197 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0; 1198 ep->e_limit = p->p_p->ps_limit; 1199 } 1200 1201 #ifndef SMALL_KERNEL 1202 1203 /* 1204 * Fill in a kproc2 structure for the specified process. 1205 */ 1206 void 1207 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 1208 { 1209 struct tty *tp; 1210 struct timeval ut, st; 1211 1212 bzero(ki, sizeof(*ki)); 1213 1214 ki->p_paddr = PTRTOINT64(p); 1215 ki->p_fd = PTRTOINT64(p->p_fd); 1216 ki->p_stats = PTRTOINT64(p->p_stats); 1217 ki->p_limit = PTRTOINT64(p->p_p->ps_limit); 1218 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 1219 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 1220 ki->p_sess = PTRTOINT64(p->p_session); 1221 ki->p_tsess = 0; /* may be changed if controlling tty below */ 1222 ki->p_ru = PTRTOINT64(p->p_ru); 1223 1224 ki->p_eflag = 0; 1225 ki->p_exitsig = p->p_exitsig; 1226 ki->p_flag = p->p_flag | P_INMEM; 1227 1228 ki->p_pid = p->p_pid; 1229 if (p->p_pptr) 1230 ki->p_ppid = p->p_pptr->p_pid; 1231 else 1232 ki->p_ppid = 0; 1233 if (p->p_session->s_leader) 1234 ki->p_sid = p->p_session->s_leader->p_pid; 1235 else 1236 ki->p_sid = 0; 1237 ki->p__pgid = p->p_pgrp->pg_id; 1238 1239 ki->p_tpgid = -1; /* may be changed if controlling tty below */ 1240 1241 ki->p_uid = p->p_ucred->cr_uid; 1242 ki->p_ruid = p->p_cred->p_ruid; 1243 ki->p_gid = p->p_ucred->cr_gid; 1244 ki->p_rgid = p->p_cred->p_rgid; 1245 ki->p_svuid = p->p_cred->p_svuid; 1246 ki->p_svgid = p->p_cred->p_svgid; 1247 1248 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 1249 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 1250 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 1251 1252 ki->p_jobc = p->p_pgrp->pg_jobc; 1253 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 1254 ki->p_tdev = tp->t_dev; 1255 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; 1256 ki->p_tsess = PTRTOINT64(tp->t_session); 1257 } else { 1258 ki->p_tdev = NODEV; 1259 } 1260 1261 ki->p_estcpu = p->p_estcpu; 1262 ki->p_rtime_sec = p->p_rtime.tv_sec; 1263 ki->p_rtime_usec = p->p_rtime.tv_usec; 1264 ki->p_cpticks = p->p_cpticks; 1265 ki->p_pctcpu = p->p_pctcpu; 1266 1267 ki->p_uticks = p->p_uticks; 1268 ki->p_sticks = p->p_sticks; 1269 ki->p_iticks = p->p_iticks; 1270 1271 ki->p_tracep = PTRTOINT64(p->p_tracep); 1272 ki->p_traceflag = p->p_traceflag; 1273 1274 ki->p_siglist = p->p_siglist; 1275 ki->p_sigmask = p->p_sigmask; 1276 ki->p_sigignore = p->p_sigignore; 1277 ki->p_sigcatch = p->p_sigcatch; 1278 1279 ki->p_stat = p->p_stat; 1280 ki->p_nice = p->p_nice; 1281 1282 ki->p_xstat = p->p_xstat; 1283 ki->p_acflag = p->p_acflag; 1284 1285 strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul)); 1286 strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm)); 1287 strncpy(ki->p_login, p->p_session->s_login, 1288 min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login))); 1289 1290 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1291 ki->p_vm_rssize = 0; 1292 ki->p_vm_tsize = 0; 1293 ki->p_vm_dsize = 0; 1294 ki->p_vm_ssize = 0; 1295 } else { 1296 struct vmspace *vm = p->p_vmspace; 1297 1298 ki->p_vm_rssize = vm_resident_count(vm); 1299 ki->p_vm_tsize = vm->vm_tsize; 1300 ki->p_vm_dsize = vm->vm_dused; 1301 ki->p_vm_ssize = vm->vm_ssize; 1302 ki->p_forw = ki->p_back = 0; 1303 ki->p_addr = PTRTOINT64(p->p_addr); 1304 ki->p_stat = p->p_stat; 1305 ki->p_swtime = p->p_swtime; 1306 ki->p_slptime = p->p_slptime; 1307 ki->p_schedflags = 0; 1308 ki->p_holdcnt = 1; 1309 ki->p_priority = p->p_priority; 1310 ki->p_usrpri = p->p_usrpri; 1311 if (p->p_wmesg) 1312 strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg)); 1313 ki->p_wchan = PTRTOINT64(p->p_wchan); 1314 1315 } 1316 1317 if (p->p_session->s_ttyvp) 1318 ki->p_eflag |= EPROC_CTTY; 1319 if (SESS_LEADER(p)) 1320 ki->p_eflag |= EPROC_SLEADER; 1321 if (p->p_rlimit) 1322 ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur; 1323 1324 /* XXX Is this double check necessary? */ 1325 if (P_ZOMBIE(p)) { 1326 ki->p_uvalid = 0; 1327 } else { 1328 ki->p_uvalid = 1; 1329 1330 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 1331 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 1332 1333 calcru(p, &ut, &st, NULL); 1334 ki->p_uutime_sec = ut.tv_sec; 1335 ki->p_uutime_usec = ut.tv_usec; 1336 ki->p_ustime_sec = st.tv_sec; 1337 ki->p_ustime_usec = st.tv_usec; 1338 1339 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 1340 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 1341 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 1342 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 1343 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 1344 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 1345 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 1346 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 1347 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 1348 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 1349 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 1350 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 1351 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 1352 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 1353 1354 timeradd(&p->p_stats->p_cru.ru_utime, 1355 &p->p_stats->p_cru.ru_stime, &ut); 1356 ki->p_uctime_sec = ut.tv_sec; 1357 ki->p_uctime_usec = ut.tv_usec; 1358 ki->p_cpuid = KI_NOCPU; 1359 #ifdef MULTIPROCESSOR 1360 if (p->p_cpu != NULL) 1361 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); 1362 #endif 1363 } 1364 } 1365 1366 int 1367 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1368 struct proc *cp) 1369 { 1370 struct proc *vp; 1371 pid_t pid; 1372 struct ps_strings pss; 1373 struct iovec iov; 1374 struct uio uio; 1375 int error, cnt, op; 1376 size_t limit; 1377 char **rargv, **vargv; /* reader vs. victim */ 1378 char *rarg, *varg, *buf; 1379 struct vmspace *vm; 1380 1381 if (namelen > 2) 1382 return (ENOTDIR); 1383 if (namelen < 2) 1384 return (EINVAL); 1385 1386 pid = name[0]; 1387 op = name[1]; 1388 1389 switch (op) { 1390 case KERN_PROC_ARGV: 1391 case KERN_PROC_NARGV: 1392 case KERN_PROC_ENV: 1393 case KERN_PROC_NENV: 1394 break; 1395 default: 1396 return (EOPNOTSUPP); 1397 } 1398 1399 if ((vp = pfind(pid)) == NULL) 1400 return (ESRCH); 1401 1402 if (oldp == NULL) { 1403 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) 1404 *oldlenp = sizeof(int); 1405 else 1406 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1407 return (0); 1408 } 1409 1410 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM)) 1411 return (EINVAL); 1412 1413 /* Exiting - don't bother, it will be gone soon anyway */ 1414 if ((vp->p_flag & P_WEXIT)) 1415 return (ESRCH); 1416 1417 /* Execing - danger. */ 1418 if ((vp->p_flag & P_INEXEC)) 1419 return (EBUSY); 1420 1421 vm = vp->p_vmspace; 1422 vm->vm_refcnt++; 1423 vp = NULL; 1424 1425 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1426 1427 iov.iov_base = &pss; 1428 iov.iov_len = sizeof(pss); 1429 uio.uio_iov = &iov; 1430 uio.uio_iovcnt = 1; 1431 uio.uio_offset = (off_t)PS_STRINGS; 1432 uio.uio_resid = sizeof(pss); 1433 uio.uio_segflg = UIO_SYSSPACE; 1434 uio.uio_rw = UIO_READ; 1435 uio.uio_procp = cp; 1436 1437 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1438 goto out; 1439 1440 if (op == KERN_PROC_NARGV) { 1441 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 1442 goto out; 1443 } 1444 if (op == KERN_PROC_NENV) { 1445 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 1446 goto out; 1447 } 1448 1449 if (op == KERN_PROC_ARGV) { 1450 cnt = pss.ps_nargvstr; 1451 vargv = pss.ps_argvstr; 1452 } else { 1453 cnt = pss.ps_nenvstr; 1454 vargv = pss.ps_envstr; 1455 } 1456 1457 /* -1 to have space for a terminating NUL */ 1458 limit = *oldlenp - 1; 1459 *oldlenp = 0; 1460 1461 rargv = oldp; 1462 1463 /* 1464 * *oldlenp - number of bytes copied out into readers buffer. 1465 * limit - maximal number of bytes allowed into readers buffer. 1466 * rarg - pointer into readers buffer where next arg will be stored. 1467 * rargv - pointer into readers buffer where the next rarg pointer 1468 * will be stored. 1469 * vargv - pointer into victim address space where the next argument 1470 * will be read. 1471 */ 1472 1473 /* space for cnt pointers and a NULL */ 1474 rarg = (char *)(rargv + cnt + 1); 1475 *oldlenp += (cnt + 1) * sizeof(char **); 1476 1477 while (cnt > 0 && *oldlenp < limit) { 1478 size_t len, vstrlen; 1479 1480 /* Write to readers argv */ 1481 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 1482 goto out; 1483 1484 /* read the victim argv */ 1485 iov.iov_base = &varg; 1486 iov.iov_len = sizeof(varg); 1487 uio.uio_iov = &iov; 1488 uio.uio_iovcnt = 1; 1489 uio.uio_offset = (off_t)(vaddr_t)vargv; 1490 uio.uio_resid = sizeof(varg); 1491 uio.uio_segflg = UIO_SYSSPACE; 1492 uio.uio_rw = UIO_READ; 1493 uio.uio_procp = cp; 1494 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1495 goto out; 1496 1497 if (varg == NULL) 1498 break; 1499 1500 /* 1501 * read the victim arg. We must jump through hoops to avoid 1502 * crossing a page boundary too much and returning an error. 1503 */ 1504 more: 1505 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 1506 /* leave space for the terminating NUL */ 1507 iov.iov_base = buf; 1508 iov.iov_len = len; 1509 uio.uio_iov = &iov; 1510 uio.uio_iovcnt = 1; 1511 uio.uio_offset = (off_t)(vaddr_t)varg; 1512 uio.uio_resid = len; 1513 uio.uio_segflg = UIO_SYSSPACE; 1514 uio.uio_rw = UIO_READ; 1515 uio.uio_procp = cp; 1516 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1517 goto out; 1518 1519 for (vstrlen = 0; vstrlen < len; vstrlen++) { 1520 if (buf[vstrlen] == '\0') 1521 break; 1522 } 1523 1524 /* Don't overflow readers buffer. */ 1525 if (*oldlenp + vstrlen + 1 >= limit) { 1526 error = ENOMEM; 1527 goto out; 1528 } 1529 1530 if ((error = copyout(buf, rarg, vstrlen)) != 0) 1531 goto out; 1532 1533 *oldlenp += vstrlen; 1534 rarg += vstrlen; 1535 1536 /* The string didn't end in this page? */ 1537 if (vstrlen == len) { 1538 varg += vstrlen; 1539 goto more; 1540 } 1541 1542 /* End of string. Terminate it with a NUL */ 1543 buf[0] = '\0'; 1544 if ((error = copyout(buf, rarg, 1)) != 0) 1545 goto out; 1546 *oldlenp += 1; 1547 rarg += 1; 1548 1549 vargv++; 1550 rargv++; 1551 cnt--; 1552 } 1553 1554 if (*oldlenp >= limit) { 1555 error = ENOMEM; 1556 goto out; 1557 } 1558 1559 /* Write the terminating null */ 1560 rarg = NULL; 1561 error = copyout(&rarg, rargv, sizeof(rarg)); 1562 1563 out: 1564 uvmspace_free(vm); 1565 free(buf, M_TEMP); 1566 return (error); 1567 } 1568 1569 #endif 1570 1571 /* 1572 * Initialize disknames/diskstats for export by sysctl. If update is set, 1573 * then we simply update the disk statistics information. 1574 */ 1575 int 1576 sysctl_diskinit(int update, struct proc *p) 1577 { 1578 struct diskstats *sdk; 1579 struct disk *dk; 1580 int i, tlen, l; 1581 1582 if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) 1583 return i; 1584 1585 if (disk_change) { 1586 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk; 1587 dk = TAILQ_NEXT(dk, dk_link)) 1588 tlen += strlen(dk->dk_name) + 1; 1589 tlen++; 1590 1591 if (disknames) 1592 free(disknames, M_SYSCTL); 1593 if (diskstats) 1594 free(diskstats, M_SYSCTL); 1595 diskstats = NULL; 1596 disknames = NULL; 1597 diskstats = malloc(disk_count * sizeof(struct diskstats), 1598 M_SYSCTL, M_WAITOK); 1599 disknames = malloc(tlen, M_SYSCTL, M_WAITOK); 1600 disknames[0] = '\0'; 1601 1602 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk; 1603 dk = TAILQ_NEXT(dk, dk_link), i++) { 1604 snprintf(disknames + l, tlen - l, "%s,", 1605 dk->dk_name ? dk->dk_name : ""); 1606 l += strlen(disknames + l); 1607 sdk = diskstats + i; 1608 strlcpy(sdk->ds_name, dk->dk_name, 1609 sizeof(sdk->ds_name)); 1610 mtx_enter(&dk->dk_mtx); 1611 sdk->ds_busy = dk->dk_busy; 1612 sdk->ds_rxfer = dk->dk_rxfer; 1613 sdk->ds_wxfer = dk->dk_wxfer; 1614 sdk->ds_seek = dk->dk_seek; 1615 sdk->ds_rbytes = dk->dk_rbytes; 1616 sdk->ds_wbytes = dk->dk_wbytes; 1617 sdk->ds_attachtime = dk->dk_attachtime; 1618 sdk->ds_timestamp = dk->dk_timestamp; 1619 sdk->ds_time = dk->dk_time; 1620 mtx_leave(&dk->dk_mtx); 1621 } 1622 1623 /* Eliminate trailing comma */ 1624 if (l != 0) 1625 disknames[l - 1] = '\0'; 1626 disk_change = 0; 1627 } else if (update) { 1628 /* Just update, number of drives hasn't changed */ 1629 for (dk = TAILQ_FIRST(&disklist), i = 0; dk; 1630 dk = TAILQ_NEXT(dk, dk_link), i++) { 1631 sdk = diskstats + i; 1632 strlcpy(sdk->ds_name, dk->dk_name, 1633 sizeof(sdk->ds_name)); 1634 mtx_enter(&dk->dk_mtx); 1635 sdk->ds_busy = dk->dk_busy; 1636 sdk->ds_rxfer = dk->dk_rxfer; 1637 sdk->ds_wxfer = dk->dk_wxfer; 1638 sdk->ds_seek = dk->dk_seek; 1639 sdk->ds_rbytes = dk->dk_rbytes; 1640 sdk->ds_wbytes = dk->dk_wbytes; 1641 sdk->ds_attachtime = dk->dk_attachtime; 1642 sdk->ds_timestamp = dk->dk_timestamp; 1643 sdk->ds_time = dk->dk_time; 1644 mtx_leave(&dk->dk_mtx); 1645 } 1646 } 1647 rw_exit_write(&sysctl_disklock); 1648 return 0; 1649 } 1650 1651 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1652 int 1653 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 1654 { 1655 #ifdef SYSVMSG 1656 struct msg_sysctl_info *msgsi; 1657 #endif 1658 #ifdef SYSVSEM 1659 struct sem_sysctl_info *semsi; 1660 #endif 1661 #ifdef SYSVSHM 1662 struct shm_sysctl_info *shmsi; 1663 #endif 1664 size_t infosize, dssize, tsize, buflen; 1665 int i, nds, error, ret; 1666 void *buf; 1667 1668 if (namelen != 1) 1669 return (EINVAL); 1670 1671 buflen = *sizep; 1672 1673 switch (*name) { 1674 case KERN_SYSVIPC_MSG_INFO: 1675 #ifdef SYSVMSG 1676 infosize = sizeof(msgsi->msginfo); 1677 nds = msginfo.msgmni; 1678 dssize = sizeof(msgsi->msgids[0]); 1679 break; 1680 #else 1681 return (EOPNOTSUPP); 1682 #endif 1683 case KERN_SYSVIPC_SEM_INFO: 1684 #ifdef SYSVSEM 1685 infosize = sizeof(semsi->seminfo); 1686 nds = seminfo.semmni; 1687 dssize = sizeof(semsi->semids[0]); 1688 break; 1689 #else 1690 return (EOPNOTSUPP); 1691 #endif 1692 case KERN_SYSVIPC_SHM_INFO: 1693 #ifdef SYSVSHM 1694 infosize = sizeof(shmsi->shminfo); 1695 nds = shminfo.shmmni; 1696 dssize = sizeof(shmsi->shmids[0]); 1697 break; 1698 #else 1699 return (EOPNOTSUPP); 1700 #endif 1701 default: 1702 return (EINVAL); 1703 } 1704 tsize = infosize + (nds * dssize); 1705 1706 /* Return just the total size required. */ 1707 if (where == NULL) { 1708 *sizep = tsize; 1709 return (0); 1710 } 1711 1712 /* Not enough room for even the info struct. */ 1713 if (buflen < infosize) { 1714 *sizep = 0; 1715 return (ENOMEM); 1716 } 1717 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK|M_ZERO); 1718 1719 switch (*name) { 1720 #ifdef SYSVMSG 1721 case KERN_SYSVIPC_MSG_INFO: 1722 msgsi = (struct msg_sysctl_info *)buf; 1723 msgsi->msginfo = msginfo; 1724 break; 1725 #endif 1726 #ifdef SYSVSEM 1727 case KERN_SYSVIPC_SEM_INFO: 1728 semsi = (struct sem_sysctl_info *)buf; 1729 semsi->seminfo = seminfo; 1730 break; 1731 #endif 1732 #ifdef SYSVSHM 1733 case KERN_SYSVIPC_SHM_INFO: 1734 shmsi = (struct shm_sysctl_info *)buf; 1735 shmsi->shminfo = shminfo; 1736 break; 1737 #endif 1738 } 1739 buflen -= infosize; 1740 1741 ret = 0; 1742 if (buflen > 0) { 1743 /* Fill in the IPC data structures. */ 1744 for (i = 0; i < nds; i++) { 1745 if (buflen < dssize) { 1746 ret = ENOMEM; 1747 break; 1748 } 1749 switch (*name) { 1750 #ifdef SYSVMSG 1751 case KERN_SYSVIPC_MSG_INFO: 1752 bcopy(&msqids[i], &msgsi->msgids[i], dssize); 1753 break; 1754 #endif 1755 #ifdef SYSVSEM 1756 case KERN_SYSVIPC_SEM_INFO: 1757 if (sema[i] != NULL) 1758 bcopy(sema[i], &semsi->semids[i], 1759 dssize); 1760 else 1761 bzero(&semsi->semids[i], dssize); 1762 break; 1763 #endif 1764 #ifdef SYSVSHM 1765 case KERN_SYSVIPC_SHM_INFO: 1766 if (shmsegs[i] != NULL) 1767 bcopy(shmsegs[i], &shmsi->shmids[i], 1768 dssize); 1769 else 1770 bzero(&shmsi->shmids[i], dssize); 1771 break; 1772 #endif 1773 } 1774 buflen -= dssize; 1775 } 1776 } 1777 *sizep -= buflen; 1778 error = copyout(buf, where, *sizep); 1779 free(buf, M_TEMP); 1780 /* If copyout succeeded, use return code set earlier. */ 1781 return (error ? error : ret); 1782 } 1783 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1784 1785 #ifndef SMALL_KERNEL 1786 1787 int 1788 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 1789 { 1790 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); 1791 } 1792 1793 1794 int 1795 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1796 void *newp, size_t newlen) 1797 { 1798 struct ksensor *ks; 1799 struct sensor *us; 1800 struct ksensordev *ksd; 1801 struct sensordev *usd; 1802 int dev, numt, ret; 1803 enum sensor_type type; 1804 1805 if (namelen != 1 && namelen != 3) 1806 return (ENOTDIR); 1807 1808 dev = name[0]; 1809 if (namelen == 1) { 1810 ksd = sensordev_get(dev); 1811 if (ksd == NULL) 1812 return (ENOENT); 1813 1814 /* Grab a copy, to clear the kernel pointers */ 1815 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); 1816 usd->num = ksd->num; 1817 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); 1818 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); 1819 usd->sensors_count = ksd->sensors_count; 1820 1821 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, 1822 sizeof(struct sensordev)); 1823 1824 free(usd, M_TEMP); 1825 return (ret); 1826 } 1827 1828 type = name[1]; 1829 numt = name[2]; 1830 1831 ks = sensor_find(dev, type, numt); 1832 if (ks == NULL) 1833 return (ENOENT); 1834 1835 /* Grab a copy, to clear the kernel pointers */ 1836 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); 1837 memcpy(us->desc, ks->desc, sizeof(us->desc)); 1838 us->tv = ks->tv; 1839 us->value = ks->value; 1840 us->type = ks->type; 1841 us->status = ks->status; 1842 us->numt = ks->numt; 1843 us->flags = ks->flags; 1844 1845 ret = sysctl_rdstruct(oldp, oldlenp, newp, us, 1846 sizeof(struct sensor)); 1847 free(us, M_TEMP); 1848 return (ret); 1849 } 1850 1851 int 1852 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1853 void *newp, size_t newlen) 1854 { 1855 int enabled, error; 1856 struct emul *e; 1857 1858 if (name[0] == KERN_EMUL_NUM) { 1859 if (namelen != 1) 1860 return (ENOTDIR); 1861 return (sysctl_rdint(oldp, oldlenp, newp, nexecs)); 1862 } 1863 1864 if (namelen != 2) 1865 return (ENOTDIR); 1866 if (name[0] > nexecs || name[0] < 0) 1867 return (EINVAL); 1868 e = execsw[name[0] - 1].es_emul; 1869 if (e == NULL) 1870 return (EINVAL); 1871 1872 switch (name[1]) { 1873 case KERN_EMUL_NAME: 1874 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name)); 1875 case KERN_EMUL_ENABLED: 1876 enabled = (e->e_flags & EMUL_ENABLED); 1877 error = sysctl_int(oldp, oldlenp, newp, newlen, 1878 &enabled); 1879 e->e_flags = (enabled & EMUL_ENABLED); 1880 return (error); 1881 default: 1882 return (EINVAL); 1883 } 1884 } 1885 1886 #endif /* SMALL_KERNEL */ 1887 1888 int 1889 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1890 void *newp, size_t newlen) 1891 { 1892 CPU_INFO_ITERATOR cii; 1893 struct cpu_info *ci; 1894 int i; 1895 1896 if (namelen != 1) 1897 return (ENOTDIR); 1898 1899 i = name[0]; 1900 1901 CPU_INFO_FOREACH(cii, ci) { 1902 if (i-- == 0) 1903 break; 1904 } 1905 if (i > 0) 1906 return (ENOENT); 1907 1908 return (sysctl_rdstruct(oldp, oldlenp, newp, 1909 &ci->ci_schedstate.spc_cp_time, 1910 sizeof(ci->ci_schedstate.spc_cp_time))); 1911 } 1912