1 /* $OpenBSD: kern_sysctl.c,v 1.226 2012/06/02 05:44:27 guenther 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/signalvar.h> 49 #include <sys/file.h> 50 #include <sys/filedesc.h> 51 #include <sys/vnode.h> 52 #include <sys/unistd.h> 53 #include <sys/buf.h> 54 #include <sys/ioctl.h> 55 #include <sys/tty.h> 56 #include <sys/disklabel.h> 57 #include <sys/disk.h> 58 #include <uvm/uvm_extern.h> 59 #include <sys/sysctl.h> 60 #include <sys/msgbuf.h> 61 #include <sys/dkstat.h> 62 #include <sys/vmmeter.h> 63 #include <sys/namei.h> 64 #include <sys/exec.h> 65 #include <sys/mbuf.h> 66 #include <sys/sensors.h> 67 #include <sys/pipe.h> 68 #include <sys/eventvar.h> 69 #include <sys/socketvar.h> 70 #include <sys/socket.h> 71 #include <sys/domain.h> 72 #include <sys/protosw.h> 73 #ifdef __HAVE_TIMECOUNTER 74 #include <sys/timetc.h> 75 #endif 76 #include <sys/evcount.h> 77 #include <sys/unpcb.h> 78 79 #include <sys/mount.h> 80 #include <sys/syscallargs.h> 81 82 #include <dev/cons.h> 83 #include <dev/rndvar.h> 84 #include <dev/systrace.h> 85 86 #include <net/route.h> 87 #include <netinet/in.h> 88 #include <netinet/in_systm.h> 89 #include <netinet/ip.h> 90 #include <netinet/in_pcb.h> 91 #include <netinet/ip6.h> 92 #include <netinet6/ip6_var.h> 93 94 #ifdef DDB 95 #include <ddb/db_var.h> 96 #endif 97 98 #ifdef SYSVMSG 99 #include <sys/msg.h> 100 #endif 101 #ifdef SYSVSEM 102 #include <sys/sem.h> 103 #endif 104 #ifdef SYSVSHM 105 #include <sys/shm.h> 106 #endif 107 108 extern struct forkstat forkstat; 109 extern struct nchstats nchstats; 110 extern int nselcoll, fscale; 111 extern struct disklist_head disklist; 112 extern fixpt_t ccpu; 113 extern long numvnodes; 114 extern u_int mcllivelocks; 115 116 extern void nmbclust_update(void); 117 118 int sysctl_diskinit(int, struct proc *); 119 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); 120 int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *); 121 int sysctl_intrcnt(int *, u_int, void *, size_t *); 122 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); 123 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t); 124 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t); 125 126 int (*cpu_cpuspeed)(int *); 127 void (*cpu_setperf)(int); 128 int perflevel = 100; 129 130 int rthreads_enabled = 1; 131 132 /* 133 * Lock to avoid too many processes vslocking a large amount of memory 134 * at the same time. 135 */ 136 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk"); 137 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk"); 138 139 int 140 sys___sysctl(struct proc *p, void *v, register_t *retval) 141 { 142 struct sys___sysctl_args /* { 143 syscallarg(int *) name; 144 syscallarg(u_int) namelen; 145 syscallarg(void *) old; 146 syscallarg(size_t *) oldlenp; 147 syscallarg(void *) new; 148 syscallarg(size_t) newlen; 149 } */ *uap = v; 150 int error, dolock = 1; 151 size_t savelen = 0, oldlen = 0; 152 sysctlfn *fn; 153 int name[CTL_MAXNAME]; 154 155 if (SCARG(uap, new) != NULL && 156 (error = suser(p, 0))) 157 return (error); 158 /* 159 * all top-level sysctl names are non-terminal 160 */ 161 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 162 return (EINVAL); 163 error = copyin(SCARG(uap, name), name, 164 SCARG(uap, namelen) * sizeof(int)); 165 if (error) 166 return (error); 167 168 switch (name[0]) { 169 case CTL_KERN: 170 fn = kern_sysctl; 171 if (name[1] == KERN_VNODE) /* XXX */ 172 dolock = 0; 173 break; 174 case CTL_HW: 175 fn = hw_sysctl; 176 break; 177 case CTL_VM: 178 fn = uvm_sysctl; 179 break; 180 case CTL_NET: 181 fn = net_sysctl; 182 break; 183 case CTL_FS: 184 fn = fs_sysctl; 185 break; 186 case CTL_VFS: 187 fn = vfs_sysctl; 188 break; 189 case CTL_MACHDEP: 190 fn = cpu_sysctl; 191 break; 192 #ifdef DEBUG 193 case CTL_DEBUG: 194 fn = debug_sysctl; 195 break; 196 #endif 197 #ifdef DDB 198 case CTL_DDB: 199 fn = ddb_sysctl; 200 break; 201 #endif 202 default: 203 return (EOPNOTSUPP); 204 } 205 206 if (SCARG(uap, oldlenp) && 207 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) 208 return (error); 209 if (SCARG(uap, old) != NULL) { 210 if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0) 211 return (error); 212 if (dolock) { 213 if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) { 214 rw_exit_write(&sysctl_lock); 215 return (ENOMEM); 216 } 217 error = uvm_vslock(p, SCARG(uap, old), oldlen, 218 VM_PROT_READ|VM_PROT_WRITE); 219 if (error) { 220 rw_exit_write(&sysctl_lock); 221 return (error); 222 } 223 } 224 savelen = oldlen; 225 } 226 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old), 227 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); 228 if (SCARG(uap, old) != NULL) { 229 if (dolock) 230 uvm_vsunlock(p, SCARG(uap, old), savelen); 231 rw_exit_write(&sysctl_lock); 232 } 233 if (error) 234 return (error); 235 if (SCARG(uap, oldlenp)) 236 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 237 return (error); 238 } 239 240 /* 241 * Attributes stored in the kernel. 242 */ 243 char hostname[MAXHOSTNAMELEN]; 244 int hostnamelen; 245 char domainname[MAXHOSTNAMELEN]; 246 int domainnamelen; 247 long hostid; 248 char *disknames = NULL; 249 struct diskstats *diskstats = NULL; 250 #ifdef INSECURE 251 int securelevel = -1; 252 #else 253 int securelevel; 254 #endif 255 256 /* 257 * kernel related system variables. 258 */ 259 int 260 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 261 size_t newlen, struct proc *p) 262 { 263 int error, level, inthostid, stackgap; 264 dev_t dev; 265 extern int somaxconn, sominconn; 266 extern int usermount, nosuidcoredump; 267 extern long cp_time[CPUSTATES]; 268 extern int stackgap_random; 269 #ifdef CRYPTO 270 extern int usercrypto; 271 extern int userasymcrypto; 272 extern int cryptodevallowsoft; 273 #endif 274 extern int maxlocksperuid; 275 extern int pool_debug; 276 277 /* all sysctl names at this level are terminal except a ton of them */ 278 if (namelen != 1) { 279 switch (name[0]) { 280 case KERN_PROC: 281 case KERN_PROF: 282 case KERN_MALLOCSTATS: 283 case KERN_TTY: 284 case KERN_POOL: 285 case KERN_PROC_ARGS: 286 case KERN_PROC_CWD: 287 case KERN_SYSVIPC_INFO: 288 case KERN_SEMINFO: 289 case KERN_SHMINFO: 290 case KERN_INTRCNT: 291 case KERN_WATCHDOG: 292 case KERN_EMUL: 293 case KERN_EVCOUNT: 294 #ifdef __HAVE_TIMECOUNTER 295 case KERN_TIMECOUNTER: 296 #endif 297 case KERN_CPTIME2: 298 case KERN_FILE2: 299 break; 300 default: 301 return (ENOTDIR); /* overloaded */ 302 } 303 } 304 305 switch (name[0]) { 306 case KERN_OSTYPE: 307 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 308 case KERN_OSRELEASE: 309 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 310 case KERN_OSREV: 311 return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD)); 312 case KERN_OSVERSION: 313 return (sysctl_rdstring(oldp, oldlenp, newp, osversion)); 314 case KERN_VERSION: 315 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 316 case KERN_MAXVNODES: 317 return(sysctl_int(oldp, oldlenp, newp, newlen, &maxvnodes)); 318 case KERN_MAXPROC: 319 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxprocess)); 320 case KERN_MAXFILES: 321 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 322 case KERN_NFILES: 323 return (sysctl_rdint(oldp, oldlenp, newp, nfiles)); 324 case KERN_TTYCOUNT: 325 return (sysctl_rdint(oldp, oldlenp, newp, tty_count)); 326 case KERN_NUMVNODES: 327 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes)); 328 case KERN_ARGMAX: 329 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 330 case KERN_NSELCOLL: 331 return (sysctl_rdint(oldp, oldlenp, newp, nselcoll)); 332 case KERN_SECURELVL: 333 level = securelevel; 334 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 335 newp == NULL) 336 return (error); 337 if ((securelevel > 0 || level < -1) && 338 level < securelevel && p->p_pid != 1) 339 return (EPERM); 340 securelevel = level; 341 return (0); 342 case KERN_HOSTNAME: 343 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 344 hostname, sizeof(hostname)); 345 if (newp && !error) 346 hostnamelen = newlen; 347 return (error); 348 case KERN_DOMAINNAME: 349 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 350 domainname, sizeof(domainname)); 351 if (newp && !error) 352 domainnamelen = newlen; 353 return (error); 354 case KERN_HOSTID: 355 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 356 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 357 hostid = inthostid; 358 return (error); 359 case KERN_CLOCKRATE: 360 return (sysctl_clockrate(oldp, oldlenp, newp)); 361 case KERN_BOOTTIME: 362 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 363 sizeof(struct timeval))); 364 case KERN_VNODE: 365 return (sysctl_vnode(oldp, oldlenp, p)); 366 #ifndef SMALL_KERNEL 367 case KERN_PROC: 368 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 369 case KERN_PROC_ARGS: 370 return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp, 371 p)); 372 case KERN_PROC_CWD: 373 return (sysctl_proc_cwd(name + 1, namelen - 1, oldp, oldlenp, 374 p)); 375 case KERN_FILE2: 376 return (sysctl_file2(name + 1, namelen - 1, oldp, oldlenp, p)); 377 #endif 378 case KERN_FILE: 379 return (sysctl_file(oldp, oldlenp, p)); 380 case KERN_MBSTAT: 381 return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat, 382 sizeof(mbstat))); 383 #ifdef GPROF 384 case KERN_PROF: 385 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 386 newp, newlen)); 387 #endif 388 case KERN_POSIX1: 389 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 390 case KERN_NGROUPS: 391 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 392 case KERN_JOB_CONTROL: 393 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 394 case KERN_SAVED_IDS: 395 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 396 case KERN_MAXPARTITIONS: 397 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 398 case KERN_RAWPARTITION: 399 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 400 case KERN_MAXTHREAD: 401 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxthread)); 402 case KERN_NTHREADS: 403 return (sysctl_rdint(oldp, oldlenp, newp, nthreads)); 404 case KERN_SOMAXCONN: 405 return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn)); 406 case KERN_SOMINCONN: 407 return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn)); 408 case KERN_USERMOUNT: 409 return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount)); 410 case KERN_RND: 411 return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats, 412 sizeof(rndstats))); 413 case KERN_ARND: { 414 char buf[256]; 415 416 if (*oldlenp > sizeof(buf)) 417 *oldlenp = sizeof(buf); 418 if (oldp) { 419 arc4random_buf(buf, *oldlenp); 420 if ((error = copyout(buf, oldp, *oldlenp))) 421 return (error); 422 } 423 return (0); 424 } 425 case KERN_NOSUIDCOREDUMP: 426 return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump)); 427 case KERN_FSYNC: 428 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 429 case KERN_SYSVMSG: 430 #ifdef SYSVMSG 431 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 432 #else 433 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 434 #endif 435 case KERN_SYSVSEM: 436 #ifdef SYSVSEM 437 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 438 #else 439 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 440 #endif 441 case KERN_SYSVSHM: 442 #ifdef SYSVSHM 443 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 444 #else 445 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 446 #endif 447 case KERN_MSGBUFSIZE: 448 /* 449 * deal with cases where the message buffer has 450 * become corrupted. 451 */ 452 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 453 return (ENXIO); 454 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 455 case KERN_MSGBUF: 456 /* see note above */ 457 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 458 return (ENXIO); 459 return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp, 460 msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); 461 case KERN_MALLOCSTATS: 462 return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp, 463 newp, newlen, p)); 464 case KERN_CPTIME: 465 { 466 CPU_INFO_ITERATOR cii; 467 struct cpu_info *ci; 468 int i; 469 470 bzero(cp_time, sizeof(cp_time)); 471 472 CPU_INFO_FOREACH(cii, ci) { 473 for (i = 0; i < CPUSTATES; i++) 474 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 475 } 476 477 for (i = 0; i < CPUSTATES; i++) 478 cp_time[i] /= ncpus; 479 480 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time, 481 sizeof(cp_time))); 482 } 483 case KERN_NCHSTATS: 484 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats, 485 sizeof(struct nchstats))); 486 case KERN_FORKSTAT: 487 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat, 488 sizeof(struct forkstat))); 489 case KERN_TTY: 490 return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp, 491 newp, newlen)); 492 case KERN_FSCALE: 493 return (sysctl_rdint(oldp, oldlenp, newp, fscale)); 494 case KERN_CCPU: 495 return (sysctl_rdint(oldp, oldlenp, newp, ccpu)); 496 case KERN_NPROCS: 497 return (sysctl_rdint(oldp, oldlenp, newp, nprocesses)); 498 case KERN_POOL: 499 return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp)); 500 case KERN_STACKGAPRANDOM: 501 stackgap = stackgap_random; 502 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap); 503 if (error) 504 return (error); 505 /* 506 * Safety harness. 507 */ 508 if ((stackgap < ALIGNBYTES && stackgap != 0) || 509 !powerof2(stackgap) || stackgap >= MAXSSIZ) 510 return (EINVAL); 511 stackgap_random = stackgap; 512 return (0); 513 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 514 case KERN_SYSVIPC_INFO: 515 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp)); 516 #endif 517 #ifdef CRYPTO 518 case KERN_USERCRYPTO: 519 return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto)); 520 case KERN_USERASYMCRYPTO: 521 return (sysctl_int(oldp, oldlenp, newp, newlen, 522 &userasymcrypto)); 523 case KERN_CRYPTODEVALLOWSOFT: 524 return (sysctl_int(oldp, oldlenp, newp, newlen, 525 &cryptodevallowsoft)); 526 #endif 527 case KERN_SPLASSERT: 528 return (sysctl_int(oldp, oldlenp, newp, newlen, 529 &splassert_ctl)); 530 #ifdef SYSVSEM 531 case KERN_SEMINFO: 532 return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp, 533 newp, newlen)); 534 #endif 535 #ifdef SYSVSHM 536 case KERN_SHMINFO: 537 return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp, 538 newp, newlen)); 539 #endif 540 #ifndef SMALL_KERNEL 541 case KERN_INTRCNT: 542 return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp)); 543 case KERN_WATCHDOG: 544 return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp, 545 newp, newlen)); 546 case KERN_EMUL: 547 return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp, 548 newp, newlen)); 549 #endif 550 case KERN_MAXCLUSTERS: 551 error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust); 552 if (!error) 553 nmbclust_update(); 554 return (error); 555 #ifndef SMALL_KERNEL 556 case KERN_EVCOUNT: 557 return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp, 558 newp, newlen)); 559 #endif 560 #ifdef __HAVE_TIMECOUNTER 561 case KERN_TIMECOUNTER: 562 return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp, 563 newp, newlen)); 564 #endif 565 case KERN_MAXLOCKSPERUID: 566 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxlocksperuid)); 567 case KERN_CPTIME2: 568 return (sysctl_cptime2(name + 1, namelen -1, oldp, oldlenp, 569 newp, newlen)); 570 case KERN_RTHREADS: 571 return (sysctl_int(oldp, oldlenp, newp, newlen, 572 &rthreads_enabled)); 573 case KERN_CACHEPCT: { 574 u_int64_t dmapages; 575 int opct, pgs; 576 opct = bufcachepercent; 577 error = sysctl_int(oldp, oldlenp, newp, newlen, 578 &bufcachepercent); 579 if (error) 580 return(error); 581 if (bufcachepercent > 90 || bufcachepercent < 5) { 582 bufcachepercent = opct; 583 return (EINVAL); 584 } 585 dmapages = uvm_pagecount(&dma_constraint); 586 if (bufcachepercent != opct) { 587 pgs = bufcachepercent * dmapages / 100; 588 bufadjust(pgs); /* adjust bufpages */ 589 bufhighpages = bufpages; /* set high water mark */ 590 } 591 return(0); 592 } 593 case KERN_CONSDEV: 594 if (cn_tab != NULL) 595 dev = cn_tab->cn_dev; 596 else 597 dev = NODEV; 598 return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev)); 599 case KERN_NETLIVELOCKS: 600 return (sysctl_rdint(oldp, oldlenp, newp, mcllivelocks)); 601 case KERN_POOL_DEBUG: { 602 int old_pool_debug = pool_debug; 603 604 error = sysctl_int(oldp, oldlenp, newp, newlen, 605 &pool_debug); 606 if (error == 0 && pool_debug != old_pool_debug) 607 pool_reclaim_all(); 608 return (error); 609 } 610 default: 611 return (EOPNOTSUPP); 612 } 613 /* NOTREACHED */ 614 } 615 616 /* 617 * hardware related system variables. 618 */ 619 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; 620 int allowpowerdown = 1; 621 622 int 623 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 624 size_t newlen, struct proc *p) 625 { 626 extern char machine[], cpu_model[]; 627 int err, cpuspeed; 628 629 /* all sysctl names at this level except sensors are terminal */ 630 if (name[0] != HW_SENSORS && namelen != 1) 631 return (ENOTDIR); /* overloaded */ 632 633 switch (name[0]) { 634 case HW_MACHINE: 635 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 636 case HW_MODEL: 637 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 638 case HW_NCPU: 639 return (sysctl_rdint(oldp, oldlenp, newp, ncpus)); 640 case HW_NCPUFOUND: 641 return (sysctl_rdint(oldp, oldlenp, newp, ncpusfound)); 642 case HW_BYTEORDER: 643 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 644 case HW_PHYSMEM: 645 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem))); 646 case HW_USERMEM: 647 return (sysctl_rdint(oldp, oldlenp, newp, 648 ptoa(physmem - uvmexp.wired))); 649 case HW_PAGESIZE: 650 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 651 case HW_DISKNAMES: 652 err = sysctl_diskinit(0, p); 653 if (err) 654 return err; 655 if (disknames) 656 return (sysctl_rdstring(oldp, oldlenp, newp, 657 disknames)); 658 else 659 return (sysctl_rdstring(oldp, oldlenp, newp, "")); 660 case HW_DISKSTATS: 661 err = sysctl_diskinit(1, p); 662 if (err) 663 return err; 664 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, 665 disk_count * sizeof(struct diskstats))); 666 case HW_DISKCOUNT: 667 return (sysctl_rdint(oldp, oldlenp, newp, disk_count)); 668 #ifndef SMALL_KERNEL 669 case HW_SENSORS: 670 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, 671 newp, newlen)); 672 #endif 673 case HW_CPUSPEED: 674 if (!cpu_cpuspeed) 675 return (EOPNOTSUPP); 676 err = cpu_cpuspeed(&cpuspeed); 677 if (err) 678 return err; 679 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 680 case HW_SETPERF: 681 if (!cpu_setperf) 682 return (EOPNOTSUPP); 683 err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel); 684 if (err) 685 return err; 686 if (perflevel > 100) 687 perflevel = 100; 688 if (perflevel < 0) 689 perflevel = 0; 690 if (newp) 691 cpu_setperf(perflevel); 692 return (0); 693 case HW_VENDOR: 694 if (hw_vendor) 695 return (sysctl_rdstring(oldp, oldlenp, newp, 696 hw_vendor)); 697 else 698 return (EOPNOTSUPP); 699 case HW_PRODUCT: 700 if (hw_prod) 701 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod)); 702 else 703 return (EOPNOTSUPP); 704 case HW_VERSION: 705 if (hw_ver) 706 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver)); 707 else 708 return (EOPNOTSUPP); 709 case HW_SERIALNO: 710 if (hw_serial) 711 return (sysctl_rdstring(oldp, oldlenp, newp, 712 hw_serial)); 713 else 714 return (EOPNOTSUPP); 715 case HW_UUID: 716 if (hw_uuid) 717 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid)); 718 else 719 return (EOPNOTSUPP); 720 case HW_PHYSMEM64: 721 return (sysctl_rdquad(oldp, oldlenp, newp, 722 ptoa((psize_t)physmem))); 723 case HW_USERMEM64: 724 return (sysctl_rdquad(oldp, oldlenp, newp, 725 ptoa((psize_t)physmem - uvmexp.wired))); 726 case HW_ALLOWPOWERDOWN: 727 if (securelevel > 0) 728 return (sysctl_rdint(oldp, oldlenp, newp, 729 allowpowerdown)); 730 return (sysctl_int(oldp, oldlenp, newp, newlen, 731 &allowpowerdown)); 732 default: 733 return (EOPNOTSUPP); 734 } 735 /* NOTREACHED */ 736 } 737 738 #ifdef DEBUG 739 /* 740 * Debugging related system variables. 741 */ 742 extern struct ctldebug debug0, debug1; 743 struct ctldebug debug2, debug3, debug4; 744 struct ctldebug debug5, debug6, debug7, debug8, debug9; 745 struct ctldebug debug10, debug11, debug12, debug13, debug14; 746 struct ctldebug debug15, debug16, debug17, debug18, debug19; 747 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 748 &debug0, &debug1, &debug2, &debug3, &debug4, 749 &debug5, &debug6, &debug7, &debug8, &debug9, 750 &debug10, &debug11, &debug12, &debug13, &debug14, 751 &debug15, &debug16, &debug17, &debug18, &debug19, 752 }; 753 int 754 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 755 size_t newlen, struct proc *p) 756 { 757 struct ctldebug *cdp; 758 759 /* all sysctl names at this level are name and field */ 760 if (namelen != 2) 761 return (ENOTDIR); /* overloaded */ 762 cdp = debugvars[name[0]]; 763 if (cdp->debugname == 0) 764 return (EOPNOTSUPP); 765 switch (name[1]) { 766 case CTL_DEBUG_NAME: 767 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 768 case CTL_DEBUG_VALUE: 769 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 770 default: 771 return (EOPNOTSUPP); 772 } 773 /* NOTREACHED */ 774 } 775 #endif /* DEBUG */ 776 777 /* 778 * Reads, or writes that lower the value 779 */ 780 int 781 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 782 { 783 unsigned int oval = *valp, val = *valp; 784 int error; 785 786 if (newp == NULL) 787 return (sysctl_rdint(oldp, oldlenp, newp, *valp)); 788 789 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) 790 return (error); 791 if (val > oval) 792 return (EPERM); /* do not allow raising */ 793 *(unsigned int *)valp = val; 794 return (0); 795 } 796 797 /* 798 * Validate parameters and get old / set new parameters 799 * for an integer-valued sysctl function. 800 */ 801 int 802 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 803 { 804 int error = 0; 805 806 if (oldp && *oldlenp < sizeof(int)) 807 return (ENOMEM); 808 if (newp && newlen != sizeof(int)) 809 return (EINVAL); 810 *oldlenp = sizeof(int); 811 if (oldp) 812 error = copyout(valp, oldp, sizeof(int)); 813 if (error == 0 && newp) 814 error = copyin(newp, valp, sizeof(int)); 815 return (error); 816 } 817 818 /* 819 * As above, but read-only. 820 */ 821 int 822 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) 823 { 824 int error = 0; 825 826 if (oldp && *oldlenp < sizeof(int)) 827 return (ENOMEM); 828 if (newp) 829 return (EPERM); 830 *oldlenp = sizeof(int); 831 if (oldp) 832 error = copyout((caddr_t)&val, oldp, sizeof(int)); 833 return (error); 834 } 835 836 /* 837 * Array of integer values. 838 */ 839 int 840 sysctl_int_arr(int **valpp, int *name, u_int namelen, void *oldp, 841 size_t *oldlenp, void *newp, size_t newlen) 842 { 843 if (namelen > 1) 844 return (ENOTDIR); 845 if (name[0] < 0 || valpp[name[0]] == NULL) 846 return (EOPNOTSUPP); 847 return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]])); 848 } 849 850 /* 851 * Validate parameters and get old / set new parameters 852 * for an integer-valued sysctl function. 853 */ 854 int 855 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 856 int64_t *valp) 857 { 858 int error = 0; 859 860 if (oldp && *oldlenp < sizeof(int64_t)) 861 return (ENOMEM); 862 if (newp && newlen != sizeof(int64_t)) 863 return (EINVAL); 864 *oldlenp = sizeof(int64_t); 865 if (oldp) 866 error = copyout(valp, oldp, sizeof(int64_t)); 867 if (error == 0 && newp) 868 error = copyin(newp, valp, sizeof(int64_t)); 869 return (error); 870 } 871 872 /* 873 * As above, but read-only. 874 */ 875 int 876 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val) 877 { 878 int error = 0; 879 880 if (oldp && *oldlenp < sizeof(int64_t)) 881 return (ENOMEM); 882 if (newp) 883 return (EPERM); 884 *oldlenp = sizeof(int64_t); 885 if (oldp) 886 error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); 887 return (error); 888 } 889 890 /* 891 * Validate parameters and get old / set new parameters 892 * for a string-valued sysctl function. 893 */ 894 int 895 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, 896 int maxlen) 897 { 898 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); 899 } 900 901 int 902 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 903 char *str, int maxlen) 904 { 905 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); 906 } 907 908 int 909 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 910 char *str, int maxlen, int trunc) 911 { 912 int len, error = 0; 913 914 len = strlen(str) + 1; 915 if (oldp && *oldlenp < len) { 916 if (trunc == 0 || *oldlenp == 0) 917 return (ENOMEM); 918 } 919 if (newp && newlen >= maxlen) 920 return (EINVAL); 921 if (oldp) { 922 if (trunc && *oldlenp < len) { 923 len = *oldlenp; 924 error = copyout(str, oldp, len - 1); 925 if (error == 0) 926 error = copyout("", (char *)oldp + len - 1, 1); 927 } else { 928 error = copyout(str, oldp, len); 929 } 930 } 931 *oldlenp = len; 932 if (error == 0 && newp) { 933 error = copyin(newp, str, newlen); 934 str[newlen] = 0; 935 } 936 return (error); 937 } 938 939 /* 940 * As above, but read-only. 941 */ 942 int 943 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) 944 { 945 int len, error = 0; 946 947 len = strlen(str) + 1; 948 if (oldp && *oldlenp < len) 949 return (ENOMEM); 950 if (newp) 951 return (EPERM); 952 *oldlenp = len; 953 if (oldp) 954 error = copyout(str, oldp, len); 955 return (error); 956 } 957 958 /* 959 * Validate parameters and get old / set new parameters 960 * for a structure oriented sysctl function. 961 */ 962 int 963 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, 964 int len) 965 { 966 int error = 0; 967 968 if (oldp && *oldlenp < len) 969 return (ENOMEM); 970 if (newp && newlen > len) 971 return (EINVAL); 972 if (oldp) { 973 *oldlenp = len; 974 error = copyout(sp, oldp, len); 975 } 976 if (error == 0 && newp) 977 error = copyin(newp, sp, len); 978 return (error); 979 } 980 981 /* 982 * Validate parameters and get old parameters 983 * for a structure oriented sysctl function. 984 */ 985 int 986 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 987 int len) 988 { 989 int error = 0; 990 991 if (oldp && *oldlenp < len) 992 return (ENOMEM); 993 if (newp) 994 return (EPERM); 995 *oldlenp = len; 996 if (oldp) 997 error = copyout(sp, oldp, len); 998 return (error); 999 } 1000 1001 /* 1002 * Get file structures. 1003 */ 1004 int 1005 sysctl_file(char *where, size_t *sizep, struct proc *p) 1006 { 1007 int buflen, error; 1008 struct file *fp, cfile; 1009 char *start = where; 1010 struct ucred *cred = p->p_ucred; 1011 1012 buflen = *sizep; 1013 if (where == NULL) { 1014 /* 1015 * overestimate by KERN_FILESLOP files 1016 */ 1017 *sizep = sizeof(filehead) + 1018 (nfiles + KERN_FILESLOP) * sizeof(struct file); 1019 return (0); 1020 } 1021 1022 /* 1023 * first copyout filehead 1024 */ 1025 if (buflen < sizeof(filehead)) { 1026 *sizep = 0; 1027 return (0); 1028 } 1029 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 1030 if (error) 1031 return (error); 1032 buflen -= sizeof(filehead); 1033 where += sizeof(filehead); 1034 1035 /* 1036 * followed by an array of file structures 1037 */ 1038 LIST_FOREACH(fp, &filehead, f_list) { 1039 if (buflen < sizeof(struct file)) { 1040 *sizep = where - start; 1041 return (ENOMEM); 1042 } 1043 1044 /* Only let the superuser or the owner see some information */ 1045 bcopy(fp, &cfile, sizeof (struct file)); 1046 if (suser(p, 0) != 0 && cred->cr_uid != fp->f_cred->cr_uid) { 1047 cfile.f_offset = (off_t)-1; 1048 cfile.f_rxfer = 0; 1049 cfile.f_wxfer = 0; 1050 cfile.f_seek = 0; 1051 cfile.f_rbytes = 0; 1052 cfile.f_wbytes = 0; 1053 } 1054 error = copyout(&cfile, where, sizeof (struct file)); 1055 if (error) 1056 return (error); 1057 buflen -= sizeof(struct file); 1058 where += sizeof(struct file); 1059 } 1060 *sizep = where - start; 1061 return (0); 1062 } 1063 1064 #ifndef SMALL_KERNEL 1065 void 1066 fill_file2(struct kinfo_file2 *kf, struct file *fp, struct filedesc *fdp, 1067 int fd, struct vnode *vp, struct proc *pp, struct proc *p) 1068 { 1069 struct vattr va; 1070 1071 memset(kf, 0, sizeof(*kf)); 1072 1073 kf->fd_fd = fd; /* might not really be an fd */ 1074 1075 if (fp != NULL) { 1076 kf->f_fileaddr = PTRTOINT64(fp); 1077 kf->f_flag = fp->f_flag; 1078 kf->f_iflags = fp->f_iflags; 1079 kf->f_type = fp->f_type; 1080 kf->f_count = fp->f_count; 1081 kf->f_msgcount = fp->f_msgcount; 1082 kf->f_ucred = PTRTOINT64(fp->f_cred); 1083 kf->f_uid = fp->f_cred->cr_uid; 1084 kf->f_gid = fp->f_cred->cr_gid; 1085 kf->f_ops = PTRTOINT64(fp->f_ops); 1086 kf->f_data = PTRTOINT64(fp->f_data); 1087 kf->f_usecount = 0; 1088 1089 if (suser(p, 0) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) { 1090 kf->f_offset = fp->f_offset; 1091 kf->f_rxfer = fp->f_rxfer; 1092 kf->f_rwfer = fp->f_wxfer; 1093 kf->f_seek = fp->f_seek; 1094 kf->f_rbytes = fp->f_rbytes; 1095 kf->f_wbytes = fp->f_wbytes; 1096 } else 1097 kf->f_offset = -1; 1098 } else if (vp != NULL) { 1099 /* fake it */ 1100 kf->f_type = DTYPE_VNODE; 1101 kf->f_flag = FREAD; 1102 if (fd == KERN_FILE_TRACE) 1103 kf->f_flag |= FWRITE; 1104 } 1105 1106 /* information about the object associated with this file */ 1107 switch (kf->f_type) { 1108 case DTYPE_VNODE: 1109 if (fp != NULL) 1110 vp = (struct vnode *)fp->f_data; 1111 1112 kf->v_un = PTRTOINT64(vp->v_un.vu_socket); 1113 kf->v_type = vp->v_type; 1114 kf->v_tag = vp->v_tag; 1115 kf->v_flag = vp->v_flag; 1116 kf->v_data = PTRTOINT64(vp->v_data); 1117 kf->v_mount = PTRTOINT64(vp->v_mount); 1118 if (vp->v_mount) 1119 strlcpy(kf->f_mntonname, 1120 vp->v_mount->mnt_stat.f_mntonname, 1121 sizeof(kf->f_mntonname)); 1122 1123 if (VOP_GETATTR(vp, &va, p->p_ucred, p) == 0) { 1124 kf->va_fileid = va.va_fileid; 1125 kf->va_mode = MAKEIMODE(va.va_type, va.va_mode); 1126 kf->va_size = va.va_size; 1127 kf->va_rdev = va.va_rdev; 1128 kf->va_fsid = va.va_fsid & 0xffffffff; 1129 } 1130 break; 1131 1132 case DTYPE_SOCKET: { 1133 struct socket *so = (struct socket *)fp->f_data; 1134 1135 kf->so_type = so->so_type; 1136 kf->so_state = so->so_state; 1137 kf->so_pcb = PTRTOINT64(so->so_pcb); 1138 kf->so_protocol = so->so_proto->pr_protocol; 1139 kf->so_family = so->so_proto->pr_domain->dom_family; 1140 if (so->so_splice) { 1141 kf->so_splice = PTRTOINT64(so->so_splice); 1142 kf->so_splicelen = so->so_splicelen; 1143 } else if (so->so_spliceback) 1144 kf->so_splicelen = -1; 1145 if (!so->so_pcb) 1146 break; 1147 switch (kf->so_family) { 1148 case AF_INET: { 1149 struct inpcb *inpcb = so->so_pcb; 1150 1151 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); 1152 kf->inp_lport = inpcb->inp_lport; 1153 kf->inp_laddru[0] = inpcb->inp_laddr.s_addr; 1154 kf->inp_fport = inpcb->inp_fport; 1155 kf->inp_faddru[0] = inpcb->inp_faddr.s_addr; 1156 kf->inp_rtableid = inpcb->inp_rtableid; 1157 break; 1158 } 1159 case AF_INET6: { 1160 struct inpcb *inpcb = so->so_pcb; 1161 1162 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); 1163 kf->inp_lport = inpcb->inp_lport; 1164 kf->inp_laddru[0] = inpcb->inp_laddr6.s6_addr32[0]; 1165 kf->inp_laddru[1] = inpcb->inp_laddr6.s6_addr32[1]; 1166 kf->inp_laddru[2] = inpcb->inp_laddr6.s6_addr32[2]; 1167 kf->inp_laddru[3] = inpcb->inp_laddr6.s6_addr32[3]; 1168 kf->inp_fport = inpcb->inp_fport; 1169 kf->inp_faddru[0] = inpcb->inp_faddr6.s6_addr32[0]; 1170 kf->inp_faddru[1] = inpcb->inp_faddr6.s6_addr32[1]; 1171 kf->inp_faddru[2] = inpcb->inp_faddr6.s6_addr32[2]; 1172 kf->inp_faddru[3] = inpcb->inp_faddr6.s6_addr32[3]; 1173 kf->inp_rtableid = inpcb->inp_rtableid; 1174 break; 1175 } 1176 case AF_UNIX: { 1177 struct unpcb *unpcb = so->so_pcb; 1178 1179 kf->unp_conn = PTRTOINT64(unpcb->unp_conn); 1180 break; 1181 } 1182 } 1183 break; 1184 } 1185 1186 case DTYPE_PIPE: { 1187 struct pipe *pipe = (struct pipe *)fp->f_data; 1188 1189 kf->pipe_peer = PTRTOINT64(pipe->pipe_peer); 1190 kf->pipe_state = pipe->pipe_state; 1191 break; 1192 } 1193 1194 case DTYPE_KQUEUE: { 1195 struct kqueue *kqi = (struct kqueue *)fp->f_data; 1196 1197 kf->kq_count = kqi->kq_count; 1198 kf->kq_state = kqi->kq_state; 1199 break; 1200 } 1201 case DTYPE_SYSTRACE: { 1202 struct fsystrace *f = (struct fsystrace *)fp->f_data; 1203 1204 kf->str_npolicies = f->npolicies; 1205 break; 1206 } 1207 } 1208 1209 /* per-process information for KERN_FILE_BY[PU]ID */ 1210 if (pp != NULL) { 1211 kf->p_pid = pp->p_p->ps_pid; 1212 kf->p_uid = pp->p_ucred->cr_uid; 1213 kf->p_gid = pp->p_ucred->cr_gid; 1214 kf->p_tid = pp->p_pid + THREAD_PID_OFFSET; 1215 strlcpy(kf->p_comm, pp->p_comm, sizeof(kf->p_comm)); 1216 } 1217 if (fdp != NULL) 1218 kf->fd_ofileflags = fdp->fd_ofileflags[fd]; 1219 } 1220 1221 /* 1222 * Get file structures. 1223 */ 1224 int 1225 sysctl_file2(int *name, u_int namelen, char *where, size_t *sizep, 1226 struct proc *p) 1227 { 1228 struct kinfo_file2 *kf; 1229 struct filedesc *fdp; 1230 struct file *fp; 1231 struct proc *pp; 1232 size_t buflen, elem_size, elem_count, outsize; 1233 char *dp = where; 1234 int arg, i, error = 0, needed = 0; 1235 u_int op; 1236 1237 if (namelen > 4) 1238 return (ENOTDIR); 1239 if (namelen < 4 || name[2] > sizeof(*kf)) 1240 return (EINVAL); 1241 1242 buflen = where != NULL ? *sizep : 0; 1243 op = name[0]; 1244 arg = name[1]; 1245 elem_size = name[2]; 1246 elem_count = name[3]; 1247 outsize = MIN(sizeof(*kf), elem_size); 1248 1249 if (elem_size < 1 || elem_count < 0) 1250 return (EINVAL); 1251 1252 kf = malloc(sizeof(*kf), M_TEMP, M_WAITOK); 1253 1254 #define FILLIT(fp, fdp, i, vp, pp) do { \ 1255 if (buflen >= elem_size && elem_count > 0) { \ 1256 fill_file2(kf, fp, fdp, i, vp, pp, p); \ 1257 error = copyout(kf, dp, outsize); \ 1258 if (error) \ 1259 break; \ 1260 dp += elem_size; \ 1261 buflen -= elem_size; \ 1262 elem_count--; \ 1263 } \ 1264 needed += elem_size; \ 1265 } while (0) 1266 1267 switch (op) { 1268 case KERN_FILE_BYFILE: 1269 if (arg != 0) { 1270 /* no arg in file mode */ 1271 error = EINVAL; 1272 break; 1273 } 1274 LIST_FOREACH(fp, &filehead, f_list) { 1275 if (fp->f_count == 0) 1276 continue; 1277 FILLIT(fp, NULL, 0, NULL, NULL); 1278 } 1279 break; 1280 case KERN_FILE_BYPID: 1281 /* A arg of -1 indicates all processes */ 1282 if (arg < -1) { 1283 error = EINVAL; 1284 break; 1285 } 1286 LIST_FOREACH(pp, &allproc, p_list) { 1287 /* 1288 * skip system, exiting, embryonic and undead 1289 * processes, as well as threads 1290 */ 1291 if ((pp->p_flag & P_SYSTEM) || (pp->p_flag & P_THREAD) 1292 || (pp->p_p->ps_flags & PS_EXITING) 1293 || pp->p_stat == SIDL || pp->p_stat == SZOMB) 1294 continue; 1295 if (arg > 0 && pp->p_pid != (pid_t)arg) { 1296 /* not the pid we are looking for */ 1297 continue; 1298 } 1299 fdp = pp->p_fd; 1300 if (pp->p_textvp) 1301 FILLIT(NULL, NULL, KERN_FILE_TEXT, pp->p_textvp, pp); 1302 if (fdp->fd_cdir) 1303 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pp); 1304 if (fdp->fd_rdir) 1305 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pp); 1306 if (pp->p_p->ps_tracevp) 1307 FILLIT(NULL, NULL, KERN_FILE_TRACE, pp->p_p->ps_tracevp, pp); 1308 for (i = 0; i < fdp->fd_nfiles; i++) { 1309 if ((fp = fdp->fd_ofiles[i]) == NULL) 1310 continue; 1311 if (!FILE_IS_USABLE(fp)) 1312 continue; 1313 FILLIT(fp, fdp, i, NULL, pp); 1314 } 1315 } 1316 break; 1317 case KERN_FILE_BYUID: 1318 LIST_FOREACH(pp, &allproc, p_list) { 1319 /* 1320 * skip system, exiting, embryonic and undead 1321 * processes, as well as threads 1322 */ 1323 if ((pp->p_flag & P_SYSTEM) || (pp->p_flag & P_THREAD) 1324 || (pp->p_p->ps_flags & PS_EXITING) 1325 || pp->p_stat == SIDL || pp->p_stat == SZOMB) 1326 continue; 1327 if (arg >= 0 && pp->p_ucred->cr_uid != (uid_t)arg) { 1328 /* not the uid we are looking for */ 1329 continue; 1330 } 1331 fdp = pp->p_fd; 1332 if (fdp->fd_cdir) 1333 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pp); 1334 if (fdp->fd_rdir) 1335 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pp); 1336 if (pp->p_p->ps_tracevp) 1337 FILLIT(NULL, NULL, KERN_FILE_TRACE, pp->p_p->ps_tracevp, pp); 1338 for (i = 0; i < fdp->fd_nfiles; i++) { 1339 if ((fp = fdp->fd_ofiles[i]) == NULL) 1340 continue; 1341 if (!FILE_IS_USABLE(fp)) 1342 continue; 1343 FILLIT(fp, fdp, i, NULL, pp); 1344 } 1345 } 1346 break; 1347 default: 1348 error = EINVAL; 1349 break; 1350 } 1351 free(kf, M_TEMP); 1352 1353 if (!error) { 1354 if (where == NULL) 1355 needed += KERN_FILESLOP * elem_size; 1356 else if (*sizep < needed) 1357 error = ENOMEM; 1358 *sizep = needed; 1359 } 1360 1361 return (error); 1362 } 1363 1364 /* 1365 * try over estimating by 5 procs 1366 */ 1367 #define KERN_PROCSLOP 5 1368 1369 int 1370 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) 1371 { 1372 struct kinfo_proc *kproc = NULL; 1373 struct proc *p; 1374 struct process *pr; 1375 char *dp; 1376 int arg, buflen, doingzomb, elem_size, elem_count; 1377 int error, needed, op; 1378 int dothreads = 0; 1379 1380 dp = where; 1381 buflen = where != NULL ? *sizep : 0; 1382 needed = error = 0; 1383 1384 if (namelen != 4 || name[2] < 0 || name[3] < 0 || 1385 name[2] > sizeof(*kproc)) 1386 return (EINVAL); 1387 op = name[0]; 1388 arg = name[1]; 1389 elem_size = name[2]; 1390 elem_count = name[3]; 1391 1392 dothreads = op & KERN_PROC_SHOW_THREADS; 1393 op &= ~KERN_PROC_SHOW_THREADS; 1394 1395 if (where != NULL) 1396 kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK); 1397 1398 p = LIST_FIRST(&allproc); 1399 doingzomb = 0; 1400 again: 1401 for (; p != 0; p = LIST_NEXT(p, p_list)) { 1402 /* 1403 * Skip embryonic processes. 1404 */ 1405 if (p->p_stat == SIDL) 1406 continue; 1407 1408 /* XXX skip processes in the middle of being zapped */ 1409 pr = p->p_p; 1410 if (pr->ps_pgrp == NULL) 1411 continue; 1412 1413 /* 1414 * TODO - make more efficient (see notes below). 1415 */ 1416 switch (op) { 1417 1418 case KERN_PROC_PID: 1419 /* could do this with just a lookup */ 1420 if (p->p_pid != (pid_t)arg) 1421 continue; 1422 break; 1423 1424 case KERN_PROC_PGRP: 1425 /* could do this by traversing pgrp */ 1426 if (pr->ps_pgrp->pg_id != (pid_t)arg) 1427 continue; 1428 break; 1429 1430 case KERN_PROC_SESSION: 1431 if (pr->ps_session->s_leader == NULL || 1432 pr->ps_session->s_leader->ps_pid != (pid_t)arg) 1433 continue; 1434 break; 1435 1436 case KERN_PROC_TTY: 1437 if ((pr->ps_flags & PS_CONTROLT) == 0 || 1438 pr->ps_session->s_ttyp == NULL || 1439 pr->ps_session->s_ttyp->t_dev != (dev_t)arg) 1440 continue; 1441 break; 1442 1443 case KERN_PROC_UID: 1444 if (p->p_ucred->cr_uid != (uid_t)arg) 1445 continue; 1446 break; 1447 1448 case KERN_PROC_RUID: 1449 if (p->p_cred->p_ruid != (uid_t)arg) 1450 continue; 1451 break; 1452 1453 case KERN_PROC_ALL: 1454 if (p->p_flag & P_SYSTEM) 1455 continue; 1456 break; 1457 1458 case KERN_PROC_KTHREAD: 1459 /* no filtering */ 1460 break; 1461 1462 default: 1463 error = EINVAL; 1464 goto err; 1465 } 1466 1467 if ((p->p_flag & P_THREAD) == 0) { 1468 if (buflen >= elem_size && elem_count > 0) { 1469 fill_kproc(p, kproc, 0); 1470 error = copyout(kproc, dp, elem_size); 1471 if (error) 1472 goto err; 1473 dp += elem_size; 1474 buflen -= elem_size; 1475 elem_count--; 1476 } 1477 needed += elem_size; 1478 } 1479 /* Skip the second entry if not required by op */ 1480 if (!dothreads) 1481 continue; 1482 1483 if (buflen >= elem_size && elem_count > 0) { 1484 fill_kproc(p, kproc, 1); 1485 error = copyout(kproc, dp, elem_size); 1486 if (error) 1487 goto err; 1488 dp += elem_size; 1489 buflen -= elem_size; 1490 elem_count--; 1491 } 1492 needed += elem_size; 1493 } 1494 if (doingzomb == 0) { 1495 p = LIST_FIRST(&zombproc); 1496 doingzomb++; 1497 goto again; 1498 } 1499 if (where != NULL) { 1500 *sizep = dp - where; 1501 if (needed > *sizep) { 1502 error = ENOMEM; 1503 goto err; 1504 } 1505 } else { 1506 needed += KERN_PROCSLOP * elem_size; 1507 *sizep = needed; 1508 } 1509 err: 1510 if (kproc) 1511 free(kproc, M_TEMP); 1512 return (error); 1513 } 1514 1515 /* 1516 * Fill in a kproc structure for the specified process. 1517 */ 1518 void 1519 fill_kproc(struct proc *p, struct kinfo_proc *ki, int isthread) 1520 { 1521 struct process *pr = p->p_p; 1522 struct session *s = pr->ps_session; 1523 struct tty *tp; 1524 struct timeval ut, st; 1525 1526 FILL_KPROC(ki, strlcpy, p, pr, p->p_cred, p->p_ucred, pr->ps_pgrp, 1527 p, pr, s, p->p_vmspace, pr->ps_limit, p->p_sigacts, isthread); 1528 1529 /* stuff that's too painful to generalize into the macros */ 1530 ki->p_pid = pr->ps_pid; 1531 if (pr->ps_pptr) 1532 ki->p_ppid = pr->ps_pptr->ps_pid; 1533 if (s->s_leader) 1534 ki->p_sid = s->s_leader->ps_pid; 1535 1536 if ((pr->ps_flags & PS_CONTROLT) && (tp = s->s_ttyp)) { 1537 ki->p_tdev = tp->t_dev; 1538 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; 1539 ki->p_tsess = PTRTOINT64(tp->t_session); 1540 } else { 1541 ki->p_tdev = NODEV; 1542 ki->p_tpgid = -1; 1543 } 1544 1545 /* fixups that can only be done in the kernel */ 1546 if (!P_ZOMBIE(p)) { 1547 if (p->p_stat != SIDL) 1548 ki->p_vm_rssize = vm_resident_count(p->p_vmspace); 1549 1550 calcru(&p->p_tu, &ut, &st, NULL); 1551 ki->p_uutime_sec = ut.tv_sec; 1552 ki->p_uutime_usec = ut.tv_usec; 1553 ki->p_ustime_sec = st.tv_sec; 1554 ki->p_ustime_usec = st.tv_usec; 1555 1556 #ifdef MULTIPROCESSOR 1557 if (p->p_cpu != NULL) 1558 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); 1559 #endif 1560 } 1561 } 1562 1563 int 1564 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1565 struct proc *cp) 1566 { 1567 struct proc *vp; 1568 pid_t pid; 1569 struct ps_strings pss; 1570 struct iovec iov; 1571 struct uio uio; 1572 int error, cnt, op; 1573 size_t limit; 1574 char **rargv, **vargv; /* reader vs. victim */ 1575 char *rarg, *varg, *buf; 1576 struct vmspace *vm; 1577 1578 if (namelen > 2) 1579 return (ENOTDIR); 1580 if (namelen < 2) 1581 return (EINVAL); 1582 1583 pid = name[0]; 1584 op = name[1]; 1585 1586 switch (op) { 1587 case KERN_PROC_ARGV: 1588 case KERN_PROC_NARGV: 1589 case KERN_PROC_ENV: 1590 case KERN_PROC_NENV: 1591 break; 1592 default: 1593 return (EOPNOTSUPP); 1594 } 1595 1596 if ((vp = pfind(pid)) == NULL) 1597 return (ESRCH); 1598 1599 if (oldp == NULL) { 1600 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) 1601 *oldlenp = sizeof(int); 1602 else 1603 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1604 return (0); 1605 } 1606 1607 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM)) 1608 return (EINVAL); 1609 1610 /* Exiting - don't bother, it will be gone soon anyway */ 1611 if (vp->p_p->ps_flags & PS_EXITING) 1612 return (ESRCH); 1613 1614 /* Execing - danger. */ 1615 if ((vp->p_p->ps_flags & PS_INEXEC)) 1616 return (EBUSY); 1617 1618 vm = vp->p_vmspace; 1619 vm->vm_refcnt++; 1620 vp = NULL; 1621 1622 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1623 1624 iov.iov_base = &pss; 1625 iov.iov_len = sizeof(pss); 1626 uio.uio_iov = &iov; 1627 uio.uio_iovcnt = 1; 1628 uio.uio_offset = (off_t)(vaddr_t)PS_STRINGS; 1629 uio.uio_resid = sizeof(pss); 1630 uio.uio_segflg = UIO_SYSSPACE; 1631 uio.uio_rw = UIO_READ; 1632 uio.uio_procp = cp; 1633 1634 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1635 goto out; 1636 1637 if (op == KERN_PROC_NARGV) { 1638 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 1639 goto out; 1640 } 1641 if (op == KERN_PROC_NENV) { 1642 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 1643 goto out; 1644 } 1645 1646 if (op == KERN_PROC_ARGV) { 1647 cnt = pss.ps_nargvstr; 1648 vargv = pss.ps_argvstr; 1649 } else { 1650 cnt = pss.ps_nenvstr; 1651 vargv = pss.ps_envstr; 1652 } 1653 1654 /* -1 to have space for a terminating NUL */ 1655 limit = *oldlenp - 1; 1656 *oldlenp = 0; 1657 1658 rargv = oldp; 1659 1660 /* 1661 * *oldlenp - number of bytes copied out into readers buffer. 1662 * limit - maximal number of bytes allowed into readers buffer. 1663 * rarg - pointer into readers buffer where next arg will be stored. 1664 * rargv - pointer into readers buffer where the next rarg pointer 1665 * will be stored. 1666 * vargv - pointer into victim address space where the next argument 1667 * will be read. 1668 */ 1669 1670 /* space for cnt pointers and a NULL */ 1671 rarg = (char *)(rargv + cnt + 1); 1672 *oldlenp += (cnt + 1) * sizeof(char **); 1673 1674 while (cnt > 0 && *oldlenp < limit) { 1675 size_t len, vstrlen; 1676 1677 /* Write to readers argv */ 1678 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 1679 goto out; 1680 1681 /* read the victim argv */ 1682 iov.iov_base = &varg; 1683 iov.iov_len = sizeof(varg); 1684 uio.uio_iov = &iov; 1685 uio.uio_iovcnt = 1; 1686 uio.uio_offset = (off_t)(vaddr_t)vargv; 1687 uio.uio_resid = sizeof(varg); 1688 uio.uio_segflg = UIO_SYSSPACE; 1689 uio.uio_rw = UIO_READ; 1690 uio.uio_procp = cp; 1691 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1692 goto out; 1693 1694 if (varg == NULL) 1695 break; 1696 1697 /* 1698 * read the victim arg. We must jump through hoops to avoid 1699 * crossing a page boundary too much and returning an error. 1700 */ 1701 more: 1702 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 1703 /* leave space for the terminating NUL */ 1704 iov.iov_base = buf; 1705 iov.iov_len = len; 1706 uio.uio_iov = &iov; 1707 uio.uio_iovcnt = 1; 1708 uio.uio_offset = (off_t)(vaddr_t)varg; 1709 uio.uio_resid = len; 1710 uio.uio_segflg = UIO_SYSSPACE; 1711 uio.uio_rw = UIO_READ; 1712 uio.uio_procp = cp; 1713 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 1714 goto out; 1715 1716 for (vstrlen = 0; vstrlen < len; vstrlen++) { 1717 if (buf[vstrlen] == '\0') 1718 break; 1719 } 1720 1721 /* Don't overflow readers buffer. */ 1722 if (*oldlenp + vstrlen + 1 >= limit) { 1723 error = ENOMEM; 1724 goto out; 1725 } 1726 1727 if ((error = copyout(buf, rarg, vstrlen)) != 0) 1728 goto out; 1729 1730 *oldlenp += vstrlen; 1731 rarg += vstrlen; 1732 1733 /* The string didn't end in this page? */ 1734 if (vstrlen == len) { 1735 varg += vstrlen; 1736 goto more; 1737 } 1738 1739 /* End of string. Terminate it with a NUL */ 1740 buf[0] = '\0'; 1741 if ((error = copyout(buf, rarg, 1)) != 0) 1742 goto out; 1743 *oldlenp += 1; 1744 rarg += 1; 1745 1746 vargv++; 1747 rargv++; 1748 cnt--; 1749 } 1750 1751 if (*oldlenp >= limit) { 1752 error = ENOMEM; 1753 goto out; 1754 } 1755 1756 /* Write the terminating null */ 1757 rarg = NULL; 1758 error = copyout(&rarg, rargv, sizeof(rarg)); 1759 1760 out: 1761 uvmspace_free(vm); 1762 free(buf, M_TEMP); 1763 return (error); 1764 } 1765 1766 int 1767 sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1768 struct proc *cp) 1769 { 1770 struct proc *findp; 1771 pid_t pid; 1772 int error; 1773 size_t lenused, len; 1774 char *path, *bp, *bend; 1775 1776 if (namelen > 1) 1777 return (ENOTDIR); 1778 if (namelen < 1) 1779 return (EINVAL); 1780 1781 pid = name[0]; 1782 if ((findp = pfind(pid)) == NULL) 1783 return (ESRCH); 1784 1785 if (oldp == NULL) { 1786 *oldlenp = MAXPATHLEN * 4; 1787 return (0); 1788 } 1789 1790 if (P_ZOMBIE(findp) || (findp->p_flag & P_SYSTEM)) 1791 return (EINVAL); 1792 1793 /* Only owner or root can get cwd */ 1794 if (findp->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1795 (error = suser(cp, 0)) != 0) 1796 return (error); 1797 1798 /* Exiting - don't bother, it will be gone soon anyway */ 1799 if (findp->p_p->ps_flags & PS_EXITING) 1800 return (ESRCH); 1801 1802 len = *oldlenp; 1803 if (len > MAXPATHLEN * 4) 1804 len = MAXPATHLEN * 4; 1805 else if (len < 2) 1806 return (ERANGE); 1807 *oldlenp = 0; 1808 1809 path = malloc(len, M_TEMP, M_WAITOK); 1810 1811 bp = &path[len]; 1812 bend = bp; 1813 *(--bp) = '\0'; 1814 1815 /* Same as sys__getcwd */ 1816 error = vfs_getcwd_common(findp->p_fd->fd_cdir, NULL, 1817 &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp); 1818 if (error == 0) { 1819 *oldlenp = lenused = bend - bp; 1820 error = copyout(bp, oldp, lenused); 1821 } 1822 1823 free(path, M_TEMP); 1824 1825 return (error); 1826 } 1827 #endif 1828 1829 /* 1830 * Initialize disknames/diskstats for export by sysctl. If update is set, 1831 * then we simply update the disk statistics information. 1832 */ 1833 int 1834 sysctl_diskinit(int update, struct proc *p) 1835 { 1836 struct disklabel *dl; 1837 struct diskstats *sdk; 1838 struct disk *dk; 1839 char duid[17]; 1840 u_int64_t uid = 0; 1841 int i, tlen, l; 1842 1843 if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) 1844 return i; 1845 1846 if (disk_change) { 1847 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk; 1848 dk = TAILQ_NEXT(dk, dk_link)) { 1849 if (dk->dk_name) 1850 tlen += strlen(dk->dk_name); 1851 tlen += 18; /* label uid + separators */ 1852 } 1853 tlen++; 1854 1855 if (disknames) 1856 free(disknames, M_SYSCTL); 1857 if (diskstats) 1858 free(diskstats, M_SYSCTL); 1859 diskstats = NULL; 1860 disknames = NULL; 1861 diskstats = malloc(disk_count * sizeof(struct diskstats), 1862 M_SYSCTL, M_WAITOK); 1863 disknames = malloc(tlen, M_SYSCTL, M_WAITOK); 1864 disknames[0] = '\0'; 1865 1866 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk; 1867 dk = TAILQ_NEXT(dk, dk_link), i++) { 1868 dl = dk->dk_label; 1869 bzero(duid, sizeof(duid)); 1870 if (dl && bcmp(dl->d_uid, &uid, sizeof(dl->d_uid))) { 1871 snprintf(duid, sizeof(duid), 1872 "%02hx%02hx%02hx%02hx" 1873 "%02hx%02hx%02hx%02hx", 1874 dl->d_uid[0], dl->d_uid[1], dl->d_uid[2], 1875 dl->d_uid[3], dl->d_uid[4], dl->d_uid[5], 1876 dl->d_uid[6], dl->d_uid[7]); 1877 } 1878 snprintf(disknames + l, tlen - l, "%s:%s,", 1879 dk->dk_name ? dk->dk_name : "", duid); 1880 l += strlen(disknames + l); 1881 sdk = diskstats + i; 1882 strlcpy(sdk->ds_name, dk->dk_name, 1883 sizeof(sdk->ds_name)); 1884 mtx_enter(&dk->dk_mtx); 1885 sdk->ds_busy = dk->dk_busy; 1886 sdk->ds_rxfer = dk->dk_rxfer; 1887 sdk->ds_wxfer = dk->dk_wxfer; 1888 sdk->ds_seek = dk->dk_seek; 1889 sdk->ds_rbytes = dk->dk_rbytes; 1890 sdk->ds_wbytes = dk->dk_wbytes; 1891 sdk->ds_attachtime = dk->dk_attachtime; 1892 sdk->ds_timestamp = dk->dk_timestamp; 1893 sdk->ds_time = dk->dk_time; 1894 mtx_leave(&dk->dk_mtx); 1895 } 1896 1897 /* Eliminate trailing comma */ 1898 if (l != 0) 1899 disknames[l - 1] = '\0'; 1900 disk_change = 0; 1901 } else if (update) { 1902 /* Just update, number of drives hasn't changed */ 1903 for (dk = TAILQ_FIRST(&disklist), i = 0; dk; 1904 dk = TAILQ_NEXT(dk, dk_link), i++) { 1905 sdk = diskstats + i; 1906 strlcpy(sdk->ds_name, dk->dk_name, 1907 sizeof(sdk->ds_name)); 1908 mtx_enter(&dk->dk_mtx); 1909 sdk->ds_busy = dk->dk_busy; 1910 sdk->ds_rxfer = dk->dk_rxfer; 1911 sdk->ds_wxfer = dk->dk_wxfer; 1912 sdk->ds_seek = dk->dk_seek; 1913 sdk->ds_rbytes = dk->dk_rbytes; 1914 sdk->ds_wbytes = dk->dk_wbytes; 1915 sdk->ds_attachtime = dk->dk_attachtime; 1916 sdk->ds_timestamp = dk->dk_timestamp; 1917 sdk->ds_time = dk->dk_time; 1918 mtx_leave(&dk->dk_mtx); 1919 } 1920 } 1921 rw_exit_write(&sysctl_disklock); 1922 return 0; 1923 } 1924 1925 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1926 int 1927 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 1928 { 1929 #ifdef SYSVSEM 1930 struct sem_sysctl_info *semsi; 1931 #endif 1932 #ifdef SYSVSHM 1933 struct shm_sysctl_info *shmsi; 1934 #endif 1935 size_t infosize, dssize, tsize, buflen; 1936 int i, nds, error, ret; 1937 void *buf; 1938 1939 if (namelen != 1) 1940 return (EINVAL); 1941 1942 buflen = *sizep; 1943 1944 switch (*name) { 1945 case KERN_SYSVIPC_MSG_INFO: 1946 #ifdef SYSVMSG 1947 return (sysctl_sysvmsg(name, namelen, where, sizep)); 1948 #else 1949 return (EOPNOTSUPP); 1950 #endif 1951 case KERN_SYSVIPC_SEM_INFO: 1952 #ifdef SYSVSEM 1953 infosize = sizeof(semsi->seminfo); 1954 nds = seminfo.semmni; 1955 dssize = sizeof(semsi->semids[0]); 1956 break; 1957 #else 1958 return (EOPNOTSUPP); 1959 #endif 1960 case KERN_SYSVIPC_SHM_INFO: 1961 #ifdef SYSVSHM 1962 infosize = sizeof(shmsi->shminfo); 1963 nds = shminfo.shmmni; 1964 dssize = sizeof(shmsi->shmids[0]); 1965 break; 1966 #else 1967 return (EOPNOTSUPP); 1968 #endif 1969 default: 1970 return (EINVAL); 1971 } 1972 tsize = infosize + (nds * dssize); 1973 1974 /* Return just the total size required. */ 1975 if (where == NULL) { 1976 *sizep = tsize; 1977 return (0); 1978 } 1979 1980 /* Not enough room for even the info struct. */ 1981 if (buflen < infosize) { 1982 *sizep = 0; 1983 return (ENOMEM); 1984 } 1985 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK|M_ZERO); 1986 1987 switch (*name) { 1988 #ifdef SYSVSEM 1989 case KERN_SYSVIPC_SEM_INFO: 1990 semsi = (struct sem_sysctl_info *)buf; 1991 semsi->seminfo = seminfo; 1992 break; 1993 #endif 1994 #ifdef SYSVSHM 1995 case KERN_SYSVIPC_SHM_INFO: 1996 shmsi = (struct shm_sysctl_info *)buf; 1997 shmsi->shminfo = shminfo; 1998 break; 1999 #endif 2000 } 2001 buflen -= infosize; 2002 2003 ret = 0; 2004 if (buflen > 0) { 2005 /* Fill in the IPC data structures. */ 2006 for (i = 0; i < nds; i++) { 2007 if (buflen < dssize) { 2008 ret = ENOMEM; 2009 break; 2010 } 2011 switch (*name) { 2012 #ifdef SYSVSEM 2013 case KERN_SYSVIPC_SEM_INFO: 2014 if (sema[i] != NULL) 2015 bcopy(sema[i], &semsi->semids[i], 2016 dssize); 2017 else 2018 bzero(&semsi->semids[i], dssize); 2019 break; 2020 #endif 2021 #ifdef SYSVSHM 2022 case KERN_SYSVIPC_SHM_INFO: 2023 if (shmsegs[i] != NULL) 2024 bcopy(shmsegs[i], &shmsi->shmids[i], 2025 dssize); 2026 else 2027 bzero(&shmsi->shmids[i], dssize); 2028 break; 2029 #endif 2030 } 2031 buflen -= dssize; 2032 } 2033 } 2034 *sizep -= buflen; 2035 error = copyout(buf, where, *sizep); 2036 free(buf, M_TEMP); 2037 /* If copyout succeeded, use return code set earlier. */ 2038 return (error ? error : ret); 2039 } 2040 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 2041 2042 #ifndef SMALL_KERNEL 2043 2044 int 2045 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 2046 { 2047 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); 2048 } 2049 2050 2051 int 2052 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2053 void *newp, size_t newlen) 2054 { 2055 struct ksensor *ks; 2056 struct sensor *us; 2057 struct ksensordev *ksd; 2058 struct sensordev *usd; 2059 int dev, numt, ret; 2060 enum sensor_type type; 2061 2062 if (namelen != 1 && namelen != 3) 2063 return (ENOTDIR); 2064 2065 dev = name[0]; 2066 if (namelen == 1) { 2067 ret = sensordev_get(dev, &ksd); 2068 if (ret) 2069 return (ret); 2070 2071 /* Grab a copy, to clear the kernel pointers */ 2072 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); 2073 usd->num = ksd->num; 2074 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); 2075 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); 2076 usd->sensors_count = ksd->sensors_count; 2077 2078 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, 2079 sizeof(struct sensordev)); 2080 2081 free(usd, M_TEMP); 2082 return (ret); 2083 } 2084 2085 type = name[1]; 2086 numt = name[2]; 2087 2088 ret = sensor_find(dev, type, numt, &ks); 2089 if (ret) 2090 return (ret); 2091 2092 /* Grab a copy, to clear the kernel pointers */ 2093 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); 2094 memcpy(us->desc, ks->desc, sizeof(us->desc)); 2095 us->tv = ks->tv; 2096 us->value = ks->value; 2097 us->type = ks->type; 2098 us->status = ks->status; 2099 us->numt = ks->numt; 2100 us->flags = ks->flags; 2101 2102 ret = sysctl_rdstruct(oldp, oldlenp, newp, us, 2103 sizeof(struct sensor)); 2104 free(us, M_TEMP); 2105 return (ret); 2106 } 2107 2108 int 2109 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2110 void *newp, size_t newlen) 2111 { 2112 int enabled, error; 2113 struct emul *e; 2114 2115 if (name[0] == KERN_EMUL_NUM) { 2116 if (namelen != 1) 2117 return (ENOTDIR); 2118 return (sysctl_rdint(oldp, oldlenp, newp, nexecs)); 2119 } 2120 2121 if (namelen != 2) 2122 return (ENOTDIR); 2123 if (name[0] > nexecs || name[0] < 0) 2124 return (EINVAL); 2125 e = execsw[name[0] - 1].es_emul; 2126 if (e == NULL) 2127 return (EINVAL); 2128 2129 switch (name[1]) { 2130 case KERN_EMUL_NAME: 2131 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name)); 2132 case KERN_EMUL_ENABLED: 2133 enabled = (e->e_flags & EMUL_ENABLED); 2134 error = sysctl_int(oldp, oldlenp, newp, newlen, 2135 &enabled); 2136 e->e_flags = (enabled & EMUL_ENABLED); 2137 return (error); 2138 default: 2139 return (EINVAL); 2140 } 2141 } 2142 2143 #endif /* SMALL_KERNEL */ 2144 2145 int 2146 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2147 void *newp, size_t newlen) 2148 { 2149 CPU_INFO_ITERATOR cii; 2150 struct cpu_info *ci; 2151 int i; 2152 2153 if (namelen != 1) 2154 return (ENOTDIR); 2155 2156 i = name[0]; 2157 2158 CPU_INFO_FOREACH(cii, ci) { 2159 if (i-- == 0) 2160 break; 2161 } 2162 if (i > 0) 2163 return (ENOENT); 2164 2165 return (sysctl_rdstruct(oldp, oldlenp, newp, 2166 &ci->ci_schedstate.spc_cp_time, 2167 sizeof(ci->ci_schedstate.spc_cp_time))); 2168 } 2169