1 /* $OpenBSD: kern_sysctl.c,v 1.454 2024/11/08 10:24:13 bluhm 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/atomic.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/pool.h> 48 #include <sys/proc.h> 49 #include <sys/resourcevar.h> 50 #include <sys/signalvar.h> 51 #include <sys/fcntl.h> 52 #include <sys/file.h> 53 #include <sys/filedesc.h> 54 #include <sys/vnode.h> 55 #include <sys/unistd.h> 56 #include <sys/buf.h> 57 #include <sys/clockintr.h> 58 #include <sys/tty.h> 59 #include <sys/disklabel.h> 60 #include <sys/disk.h> 61 #include <sys/sysctl.h> 62 #include <sys/msgbuf.h> 63 #include <sys/vmmeter.h> 64 #include <sys/namei.h> 65 #include <sys/exec.h> 66 #include <sys/mbuf.h> 67 #include <sys/percpu.h> 68 #include <sys/sensors.h> 69 #include <sys/pipe.h> 70 #include <sys/eventvar.h> 71 #include <sys/socketvar.h> 72 #include <sys/socket.h> 73 #include <sys/domain.h> 74 #include <sys/protosw.h> 75 #include <sys/pledge.h> 76 #include <sys/timetc.h> 77 #include <sys/evcount.h> 78 #include <sys/un.h> 79 #include <sys/unpcb.h> 80 #include <sys/sched.h> 81 #include <sys/mount.h> 82 #include <sys/syscallargs.h> 83 #include <sys/wait.h> 84 #include <sys/witness.h> 85 86 #include <uvm/uvm_extern.h> 87 88 #include <dev/cons.h> 89 90 #include <dev/usb/ucomvar.h> 91 92 #include <net/route.h> 93 #include <netinet/in.h> 94 #include <netinet/ip.h> 95 #include <netinet/ip_var.h> 96 #include <netinet/in_pcb.h> 97 #include <netinet/ip6.h> 98 #include <netinet/tcp.h> 99 #include <netinet/tcp_timer.h> 100 #include <netinet/tcp_var.h> 101 #include <netinet/udp.h> 102 #include <netinet/udp_var.h> 103 #include <netinet6/ip6_var.h> 104 105 #ifdef DDB 106 #include <ddb/db_var.h> 107 #endif 108 109 #ifdef SYSVMSG 110 #include <sys/msg.h> 111 #endif 112 #ifdef SYSVSEM 113 #include <sys/sem.h> 114 #endif 115 #ifdef SYSVSHM 116 #include <sys/shm.h> 117 #endif 118 119 #include "audio.h" 120 #include "dt.h" 121 #include "pf.h" 122 #include "ucom.h" 123 #include "video.h" 124 125 /* 126 * Locks used to protect data: 127 * a atomic 128 */ 129 130 extern struct forkstat forkstat; 131 extern struct nchstats nchstats; 132 extern int fscale; 133 extern fixpt_t ccpu; 134 extern long numvnodes; 135 extern int allowdt; 136 extern int audio_record_enable; 137 extern int video_record_enable; 138 extern int autoconf_serial; 139 140 int allowkmem; /* [a] */ 141 142 int sysctl_securelevel(void *, size_t *, void *, size_t, struct proc *); 143 int sysctl_diskinit(int, struct proc *); 144 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); 145 int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *); 146 int sysctl_proc_nobroadcastkill(int *, u_int, void *, size_t, void *, size_t *, 147 struct proc *); 148 int sysctl_proc_vmmap(int *, u_int, void *, size_t *, struct proc *); 149 int sysctl_intrcnt(int *, u_int, void *, size_t *); 150 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); 151 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t); 152 int sysctl_audio(int *, u_int, void *, size_t *, void *, size_t); 153 int sysctl_video(int *, u_int, void *, size_t *, void *, size_t); 154 int sysctl_cpustats(int *, u_int, void *, size_t *, void *, size_t); 155 int sysctl_utc_offset(void *, size_t *, void *, size_t); 156 int sysctl_hwbattery(int *, u_int, void *, size_t *, void *, size_t); 157 158 void fill_file(struct kinfo_file *, struct file *, struct filedesc *, int, 159 struct vnode *, struct process *, struct proc *, struct socket *, int); 160 void fill_kproc(struct process *, struct kinfo_proc *, struct proc *, int); 161 162 int kern_sysctl_locked(int *, u_int, void *, size_t *, void *, size_t, 163 struct proc *); 164 int hw_sysctl_locked(int *, u_int, void *, size_t *,void *, size_t, 165 struct proc *); 166 167 int (*cpu_cpuspeed)(int *); 168 169 /* 170 * Lock to avoid too many processes vslocking a large amount of memory 171 * at the same time. 172 */ 173 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk"); 174 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk"); 175 176 int 177 sysctl_vslock(void *addr, size_t len) 178 { 179 int error; 180 181 error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR); 182 if (error) 183 return (error); 184 KERNEL_LOCK(); 185 186 if (addr) { 187 if (atop(len) > uvmexp.wiredmax - uvmexp.wired) { 188 error = ENOMEM; 189 goto out; 190 } 191 error = uvm_vslock(curproc, addr, len, PROT_READ | PROT_WRITE); 192 if (error) 193 goto out; 194 } 195 196 return (0); 197 out: 198 KERNEL_UNLOCK(); 199 rw_exit_write(&sysctl_lock); 200 return (error); 201 } 202 203 void 204 sysctl_vsunlock(void *addr, size_t len) 205 { 206 KERNEL_ASSERT_LOCKED(); 207 208 if (addr) 209 uvm_vsunlock(curproc, addr, len); 210 KERNEL_UNLOCK(); 211 rw_exit_write(&sysctl_lock); 212 } 213 214 int 215 sys_sysctl(struct proc *p, void *v, register_t *retval) 216 { 217 struct sys_sysctl_args /* { 218 syscallarg(const int *) name; 219 syscallarg(u_int) namelen; 220 syscallarg(void *) old; 221 syscallarg(size_t *) oldlenp; 222 syscallarg(void *) new; 223 syscallarg(size_t) newlen; 224 } */ *uap = v; 225 int error, dolock = 1; 226 size_t savelen = 0, oldlen = 0; 227 sysctlfn *fn; 228 int name[CTL_MAXNAME]; 229 230 if (SCARG(uap, new) != NULL && 231 (error = suser(p))) 232 return (error); 233 /* 234 * all top-level sysctl names are non-terminal 235 */ 236 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 237 return (EINVAL); 238 error = copyin(SCARG(uap, name), name, 239 SCARG(uap, namelen) * sizeof(int)); 240 if (error) 241 return (error); 242 243 error = pledge_sysctl(p, SCARG(uap, namelen), 244 name, SCARG(uap, new)); 245 if (error) 246 return (error); 247 248 switch (name[0]) { 249 case CTL_KERN: 250 dolock = 0; 251 fn = kern_sysctl; 252 break; 253 case CTL_HW: 254 dolock = 0; 255 fn = hw_sysctl; 256 break; 257 case CTL_VM: 258 fn = uvm_sysctl; 259 break; 260 case CTL_NET: 261 dolock = 0; 262 fn = net_sysctl; 263 break; 264 case CTL_FS: 265 dolock = 0; 266 fn = fs_sysctl; 267 break; 268 case CTL_VFS: 269 fn = vfs_sysctl; 270 break; 271 case CTL_MACHDEP: 272 fn = cpu_sysctl; 273 break; 274 #ifdef DEBUG_SYSCTL 275 case CTL_DEBUG: 276 fn = debug_sysctl; 277 break; 278 #endif 279 #ifdef DDB 280 case CTL_DDB: 281 fn = ddb_sysctl; 282 break; 283 #endif 284 default: 285 return (EOPNOTSUPP); 286 } 287 288 if (SCARG(uap, oldlenp) && 289 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) 290 return (error); 291 292 if (dolock) { 293 error = sysctl_vslock(SCARG(uap, old), oldlen); 294 if (error) 295 return (error); 296 savelen = oldlen; 297 } 298 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old), 299 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); 300 if (dolock) 301 sysctl_vsunlock(SCARG(uap, old), savelen); 302 303 if (error) 304 return (error); 305 if (SCARG(uap, oldlenp)) 306 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 307 return (error); 308 } 309 310 /* 311 * Attributes stored in the kernel. 312 */ 313 char hostname[MAXHOSTNAMELEN]; 314 int hostnamelen; 315 char domainname[MAXHOSTNAMELEN]; 316 int domainnamelen; 317 int hostid; 318 char *disknames = NULL; 319 size_t disknameslen; 320 struct diskstats *diskstats = NULL; 321 size_t diskstatslen; 322 int securelevel; 323 324 /* morally const values reported by sysctl_bounded_arr */ 325 static int arg_max = ARG_MAX; 326 static int openbsd = OpenBSD; 327 static int posix_version = _POSIX_VERSION; 328 static int ngroups_max = NGROUPS_MAX; 329 static int int_zero = 0; 330 static int int_one = 1; 331 static int maxpartitions = MAXPARTITIONS; 332 static int raw_part = RAW_PART; 333 334 extern int somaxconn, sominconn; 335 extern int nosuidcoredump; 336 extern int maxlocksperuid; 337 extern int uvm_wxabort; 338 extern int global_ptrace; 339 340 const struct sysctl_bounded_args kern_vars[] = { 341 {KERN_OSREV, &openbsd, SYSCTL_INT_READONLY}, 342 {KERN_MAXVNODES, &maxvnodes, 0, INT_MAX}, 343 {KERN_MAXPROC, &maxprocess, 0, INT_MAX}, 344 {KERN_MAXFILES, &maxfiles, 0, INT_MAX}, 345 {KERN_NFILES, &numfiles, SYSCTL_INT_READONLY}, 346 {KERN_TTYCOUNT, &tty_count, SYSCTL_INT_READONLY}, 347 {KERN_ARGMAX, &arg_max, SYSCTL_INT_READONLY}, 348 {KERN_POSIX1, &posix_version, SYSCTL_INT_READONLY}, 349 {KERN_NGROUPS, &ngroups_max, SYSCTL_INT_READONLY}, 350 {KERN_JOB_CONTROL, &int_one, SYSCTL_INT_READONLY}, 351 {KERN_SAVED_IDS, &int_one, SYSCTL_INT_READONLY}, 352 {KERN_MAXPARTITIONS, &maxpartitions, SYSCTL_INT_READONLY}, 353 {KERN_RAWPARTITION, &raw_part, SYSCTL_INT_READONLY}, 354 {KERN_MAXTHREAD, &maxthread, 0, INT_MAX}, 355 {KERN_NTHREADS, &nthreads, SYSCTL_INT_READONLY}, 356 {KERN_SOMAXCONN, &somaxconn, 0, SHRT_MAX}, 357 {KERN_SOMINCONN, &sominconn, 0, SHRT_MAX}, 358 {KERN_NOSUIDCOREDUMP, &nosuidcoredump, 0, 3}, 359 {KERN_FSYNC, &int_one, SYSCTL_INT_READONLY}, 360 {KERN_SYSVMSG, 361 #ifdef SYSVMSG 362 &int_one, 363 #else 364 &int_zero, 365 #endif 366 SYSCTL_INT_READONLY}, 367 {KERN_SYSVSEM, 368 #ifdef SYSVSEM 369 &int_one, 370 #else 371 &int_zero, 372 #endif 373 SYSCTL_INT_READONLY}, 374 {KERN_SYSVSHM, 375 #ifdef SYSVSHM 376 &int_one, 377 #else 378 &int_zero, 379 #endif 380 SYSCTL_INT_READONLY}, 381 {KERN_FSCALE, &fscale, SYSCTL_INT_READONLY}, 382 {KERN_CCPU, &ccpu, SYSCTL_INT_READONLY}, 383 {KERN_NPROCS, &nprocesses, SYSCTL_INT_READONLY}, 384 {KERN_SPLASSERT, &splassert_ctl, 0, 3}, 385 {KERN_MAXLOCKSPERUID, &maxlocksperuid, 0, INT_MAX}, 386 {KERN_WXABORT, &uvm_wxabort, 0, 1}, 387 {KERN_NETLIVELOCKS, &int_zero, SYSCTL_INT_READONLY}, 388 #ifdef PTRACE 389 {KERN_GLOBAL_PTRACE, &global_ptrace, 0, 1}, 390 #endif 391 {KERN_AUTOCONF_SERIAL, &autoconf_serial, SYSCTL_INT_READONLY}, 392 }; 393 394 int 395 kern_sysctl_dirs(int top_name, int *name, u_int namelen, 396 void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) 397 { 398 switch (top_name) { 399 #ifndef SMALL_KERNEL 400 case KERN_PROC: 401 return (sysctl_doproc(name, namelen, oldp, oldlenp)); 402 case KERN_PROC_ARGS: 403 return (sysctl_proc_args(name, namelen, oldp, oldlenp, p)); 404 case KERN_PROC_CWD: 405 return (sysctl_proc_cwd(name, namelen, oldp, oldlenp, p)); 406 case KERN_PROC_NOBROADCASTKILL: 407 return (sysctl_proc_nobroadcastkill(name, namelen, 408 newp, newlen, oldp, oldlenp, p)); 409 case KERN_PROC_VMMAP: 410 return (sysctl_proc_vmmap(name, namelen, oldp, oldlenp, p)); 411 case KERN_FILE: 412 return (sysctl_file(name, namelen, oldp, oldlenp, p)); 413 #endif 414 #if defined(GPROF) || defined(DDBPROF) 415 case KERN_PROF: 416 return (sysctl_doprof(name, namelen, oldp, oldlenp, 417 newp, newlen)); 418 #endif 419 case KERN_MALLOCSTATS: 420 return (sysctl_malloc(name, namelen, oldp, oldlenp, 421 newp, newlen, p)); 422 case KERN_TTY: 423 return (sysctl_tty(name, namelen, oldp, oldlenp, 424 newp, newlen)); 425 case KERN_POOL: 426 return (sysctl_dopool(name, namelen, oldp, oldlenp)); 427 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 428 case KERN_SYSVIPC_INFO: 429 return (sysctl_sysvipc(name, namelen, oldp, oldlenp)); 430 #endif 431 #ifdef SYSVSEM 432 case KERN_SEMINFO: 433 return (sysctl_sysvsem(name, namelen, oldp, oldlenp, 434 newp, newlen)); 435 #endif 436 #ifdef SYSVSHM 437 case KERN_SHMINFO: 438 return (sysctl_sysvshm(name, namelen, oldp, oldlenp, 439 newp, newlen)); 440 #endif 441 #ifndef SMALL_KERNEL 442 case KERN_INTRCNT: 443 return (sysctl_intrcnt(name, namelen, oldp, oldlenp)); 444 case KERN_WATCHDOG: 445 return (sysctl_wdog(name, namelen, oldp, oldlenp, 446 newp, newlen)); 447 #endif 448 #ifndef SMALL_KERNEL 449 case KERN_EVCOUNT: 450 return (evcount_sysctl(name, namelen, oldp, oldlenp, 451 newp, newlen)); 452 #endif 453 case KERN_TIMECOUNTER: 454 return (sysctl_tc(name, namelen, oldp, oldlenp, newp, newlen)); 455 case KERN_CPTIME2: 456 return (sysctl_cptime2(name, namelen, oldp, oldlenp, 457 newp, newlen)); 458 #ifdef WITNESS 459 case KERN_WITNESSWATCH: 460 return witness_sysctl_watch(oldp, oldlenp, newp, newlen); 461 case KERN_WITNESS: 462 return witness_sysctl(name, namelen, oldp, oldlenp, 463 newp, newlen); 464 #endif 465 #if NVIDEO > 0 466 case KERN_VIDEO: 467 return (sysctl_video(name, namelen, oldp, oldlenp, 468 newp, newlen)); 469 #endif 470 case KERN_CPUSTATS: 471 return (sysctl_cpustats(name, namelen, oldp, oldlenp, 472 newp, newlen)); 473 case KERN_CLOCKINTR: 474 return sysctl_clockintr(name, namelen, oldp, oldlenp, newp, 475 newlen); 476 default: 477 return (ENOTDIR); /* overloaded */ 478 } 479 } 480 481 /* 482 * kernel related system variables. 483 */ 484 int 485 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 486 size_t newlen, struct proc *p) 487 { 488 int error; 489 size_t savelen; 490 491 /* dispatch the non-terminal nodes first */ 492 if (namelen != 1) { 493 switch (name[0]) { 494 #if NAUDIO > 0 495 case KERN_AUDIO: 496 return (sysctl_audio(name + 1, namelen - 1, 497 oldp, oldlenp, newp, newlen)); 498 #endif 499 default: 500 break; 501 } 502 503 savelen = *oldlenp; 504 if ((error = sysctl_vslock(oldp, savelen))) 505 return (error); 506 error = kern_sysctl_dirs(name[0], name + 1, namelen - 1, 507 oldp, oldlenp, newp, newlen, p); 508 sysctl_vsunlock(oldp, savelen); 509 return (error); 510 } 511 512 switch (name[0]) { 513 case KERN_ALLOWKMEM: 514 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, 515 &allowkmem)); 516 case KERN_OSTYPE: 517 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 518 case KERN_OSRELEASE: 519 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 520 case KERN_OSVERSION: 521 return (sysctl_rdstring(oldp, oldlenp, newp, osversion)); 522 case KERN_VERSION: 523 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 524 case KERN_NUMVNODES: /* XXX numvnodes is a long */ 525 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes)); 526 #if NDT > 0 527 case KERN_ALLOWDT: 528 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, 529 &allowdt)); 530 #endif 531 case KERN_HOSTID: 532 return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid)); 533 case KERN_CLOCKRATE: 534 return (sysctl_clockrate(oldp, oldlenp, newp)); 535 case KERN_BOOTTIME: { 536 struct timeval bt; 537 memset(&bt, 0, sizeof bt); 538 microboottime(&bt); 539 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt)); 540 } 541 case KERN_MBSTAT: { 542 uint64_t counters[MBSTAT_COUNT]; 543 struct mbstat mbs; 544 unsigned int i; 545 546 memset(&mbs, 0, sizeof(mbs)); 547 counters_read(mbstat, counters, MBSTAT_COUNT, NULL); 548 for (i = 0; i < MBSTAT_TYPES; i++) 549 mbs.m_mtypes[i] = counters[i]; 550 551 mbs.m_drops = counters[MBSTAT_DROPS]; 552 mbs.m_wait = counters[MBSTAT_WAIT]; 553 mbs.m_drain = counters[MBSTAT_DRAIN]; 554 mbs.m_defrag_alloc = counters[MBSTAT_DEFRAG_ALLOC]; 555 mbs.m_prepend_alloc = counters[MBSTAT_PREPEND_ALLOC]; 556 mbs.m_pullup_alloc = counters[MBSTAT_PULLUP_ALLOC]; 557 mbs.m_pullup_copy = counters[MBSTAT_PULLUP_COPY]; 558 mbs.m_pulldown_alloc = counters[MBSTAT_PULLDOWN_ALLOC]; 559 mbs.m_pulldown_copy = counters[MBSTAT_PULLDOWN_COPY]; 560 561 return (sysctl_rdstruct(oldp, oldlenp, newp, 562 &mbs, sizeof(mbs))); 563 } 564 case KERN_MSGBUFSIZE: 565 case KERN_CONSBUFSIZE: { 566 struct msgbuf *mp; 567 mp = (name[0] == KERN_MSGBUFSIZE) ? msgbufp : consbufp; 568 /* 569 * deal with cases where the message buffer has 570 * become corrupted. 571 */ 572 if (!mp || mp->msg_magic != MSG_MAGIC) 573 return (ENXIO); 574 return (sysctl_rdint(oldp, oldlenp, newp, mp->msg_bufs)); 575 } 576 case KERN_TIMEOUT_STATS: 577 return (timeout_sysctl(oldp, oldlenp, newp, newlen)); 578 case KERN_OSREV: 579 case KERN_MAXPROC: 580 case KERN_MAXFILES: 581 case KERN_NFILES: 582 case KERN_TTYCOUNT: 583 case KERN_ARGMAX: 584 case KERN_POSIX1: 585 case KERN_NGROUPS: 586 case KERN_JOB_CONTROL: 587 case KERN_SAVED_IDS: 588 case KERN_MAXPARTITIONS: 589 case KERN_RAWPARTITION: 590 case KERN_MAXTHREAD: 591 case KERN_NTHREADS: 592 case KERN_SOMAXCONN: 593 case KERN_SOMINCONN: 594 case KERN_FSYNC: 595 case KERN_SYSVMSG: 596 case KERN_SYSVSEM: 597 case KERN_SYSVSHM: 598 case KERN_FSCALE: 599 case KERN_CCPU: 600 case KERN_NPROCS: 601 case KERN_NETLIVELOCKS: 602 case KERN_AUTOCONF_SERIAL: 603 return (sysctl_bounded_arr(kern_vars, nitems(kern_vars), name, 604 namelen, oldp, oldlenp, newp, newlen)); 605 } 606 607 savelen = *oldlenp; 608 if ((error = sysctl_vslock(oldp, savelen))) 609 return (error); 610 error = kern_sysctl_locked(name, namelen, oldp, oldlenp, 611 newp, newlen, p); 612 sysctl_vsunlock(oldp, savelen); 613 614 return (error); 615 } 616 617 int 618 kern_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp, 619 void *newp, size_t newlen, struct proc *p) 620 { 621 int error, stackgap; 622 dev_t dev; 623 extern int pool_debug; 624 625 switch (name[0]) { 626 case KERN_SECURELVL: 627 return (sysctl_securelevel(oldp, oldlenp, newp, newlen, p)); 628 case KERN_HOSTNAME: 629 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 630 hostname, sizeof(hostname)); 631 if (newp && !error) 632 hostnamelen = newlen; 633 return (error); 634 case KERN_DOMAINNAME: 635 if (securelevel >= 1 && domainnamelen && newp) 636 error = EPERM; 637 else 638 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 639 domainname, sizeof(domainname)); 640 if (newp && !error) 641 domainnamelen = newlen; 642 return (error); 643 case KERN_CONSBUF: 644 if ((error = suser(p))) 645 return (error); 646 /* FALLTHROUGH */ 647 case KERN_MSGBUF: { 648 struct msgbuf *mp; 649 mp = (name[0] == KERN_MSGBUF) ? msgbufp : consbufp; 650 /* 651 * deal with cases where the message buffer has 652 * become corrupted. 653 */ 654 if (!mp || mp->msg_magic != MSG_MAGIC) 655 return (ENXIO); 656 return (sysctl_rdstruct(oldp, oldlenp, newp, mp, 657 mp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); 658 } 659 case KERN_CPTIME: 660 { 661 CPU_INFO_ITERATOR cii; 662 struct cpu_info *ci; 663 long cp_time[CPUSTATES]; 664 int i, n = 0; 665 666 memset(cp_time, 0, sizeof(cp_time)); 667 668 CPU_INFO_FOREACH(cii, ci) { 669 if (!cpu_is_online(ci)) 670 continue; 671 n++; 672 for (i = 0; i < CPUSTATES; i++) 673 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 674 } 675 676 for (i = 0; i < CPUSTATES; i++) 677 cp_time[i] /= n; 678 679 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time, 680 sizeof(cp_time))); 681 } 682 case KERN_NCHSTATS: 683 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats, 684 sizeof(struct nchstats))); 685 case KERN_FORKSTAT: 686 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat, 687 sizeof(struct forkstat))); 688 case KERN_STACKGAPRANDOM: 689 stackgap = stackgap_random; 690 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap); 691 if (error) 692 return (error); 693 /* 694 * Safety harness. 695 */ 696 if ((stackgap < ALIGNBYTES && stackgap != 0) || 697 !powerof2(stackgap) || stackgap >= MAXSSIZ) 698 return (EINVAL); 699 stackgap_random = stackgap; 700 return (0); 701 case KERN_MAXCLUSTERS: { 702 int val = nmbclust; 703 error = sysctl_int(oldp, oldlenp, newp, newlen, &val); 704 if (error == 0 && val != nmbclust) 705 error = nmbclust_update(val); 706 return (error); 707 } 708 case KERN_CACHEPCT: { 709 u_int64_t dmapages; 710 int opct, pgs; 711 opct = bufcachepercent; 712 error = sysctl_int(oldp, oldlenp, newp, newlen, 713 &bufcachepercent); 714 if (error) 715 return(error); 716 if (bufcachepercent > 90 || bufcachepercent < 5) { 717 bufcachepercent = opct; 718 return (EINVAL); 719 } 720 dmapages = uvm_pagecount(&dma_constraint); 721 if (bufcachepercent != opct) { 722 pgs = bufcachepercent * dmapages / 100; 723 bufadjust(pgs); /* adjust bufpages */ 724 bufhighpages = bufpages; /* set high water mark */ 725 } 726 return(0); 727 } 728 case KERN_CONSDEV: 729 if (cn_tab != NULL) 730 dev = cn_tab->cn_dev; 731 else 732 dev = NODEV; 733 return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev)); 734 case KERN_POOL_DEBUG: { 735 int old_pool_debug = pool_debug; 736 737 error = sysctl_int(oldp, oldlenp, newp, newlen, 738 &pool_debug); 739 if (error == 0 && pool_debug != old_pool_debug) 740 pool_reclaim_all(); 741 return (error); 742 } 743 #if NPF > 0 744 case KERN_PFSTATUS: 745 return (pf_sysctl(oldp, oldlenp, newp, newlen)); 746 #endif 747 case KERN_UTC_OFFSET: 748 return (sysctl_utc_offset(oldp, oldlenp, newp, newlen)); 749 default: 750 return (sysctl_bounded_arr(kern_vars, nitems(kern_vars), name, 751 namelen, oldp, oldlenp, newp, newlen)); 752 } 753 /* NOTREACHED */ 754 } 755 756 /* 757 * hardware related system variables. 758 */ 759 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; 760 int allowpowerdown = 1; 761 int hw_power = 1; 762 763 /* morally const values reported by sysctl_bounded_arr */ 764 static int byte_order = BYTE_ORDER; 765 766 const struct sysctl_bounded_args hw_vars[] = { 767 {HW_NCPU, &ncpus, SYSCTL_INT_READONLY}, 768 {HW_NCPUFOUND, &ncpusfound, SYSCTL_INT_READONLY}, 769 {HW_BYTEORDER, &byte_order, SYSCTL_INT_READONLY}, 770 {HW_PAGESIZE, &uvmexp.pagesize, SYSCTL_INT_READONLY}, 771 {HW_DISKCOUNT, &disk_count, SYSCTL_INT_READONLY}, 772 {HW_POWER, &hw_power, SYSCTL_INT_READONLY}, 773 }; 774 775 int 776 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 777 size_t newlen, struct proc *p) 778 { 779 extern char machine[], cpu_model[]; 780 int err; 781 782 /* 783 * all sysctl names at this level except sensors and battery 784 * are terminal 785 */ 786 if (name[0] != HW_SENSORS && name[0] != HW_BATTERY && namelen != 1) 787 return (ENOTDIR); /* overloaded */ 788 789 switch (name[0]) { 790 case HW_MACHINE: 791 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 792 case HW_MODEL: 793 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 794 case HW_NCPUONLINE: 795 return (sysctl_rdint(oldp, oldlenp, newp, 796 sysctl_hwncpuonline())); 797 case HW_PHYSMEM: 798 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem))); 799 case HW_USERMEM: 800 return (sysctl_rdint(oldp, oldlenp, newp, 801 ptoa(physmem - uvmexp.wired))); 802 case HW_DISKNAMES: 803 case HW_DISKSTATS: 804 case HW_CPUSPEED: 805 #ifndef SMALL_KERNEL 806 case HW_SENSORS: 807 case HW_SETPERF: 808 case HW_PERFPOLICY: 809 case HW_BATTERY: 810 #endif /* !SMALL_KERNEL */ 811 case HW_ALLOWPOWERDOWN: 812 case HW_UCOMNAMES: 813 #ifdef __HAVE_CPU_TOPOLOGY 814 case HW_SMT: 815 #endif 816 { 817 size_t savelen = *oldlenp; 818 if ((err = sysctl_vslock(oldp, savelen))) 819 return (err); 820 err = hw_sysctl_locked(name, namelen, oldp, oldlenp, 821 newp, newlen, p); 822 sysctl_vsunlock(oldp, savelen); 823 return (err); 824 } 825 case HW_VENDOR: 826 if (hw_vendor) 827 return (sysctl_rdstring(oldp, oldlenp, newp, 828 hw_vendor)); 829 else 830 return (EOPNOTSUPP); 831 case HW_PRODUCT: 832 if (hw_prod) 833 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod)); 834 else 835 return (EOPNOTSUPP); 836 case HW_VERSION: 837 if (hw_ver) 838 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver)); 839 else 840 return (EOPNOTSUPP); 841 case HW_SERIALNO: 842 if (hw_serial) 843 return (sysctl_rdstring(oldp, oldlenp, newp, 844 hw_serial)); 845 else 846 return (EOPNOTSUPP); 847 case HW_UUID: 848 if (hw_uuid) 849 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid)); 850 else 851 return (EOPNOTSUPP); 852 case HW_PHYSMEM64: 853 return (sysctl_rdquad(oldp, oldlenp, newp, 854 ptoa((psize_t)physmem))); 855 case HW_USERMEM64: 856 return (sysctl_rdquad(oldp, oldlenp, newp, 857 ptoa((psize_t)physmem - uvmexp.wired))); 858 default: 859 return sysctl_bounded_arr(hw_vars, nitems(hw_vars), name, 860 namelen, oldp, oldlenp, newp, newlen); 861 } 862 /* NOTREACHED */ 863 } 864 865 int 866 hw_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp, 867 void *newp, size_t newlen, struct proc *p) 868 { 869 int err, cpuspeed; 870 871 switch (name[0]) { 872 case HW_DISKNAMES: 873 err = sysctl_diskinit(0, p); 874 if (err) 875 return err; 876 if (disknames) 877 return (sysctl_rdstring(oldp, oldlenp, newp, 878 disknames)); 879 else 880 return (sysctl_rdstring(oldp, oldlenp, newp, "")); 881 case HW_DISKSTATS: 882 err = sysctl_diskinit(1, p); 883 if (err) 884 return err; 885 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, 886 disk_count * sizeof(struct diskstats))); 887 case HW_CPUSPEED: 888 if (!cpu_cpuspeed) 889 return (EOPNOTSUPP); 890 err = cpu_cpuspeed(&cpuspeed); 891 if (err) 892 return err; 893 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 894 #ifndef SMALL_KERNEL 895 case HW_SENSORS: 896 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, 897 newp, newlen)); 898 case HW_SETPERF: 899 return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen)); 900 case HW_PERFPOLICY: 901 return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen)); 902 #endif /* !SMALL_KERNEL */ 903 case HW_ALLOWPOWERDOWN: 904 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen, 905 &allowpowerdown)); 906 case HW_UCOMNAMES: { 907 const char *str = ""; 908 #if NUCOM > 0 909 str = sysctl_ucominit(); 910 #endif /* NUCOM > 0 */ 911 return (sysctl_rdstring(oldp, oldlenp, newp, str)); 912 } 913 #ifdef __HAVE_CPU_TOPOLOGY 914 case HW_SMT: 915 return (sysctl_hwsmt(oldp, oldlenp, newp, newlen)); 916 #endif 917 #ifndef SMALL_KERNEL 918 case HW_BATTERY: 919 return (sysctl_hwbattery(name + 1, namelen - 1, oldp, oldlenp, 920 newp, newlen)); 921 #endif 922 default: 923 return (EOPNOTSUPP); 924 } 925 /* NOTREACHED */ 926 } 927 928 #ifndef SMALL_KERNEL 929 930 int hw_battery_chargemode; 931 int hw_battery_chargestart; 932 int hw_battery_chargestop; 933 int (*hw_battery_setchargemode)(int); 934 int (*hw_battery_setchargestart)(int); 935 int (*hw_battery_setchargestop)(int); 936 937 int 938 sysctl_hwchargemode(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 939 { 940 int mode = hw_battery_chargemode; 941 int error; 942 943 if (!hw_battery_setchargemode) 944 return EOPNOTSUPP; 945 946 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, 947 &mode, -1, 1); 948 if (error) 949 return error; 950 951 if (newp != NULL) 952 error = hw_battery_setchargemode(mode); 953 954 return error; 955 } 956 957 int 958 sysctl_hwchargestart(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 959 { 960 int start = hw_battery_chargestart; 961 int error; 962 963 if (!hw_battery_setchargestart) 964 return EOPNOTSUPP; 965 966 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, 967 &start, 0, 100); 968 if (error) 969 return error; 970 971 if (newp != NULL) 972 error = hw_battery_setchargestart(start); 973 974 return error; 975 } 976 977 int 978 sysctl_hwchargestop(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 979 { 980 int stop = hw_battery_chargestop; 981 int error; 982 983 if (!hw_battery_setchargestop) 984 return EOPNOTSUPP; 985 986 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, 987 &stop, 0, 100); 988 if (error) 989 return error; 990 991 if (newp != NULL) 992 error = hw_battery_setchargestop(stop); 993 994 return error; 995 } 996 997 int 998 sysctl_hwbattery(int *name, u_int namelen, void *oldp, size_t *oldlenp, 999 void *newp, size_t newlen) 1000 { 1001 if (namelen != 1) 1002 return (ENOTDIR); 1003 1004 switch (name[0]) { 1005 case HW_BATTERY_CHARGEMODE: 1006 return (sysctl_hwchargemode(oldp, oldlenp, newp, newlen)); 1007 case HW_BATTERY_CHARGESTART: 1008 return (sysctl_hwchargestart(oldp, oldlenp, newp, newlen)); 1009 case HW_BATTERY_CHARGESTOP: 1010 return (sysctl_hwchargestop(oldp, oldlenp, newp, newlen)); 1011 default: 1012 return (EOPNOTSUPP); 1013 } 1014 /* NOTREACHED */ 1015 } 1016 1017 #endif 1018 1019 #ifdef DEBUG_SYSCTL 1020 /* 1021 * Debugging related system variables. 1022 */ 1023 extern struct ctldebug debug_vfs_busyprt; 1024 struct ctldebug debug1, debug2, debug3, debug4; 1025 struct ctldebug debug5, debug6, debug7, debug8, debug9; 1026 struct ctldebug debug10, debug11, debug12, debug13, debug14; 1027 struct ctldebug debug15, debug16, debug17, debug18, debug19; 1028 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 1029 &debug_vfs_busyprt, 1030 &debug1, &debug2, &debug3, &debug4, 1031 &debug5, &debug6, &debug7, &debug8, &debug9, 1032 &debug10, &debug11, &debug12, &debug13, &debug14, 1033 &debug15, &debug16, &debug17, &debug18, &debug19, 1034 }; 1035 int 1036 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 1037 size_t newlen, struct proc *p) 1038 { 1039 struct ctldebug *cdp; 1040 1041 /* all sysctl names at this level are name and field */ 1042 if (namelen != 2) 1043 return (ENOTDIR); /* overloaded */ 1044 if (name[0] < 0 || name[0] >= nitems(debugvars)) 1045 return (EOPNOTSUPP); 1046 cdp = debugvars[name[0]]; 1047 if (cdp->debugname == 0) 1048 return (EOPNOTSUPP); 1049 switch (name[1]) { 1050 case CTL_DEBUG_NAME: 1051 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 1052 case CTL_DEBUG_VALUE: 1053 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 1054 default: 1055 return (EOPNOTSUPP); 1056 } 1057 /* NOTREACHED */ 1058 } 1059 #endif /* DEBUG_SYSCTL */ 1060 1061 /* 1062 * Reads, or writes that lower the value 1063 */ 1064 int 1065 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1066 int *valp) 1067 { 1068 unsigned int oldval, newval; 1069 int error; 1070 1071 if (oldp && *oldlenp < sizeof(int)) 1072 return (ENOMEM); 1073 if (newp && newlen != sizeof(int)) 1074 return (EINVAL); 1075 *oldlenp = sizeof(int); 1076 1077 if (newp) { 1078 if ((error = copyin(newp, &newval, sizeof(int)))) 1079 return (error); 1080 do { 1081 oldval = atomic_load_int(valp); 1082 if (oldval < (unsigned int)newval) 1083 return (EPERM); /* do not allow raising */ 1084 } while (atomic_cas_uint(valp, oldval, newval) != oldval); 1085 1086 if (oldp) { 1087 /* new value has been set although user gets error */ 1088 if ((error = copyout(&oldval, oldp, sizeof(int)))) 1089 return (error); 1090 } 1091 } else if (oldp) { 1092 oldval = atomic_load_int(valp); 1093 1094 if ((error = copyout(&oldval, oldp, sizeof(int)))) 1095 return (error); 1096 } 1097 1098 return (0); 1099 } 1100 1101 /* 1102 * Validate parameters and get old / set new parameters 1103 * for an integer-valued sysctl function. 1104 */ 1105 int 1106 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 1107 { 1108 return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, valp, 1109 INT_MIN, INT_MAX)); 1110 } 1111 1112 /* 1113 * As above, but read-only. 1114 */ 1115 int 1116 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) 1117 { 1118 int error = 0; 1119 1120 if (oldp && *oldlenp < sizeof(int)) 1121 return (ENOMEM); 1122 if (newp) 1123 return (EPERM); 1124 *oldlenp = sizeof(int); 1125 if (oldp) 1126 error = copyout((caddr_t)&val, oldp, sizeof(int)); 1127 return (error); 1128 } 1129 1130 int 1131 sysctl_securelevel(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1132 struct proc *p) 1133 { 1134 int oldval, newval; 1135 int error; 1136 1137 if (oldp && *oldlenp < sizeof(int)) 1138 return (ENOMEM); 1139 if (newp && newlen != sizeof(int)) 1140 return (EINVAL); 1141 *oldlenp = sizeof(int); 1142 1143 if (newp) { 1144 if ((error = copyin(newp, &newval, sizeof(int)))) 1145 return (error); 1146 do { 1147 oldval = atomic_load_int(&securelevel); 1148 if ((oldval > 0 || newval < -1) && newval < oldval && 1149 p->p_p->ps_pid != 1) 1150 return (EPERM); 1151 } while (atomic_cas_uint(&securelevel, oldval, newval) != 1152 oldval); 1153 1154 if (oldp) { 1155 /* new value has been set although user gets error */ 1156 if ((error = copyout(&oldval, oldp, sizeof(int)))) 1157 return (error); 1158 } 1159 } else if (oldp) { 1160 oldval = atomic_load_int(&securelevel); 1161 1162 if ((error = copyout(&oldval, oldp, sizeof(int)))) 1163 return (error); 1164 } 1165 1166 return (0); 1167 } 1168 1169 /* 1170 * Selects between sysctl_rdint and sysctl_int according to securelevel. 1171 */ 1172 int 1173 sysctl_securelevel_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1174 int *valp) 1175 { 1176 if (atomic_load_int(&securelevel) > 0) 1177 return (sysctl_rdint(oldp, oldlenp, newp, *valp)); 1178 return (sysctl_int(oldp, oldlenp, newp, newlen, valp)); 1179 } 1180 1181 /* 1182 * Read-only or bounded integer values. 1183 */ 1184 int 1185 sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1186 int *valp, int minimum, int maximum) 1187 { 1188 int oldval, newval; 1189 int error; 1190 1191 /* read only */ 1192 if (newp != NULL && minimum > maximum) 1193 return (EPERM); 1194 1195 if (oldp != NULL && *oldlenp < sizeof(int)) 1196 return (ENOMEM); 1197 if (newp != NULL && newlen != sizeof(int)) 1198 return (EINVAL); 1199 *oldlenp = sizeof(int); 1200 1201 /* copyin() may sleep, call it first */ 1202 if (newp != NULL) { 1203 if ((error = copyin(newp, &newval, sizeof(int)))) 1204 return (error); 1205 /* outside limits */ 1206 if (newval < minimum || maximum < newval) 1207 return (EINVAL); 1208 } 1209 if (oldp != NULL) { 1210 if (newp != NULL) 1211 oldval = atomic_swap_uint(valp, newval); 1212 else 1213 oldval = atomic_load_int(valp); 1214 if ((error = copyout(&oldval, oldp, sizeof(int)))) { 1215 /* new value has been set although user gets error */ 1216 return (error); 1217 } 1218 } else if (newp != NULL) 1219 atomic_store_int(valp, newval); 1220 1221 return (0); 1222 } 1223 1224 /* 1225 * Array of read-only or bounded integer values. 1226 */ 1227 int 1228 sysctl_bounded_arr(const struct sysctl_bounded_args *valpp, u_int valplen, 1229 int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 1230 size_t newlen) 1231 { 1232 u_int i; 1233 if (namelen != 1) 1234 return (ENOTDIR); 1235 for (i = 0; i < valplen; ++i) { 1236 if (valpp[i].mib == name[0]) { 1237 return (sysctl_int_bounded(oldp, oldlenp, newp, newlen, 1238 valpp[i].var, valpp[i].minimum, valpp[i].maximum)); 1239 } 1240 } 1241 return (EOPNOTSUPP); 1242 } 1243 1244 /* 1245 * Validate parameters and get old / set new parameters 1246 * for an integer-valued sysctl function. 1247 */ 1248 int 1249 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1250 int64_t *valp) 1251 { 1252 int error = 0; 1253 1254 if (oldp && *oldlenp < sizeof(int64_t)) 1255 return (ENOMEM); 1256 if (newp && newlen != sizeof(int64_t)) 1257 return (EINVAL); 1258 *oldlenp = sizeof(int64_t); 1259 if (oldp) 1260 error = copyout(valp, oldp, sizeof(int64_t)); 1261 if (error == 0 && newp) 1262 error = copyin(newp, valp, sizeof(int64_t)); 1263 return (error); 1264 } 1265 1266 /* 1267 * As above, but read-only. 1268 */ 1269 int 1270 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val) 1271 { 1272 int error = 0; 1273 1274 if (oldp && *oldlenp < sizeof(int64_t)) 1275 return (ENOMEM); 1276 if (newp) 1277 return (EPERM); 1278 *oldlenp = sizeof(int64_t); 1279 if (oldp) 1280 error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); 1281 return (error); 1282 } 1283 1284 /* 1285 * Validate parameters and get old / set new parameters 1286 * for a string-valued sysctl function. 1287 */ 1288 int 1289 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, 1290 size_t maxlen) 1291 { 1292 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); 1293 } 1294 1295 int 1296 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1297 char *str, size_t maxlen) 1298 { 1299 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); 1300 } 1301 1302 int 1303 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1304 char *str, size_t maxlen, int trunc) 1305 { 1306 size_t len; 1307 int error = 0; 1308 1309 len = strlen(str) + 1; 1310 if (oldp && *oldlenp < len) { 1311 if (trunc == 0 || *oldlenp == 0) 1312 return (ENOMEM); 1313 } 1314 if (newp && newlen >= maxlen) 1315 return (EINVAL); 1316 if (oldp) { 1317 if (trunc && *oldlenp < len) { 1318 len = *oldlenp; 1319 error = copyout(str, oldp, len - 1); 1320 if (error == 0) 1321 error = copyout("", (char *)oldp + len - 1, 1); 1322 } else { 1323 error = copyout(str, oldp, len); 1324 } 1325 } 1326 *oldlenp = len; 1327 if (error == 0 && newp) { 1328 error = copyin(newp, str, newlen); 1329 str[newlen] = 0; 1330 } 1331 return (error); 1332 } 1333 1334 /* 1335 * As above, but read-only. 1336 */ 1337 int 1338 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) 1339 { 1340 size_t len; 1341 int error = 0; 1342 1343 len = strlen(str) + 1; 1344 if (oldp && *oldlenp < len) 1345 return (ENOMEM); 1346 if (newp) 1347 return (EPERM); 1348 *oldlenp = len; 1349 if (oldp) 1350 error = copyout(str, oldp, len); 1351 return (error); 1352 } 1353 1354 /* 1355 * Validate parameters and get old / set new parameters 1356 * for a structure oriented sysctl function. 1357 */ 1358 int 1359 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, 1360 size_t len) 1361 { 1362 int error = 0; 1363 1364 if (oldp && *oldlenp < len) 1365 return (ENOMEM); 1366 if (newp && newlen > len) 1367 return (EINVAL); 1368 if (oldp) { 1369 *oldlenp = len; 1370 error = copyout(sp, oldp, len); 1371 } 1372 if (error == 0 && newp) 1373 error = copyin(newp, sp, len); 1374 return (error); 1375 } 1376 1377 /* 1378 * Validate parameters and get old parameters 1379 * for a structure oriented sysctl function. 1380 */ 1381 int 1382 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 1383 size_t len) 1384 { 1385 int error = 0; 1386 1387 if (oldp && *oldlenp < len) 1388 return (ENOMEM); 1389 if (newp) 1390 return (EPERM); 1391 *oldlenp = len; 1392 if (oldp) 1393 error = copyout(sp, oldp, len); 1394 return (error); 1395 } 1396 1397 #ifndef SMALL_KERNEL 1398 void 1399 fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, 1400 int fd, struct vnode *vp, struct process *pr, struct proc *p, 1401 struct socket *so, int show_pointers) 1402 { 1403 struct vattr va; 1404 1405 memset(kf, 0, sizeof(*kf)); 1406 1407 kf->fd_fd = fd; /* might not really be an fd */ 1408 1409 if (fp != NULL) { 1410 if (show_pointers) 1411 kf->f_fileaddr = PTRTOINT64(fp); 1412 kf->f_flag = fp->f_flag; 1413 kf->f_iflags = fp->f_iflags; 1414 kf->f_type = fp->f_type; 1415 kf->f_count = fp->f_count; 1416 if (show_pointers) 1417 kf->f_ucred = PTRTOINT64(fp->f_cred); 1418 kf->f_uid = fp->f_cred->cr_uid; 1419 kf->f_gid = fp->f_cred->cr_gid; 1420 if (show_pointers) 1421 kf->f_ops = PTRTOINT64(fp->f_ops); 1422 if (show_pointers) 1423 kf->f_data = PTRTOINT64(fp->f_data); 1424 kf->f_usecount = 0; 1425 1426 if (suser(p) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) { 1427 mtx_enter(&fp->f_mtx); 1428 kf->f_offset = fp->f_offset; 1429 kf->f_rxfer = fp->f_rxfer; 1430 kf->f_rwfer = fp->f_wxfer; 1431 kf->f_seek = fp->f_seek; 1432 kf->f_rbytes = fp->f_rbytes; 1433 kf->f_wbytes = fp->f_wbytes; 1434 mtx_leave(&fp->f_mtx); 1435 } else 1436 kf->f_offset = -1; 1437 } else if (vp != NULL) { 1438 /* fake it */ 1439 kf->f_type = DTYPE_VNODE; 1440 kf->f_flag = FREAD; 1441 if (fd == KERN_FILE_TRACE) 1442 kf->f_flag |= FWRITE; 1443 } else if (so != NULL) { 1444 /* fake it */ 1445 kf->f_type = DTYPE_SOCKET; 1446 } 1447 1448 /* information about the object associated with this file */ 1449 switch (kf->f_type) { 1450 case DTYPE_VNODE: 1451 if (fp != NULL) 1452 vp = (struct vnode *)fp->f_data; 1453 1454 if (show_pointers) 1455 kf->v_un = PTRTOINT64(vp->v_un.vu_socket); 1456 kf->v_type = vp->v_type; 1457 kf->v_tag = vp->v_tag; 1458 kf->v_flag = vp->v_flag; 1459 if (show_pointers) 1460 kf->v_data = PTRTOINT64(vp->v_data); 1461 if (show_pointers) 1462 kf->v_mount = PTRTOINT64(vp->v_mount); 1463 if (vp->v_mount) 1464 strlcpy(kf->f_mntonname, 1465 vp->v_mount->mnt_stat.f_mntonname, 1466 sizeof(kf->f_mntonname)); 1467 1468 if (VOP_GETATTR(vp, &va, p->p_ucred, p) == 0) { 1469 kf->va_fileid = va.va_fileid; 1470 kf->va_mode = MAKEIMODE(va.va_type, va.va_mode); 1471 kf->va_size = va.va_size; 1472 kf->va_rdev = va.va_rdev; 1473 kf->va_fsid = va.va_fsid & 0xffffffff; 1474 kf->va_nlink = va.va_nlink; 1475 } 1476 break; 1477 1478 case DTYPE_SOCKET: { 1479 int locked = 0; 1480 1481 if (so == NULL) { 1482 so = (struct socket *)fp->f_data; 1483 /* if so is passed as parameter it is already locked */ 1484 solock(so); 1485 locked = 1; 1486 } 1487 1488 kf->so_type = so->so_type; 1489 kf->so_state = so->so_state | so->so_snd.sb_state | 1490 so->so_rcv.sb_state; 1491 if (show_pointers) 1492 kf->so_pcb = PTRTOINT64(so->so_pcb); 1493 else 1494 kf->so_pcb = -1; 1495 kf->so_protocol = so->so_proto->pr_protocol; 1496 kf->so_family = so->so_proto->pr_domain->dom_family; 1497 kf->so_rcv_cc = so->so_rcv.sb_cc; 1498 kf->so_snd_cc = so->so_snd.sb_cc; 1499 if (isspliced(so)) { 1500 if (show_pointers) 1501 kf->so_splice = 1502 PTRTOINT64(so->so_sp->ssp_socket); 1503 kf->so_splicelen = so->so_sp->ssp_len; 1504 } else if (issplicedback(so)) 1505 kf->so_splicelen = -1; 1506 if (so->so_pcb == NULL) { 1507 if (locked) 1508 sounlock(so); 1509 break; 1510 } 1511 switch (kf->so_family) { 1512 case AF_INET: { 1513 struct inpcb *inpcb = so->so_pcb; 1514 1515 soassertlocked(so); 1516 if (show_pointers) 1517 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); 1518 kf->inp_lport = inpcb->inp_lport; 1519 kf->inp_laddru[0] = inpcb->inp_laddr.s_addr; 1520 kf->inp_fport = inpcb->inp_fport; 1521 kf->inp_faddru[0] = inpcb->inp_faddr.s_addr; 1522 kf->inp_rtableid = inpcb->inp_rtableid; 1523 if (so->so_type == SOCK_RAW) 1524 kf->inp_proto = inpcb->inp_ip.ip_p; 1525 if (so->so_proto->pr_protocol == IPPROTO_TCP) { 1526 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb; 1527 kf->t_rcv_wnd = tcpcb->rcv_wnd; 1528 kf->t_snd_wnd = tcpcb->snd_wnd; 1529 kf->t_snd_cwnd = tcpcb->snd_cwnd; 1530 kf->t_state = tcpcb->t_state; 1531 } 1532 break; 1533 } 1534 case AF_INET6: { 1535 struct inpcb *inpcb = so->so_pcb; 1536 1537 soassertlocked(so); 1538 if (show_pointers) 1539 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); 1540 kf->inp_lport = inpcb->inp_lport; 1541 kf->inp_laddru[0] = inpcb->inp_laddr6.s6_addr32[0]; 1542 kf->inp_laddru[1] = inpcb->inp_laddr6.s6_addr32[1]; 1543 kf->inp_laddru[2] = inpcb->inp_laddr6.s6_addr32[2]; 1544 kf->inp_laddru[3] = inpcb->inp_laddr6.s6_addr32[3]; 1545 kf->inp_fport = inpcb->inp_fport; 1546 kf->inp_faddru[0] = inpcb->inp_faddr6.s6_addr32[0]; 1547 kf->inp_faddru[1] = inpcb->inp_faddr6.s6_addr32[1]; 1548 kf->inp_faddru[2] = inpcb->inp_faddr6.s6_addr32[2]; 1549 kf->inp_faddru[3] = inpcb->inp_faddr6.s6_addr32[3]; 1550 kf->inp_rtableid = inpcb->inp_rtableid; 1551 if (so->so_type == SOCK_RAW) 1552 kf->inp_proto = inpcb->inp_ipv6.ip6_nxt; 1553 if (so->so_proto->pr_protocol == IPPROTO_TCP) { 1554 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb; 1555 kf->t_rcv_wnd = tcpcb->rcv_wnd; 1556 kf->t_snd_wnd = tcpcb->snd_wnd; 1557 kf->t_state = tcpcb->t_state; 1558 } 1559 break; 1560 } 1561 case AF_UNIX: { 1562 struct unpcb *unpcb = so->so_pcb; 1563 1564 kf->f_msgcount = unpcb->unp_msgcount; 1565 if (show_pointers) { 1566 kf->unp_conn = PTRTOINT64(unpcb->unp_conn); 1567 kf->unp_refs = PTRTOINT64( 1568 SLIST_FIRST(&unpcb->unp_refs)); 1569 kf->unp_nextref = PTRTOINT64( 1570 SLIST_NEXT(unpcb, unp_nextref)); 1571 kf->v_un = PTRTOINT64(unpcb->unp_vnode); 1572 kf->unp_addr = PTRTOINT64(unpcb->unp_addr); 1573 } 1574 if (unpcb->unp_addr != NULL) { 1575 struct sockaddr_un *un = mtod(unpcb->unp_addr, 1576 struct sockaddr_un *); 1577 memcpy(kf->unp_path, un->sun_path, un->sun_len 1578 - offsetof(struct sockaddr_un,sun_path)); 1579 } 1580 break; 1581 } 1582 } 1583 if (locked) 1584 sounlock(so); 1585 break; 1586 } 1587 1588 case DTYPE_PIPE: { 1589 struct pipe *pipe = (struct pipe *)fp->f_data; 1590 1591 if (show_pointers) 1592 kf->pipe_peer = PTRTOINT64(pipe->pipe_peer); 1593 kf->pipe_state = pipe->pipe_state; 1594 break; 1595 } 1596 1597 case DTYPE_KQUEUE: { 1598 struct kqueue *kqi = (struct kqueue *)fp->f_data; 1599 1600 kf->kq_count = kqi->kq_count; 1601 kf->kq_state = kqi->kq_state; 1602 break; 1603 } 1604 } 1605 1606 /* per-process information for KERN_FILE_BY[PU]ID */ 1607 if (pr != NULL) { 1608 kf->p_pid = pr->ps_pid; 1609 kf->p_uid = pr->ps_ucred->cr_uid; 1610 kf->p_gid = pr->ps_ucred->cr_gid; 1611 kf->p_tid = -1; 1612 strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm)); 1613 } 1614 if (fdp != NULL) { 1615 fdplock(fdp); 1616 kf->fd_ofileflags = fdp->fd_ofileflags[fd]; 1617 fdpunlock(fdp); 1618 } 1619 } 1620 1621 /* 1622 * Get file structures. 1623 */ 1624 int 1625 sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, 1626 struct proc *p) 1627 { 1628 struct kinfo_file *kf; 1629 struct filedesc *fdp; 1630 struct file *fp; 1631 struct process *pr; 1632 size_t buflen, elem_size, elem_count, outsize; 1633 char *dp = where; 1634 int arg, i, error = 0, needed = 0, matched; 1635 u_int op; 1636 int show_pointers; 1637 1638 if (namelen > 4) 1639 return (ENOTDIR); 1640 if (namelen < 4 || name[2] > sizeof(*kf)) 1641 return (EINVAL); 1642 1643 buflen = where != NULL ? *sizep : 0; 1644 op = name[0]; 1645 arg = name[1]; 1646 elem_size = name[2]; 1647 elem_count = name[3]; 1648 outsize = MIN(sizeof(*kf), elem_size); 1649 1650 if (elem_size < 1) 1651 return (EINVAL); 1652 1653 show_pointers = suser(curproc) == 0; 1654 1655 kf = malloc(sizeof(*kf), M_TEMP, M_WAITOK); 1656 1657 #define FILLIT2(fp, fdp, i, vp, pr, so) do { \ 1658 if (buflen >= elem_size && elem_count > 0) { \ 1659 fill_file(kf, fp, fdp, i, vp, pr, p, so, show_pointers);\ 1660 error = copyout(kf, dp, outsize); \ 1661 if (error) \ 1662 break; \ 1663 dp += elem_size; \ 1664 buflen -= elem_size; \ 1665 elem_count--; \ 1666 } \ 1667 needed += elem_size; \ 1668 } while (0) 1669 #define FILLIT(fp, fdp, i, vp, pr) \ 1670 FILLIT2(fp, fdp, i, vp, pr, NULL) 1671 #define FILLSO(so) \ 1672 FILLIT2(NULL, NULL, 0, NULL, NULL, so) 1673 1674 switch (op) { 1675 case KERN_FILE_BYFILE: 1676 /* use the inp-tables to pick up closed connections, too */ 1677 if (arg == DTYPE_SOCKET) { 1678 struct inpcb *inp; 1679 1680 NET_LOCK(); 1681 mtx_enter(&tcbtable.inpt_mtx); 1682 TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) 1683 FILLSO(inp->inp_socket); 1684 mtx_leave(&tcbtable.inpt_mtx); 1685 #ifdef INET6 1686 mtx_enter(&tcb6table.inpt_mtx); 1687 TAILQ_FOREACH(inp, &tcb6table.inpt_queue, inp_queue) 1688 FILLSO(inp->inp_socket); 1689 mtx_leave(&tcb6table.inpt_mtx); 1690 #endif 1691 mtx_enter(&udbtable.inpt_mtx); 1692 TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) { 1693 if (in_pcb_is_iterator(inp)) 1694 continue; 1695 FILLSO(inp->inp_socket); 1696 } 1697 mtx_leave(&udbtable.inpt_mtx); 1698 #ifdef INET6 1699 mtx_enter(&udb6table.inpt_mtx); 1700 TAILQ_FOREACH(inp, &udb6table.inpt_queue, inp_queue) { 1701 if (in_pcb_is_iterator(inp)) 1702 continue; 1703 FILLSO(inp->inp_socket); 1704 } 1705 mtx_leave(&udb6table.inpt_mtx); 1706 #endif 1707 mtx_enter(&rawcbtable.inpt_mtx); 1708 TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { 1709 if (in_pcb_is_iterator(inp)) 1710 continue; 1711 FILLSO(inp->inp_socket); 1712 } 1713 mtx_leave(&rawcbtable.inpt_mtx); 1714 #ifdef INET6 1715 mtx_enter(&rawin6pcbtable.inpt_mtx); 1716 TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, 1717 inp_queue) { 1718 if (in_pcb_is_iterator(inp)) 1719 continue; 1720 FILLSO(inp->inp_socket); 1721 } 1722 mtx_leave(&rawin6pcbtable.inpt_mtx); 1723 #endif 1724 NET_UNLOCK(); 1725 } 1726 fp = NULL; 1727 while ((fp = fd_iterfile(fp, p)) != NULL) { 1728 if ((arg == 0 || fp->f_type == arg)) { 1729 int af, skip = 0; 1730 if (arg == DTYPE_SOCKET && fp->f_type == arg) { 1731 af = ((struct socket *)fp->f_data)-> 1732 so_proto->pr_domain->dom_family; 1733 if (af == AF_INET || af == AF_INET6) 1734 skip = 1; 1735 } 1736 if (!skip) 1737 FILLIT(fp, NULL, 0, NULL, NULL); 1738 } 1739 } 1740 break; 1741 case KERN_FILE_BYPID: 1742 /* A arg of -1 indicates all processes */ 1743 if (arg < -1) { 1744 error = EINVAL; 1745 break; 1746 } 1747 matched = 0; 1748 LIST_FOREACH(pr, &allprocess, ps_list) { 1749 /* 1750 * skip system, exiting, embryonic and undead 1751 * processes 1752 */ 1753 if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING)) 1754 continue; 1755 if (arg >= 0 && pr->ps_pid != (pid_t)arg) { 1756 /* not the pid we are looking for */ 1757 continue; 1758 } 1759 1760 refcnt_take(&pr->ps_refcnt); 1761 1762 matched = 1; 1763 fdp = pr->ps_fd; 1764 if (pr->ps_textvp) 1765 FILLIT(NULL, NULL, KERN_FILE_TEXT, pr->ps_textvp, pr); 1766 if (fdp->fd_cdir) 1767 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr); 1768 if (fdp->fd_rdir) 1769 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr); 1770 if (pr->ps_tracevp) 1771 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr); 1772 for (i = 0; i < fdp->fd_nfiles; i++) { 1773 if ((fp = fd_getfile(fdp, i)) == NULL) 1774 continue; 1775 FILLIT(fp, fdp, i, NULL, pr); 1776 FRELE(fp, p); 1777 } 1778 1779 refcnt_rele_wake(&pr->ps_refcnt); 1780 1781 /* pid is unique, stop searching */ 1782 if (arg >= 0) 1783 break; 1784 } 1785 if (!matched) 1786 error = ESRCH; 1787 break; 1788 case KERN_FILE_BYUID: 1789 LIST_FOREACH(pr, &allprocess, ps_list) { 1790 /* 1791 * skip system, exiting, embryonic and undead 1792 * processes 1793 */ 1794 if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING)) 1795 continue; 1796 if (arg >= 0 && pr->ps_ucred->cr_uid != (uid_t)arg) { 1797 /* not the uid we are looking for */ 1798 continue; 1799 } 1800 1801 refcnt_take(&pr->ps_refcnt); 1802 1803 fdp = pr->ps_fd; 1804 if (fdp->fd_cdir) 1805 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr); 1806 if (fdp->fd_rdir) 1807 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr); 1808 if (pr->ps_tracevp) 1809 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr); 1810 for (i = 0; i < fdp->fd_nfiles; i++) { 1811 if ((fp = fd_getfile(fdp, i)) == NULL) 1812 continue; 1813 FILLIT(fp, fdp, i, NULL, pr); 1814 FRELE(fp, p); 1815 } 1816 1817 refcnt_rele_wake(&pr->ps_refcnt); 1818 } 1819 break; 1820 default: 1821 error = EINVAL; 1822 break; 1823 } 1824 free(kf, M_TEMP, sizeof(*kf)); 1825 1826 if (!error) { 1827 if (where == NULL) 1828 needed += KERN_FILESLOP * elem_size; 1829 else if (*sizep < needed) 1830 error = ENOMEM; 1831 *sizep = needed; 1832 } 1833 1834 return (error); 1835 } 1836 1837 /* 1838 * try over estimating by 5 procs 1839 */ 1840 #define KERN_PROCSLOP 5 1841 1842 int 1843 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) 1844 { 1845 struct kinfo_proc *kproc = NULL; 1846 struct proc *p; 1847 struct process *pr; 1848 char *dp; 1849 int arg, buflen, doingzomb, elem_size, elem_count; 1850 int error, needed, op; 1851 int dothreads = 0; 1852 int show_pointers; 1853 1854 dp = where; 1855 buflen = where != NULL ? *sizep : 0; 1856 needed = error = 0; 1857 1858 if (namelen != 4 || name[2] <= 0 || name[3] < 0 || 1859 name[2] > sizeof(*kproc)) 1860 return (EINVAL); 1861 op = name[0]; 1862 arg = name[1]; 1863 elem_size = name[2]; 1864 elem_count = name[3]; 1865 1866 dothreads = op & KERN_PROC_SHOW_THREADS; 1867 op &= ~KERN_PROC_SHOW_THREADS; 1868 1869 show_pointers = suser(curproc) == 0; 1870 1871 if (where != NULL) 1872 kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK); 1873 1874 pr = LIST_FIRST(&allprocess); 1875 doingzomb = 0; 1876 again: 1877 for (; pr != NULL; pr = LIST_NEXT(pr, ps_list)) { 1878 /* XXX skip processes in the middle of being zapped */ 1879 if (pr->ps_pgrp == NULL) 1880 continue; 1881 1882 /* 1883 * Skip embryonic processes. 1884 */ 1885 if (pr->ps_flags & PS_EMBRYO) 1886 continue; 1887 1888 /* 1889 * TODO - make more efficient (see notes below). 1890 */ 1891 switch (op) { 1892 1893 case KERN_PROC_PID: 1894 /* could do this with just a lookup */ 1895 if (pr->ps_pid != (pid_t)arg) 1896 continue; 1897 break; 1898 1899 case KERN_PROC_PGRP: 1900 /* could do this by traversing pgrp */ 1901 if (pr->ps_pgrp->pg_id != (pid_t)arg) 1902 continue; 1903 break; 1904 1905 case KERN_PROC_SESSION: 1906 if (pr->ps_session->s_leader == NULL || 1907 pr->ps_session->s_leader->ps_pid != (pid_t)arg) 1908 continue; 1909 break; 1910 1911 case KERN_PROC_TTY: 1912 if ((pr->ps_flags & PS_CONTROLT) == 0 || 1913 pr->ps_session->s_ttyp == NULL || 1914 pr->ps_session->s_ttyp->t_dev != (dev_t)arg) 1915 continue; 1916 break; 1917 1918 case KERN_PROC_UID: 1919 if (pr->ps_ucred->cr_uid != (uid_t)arg) 1920 continue; 1921 break; 1922 1923 case KERN_PROC_RUID: 1924 if (pr->ps_ucred->cr_ruid != (uid_t)arg) 1925 continue; 1926 break; 1927 1928 case KERN_PROC_ALL: 1929 if (pr->ps_flags & PS_SYSTEM) 1930 continue; 1931 break; 1932 1933 case KERN_PROC_KTHREAD: 1934 /* no filtering */ 1935 break; 1936 1937 default: 1938 error = EINVAL; 1939 goto err; 1940 } 1941 1942 if (buflen >= elem_size && elem_count > 0) { 1943 fill_kproc(pr, kproc, NULL, show_pointers); 1944 error = copyout(kproc, dp, elem_size); 1945 if (error) 1946 goto err; 1947 dp += elem_size; 1948 buflen -= elem_size; 1949 elem_count--; 1950 } 1951 needed += elem_size; 1952 1953 /* Skip per-thread entries if not required by op */ 1954 if (!dothreads) 1955 continue; 1956 1957 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { 1958 if (buflen >= elem_size && elem_count > 0) { 1959 fill_kproc(pr, kproc, p, show_pointers); 1960 error = copyout(kproc, dp, elem_size); 1961 if (error) 1962 goto err; 1963 dp += elem_size; 1964 buflen -= elem_size; 1965 elem_count--; 1966 } 1967 needed += elem_size; 1968 } 1969 } 1970 if (doingzomb == 0) { 1971 pr = LIST_FIRST(&zombprocess); 1972 doingzomb++; 1973 goto again; 1974 } 1975 if (where != NULL) { 1976 *sizep = dp - where; 1977 if (needed > *sizep) { 1978 error = ENOMEM; 1979 goto err; 1980 } 1981 } else { 1982 needed += KERN_PROCSLOP * elem_size; 1983 *sizep = needed; 1984 } 1985 err: 1986 if (kproc) 1987 free(kproc, M_TEMP, sizeof(*kproc)); 1988 return (error); 1989 } 1990 1991 /* 1992 * Fill in a kproc structure for the specified process. 1993 */ 1994 void 1995 fill_kproc(struct process *pr, struct kinfo_proc *ki, struct proc *p, 1996 int show_pointers) 1997 { 1998 struct session *s = pr->ps_session; 1999 struct tty *tp; 2000 struct vmspace *vm = pr->ps_vmspace; 2001 struct timespec booted, st, ut, utc; 2002 struct tusage tu; 2003 int isthread; 2004 2005 isthread = p != NULL; 2006 if (!isthread) { 2007 p = pr->ps_mainproc; /* XXX */ 2008 tuagg_get_process(&tu, pr); 2009 } else 2010 tuagg_get_proc(&tu, p); 2011 2012 FILL_KPROC(ki, strlcpy, p, pr, pr->ps_ucred, pr->ps_pgrp, 2013 p, pr, s, vm, pr->ps_limit, pr->ps_sigacts, &tu, isthread, 2014 show_pointers); 2015 2016 /* stuff that's too painful to generalize into the macros */ 2017 if (s->s_leader) 2018 ki->p_sid = s->s_leader->ps_pid; 2019 2020 if ((pr->ps_flags & PS_CONTROLT) && (tp = s->s_ttyp)) { 2021 ki->p_tdev = tp->t_dev; 2022 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1; 2023 if (show_pointers) 2024 ki->p_tsess = PTRTOINT64(tp->t_session); 2025 } else { 2026 ki->p_tdev = NODEV; 2027 ki->p_tpgid = -1; 2028 } 2029 2030 /* fixups that can only be done in the kernel */ 2031 if ((pr->ps_flags & PS_ZOMBIE) == 0) { 2032 if ((pr->ps_flags & PS_EMBRYO) == 0 && vm != NULL) 2033 ki->p_vm_rssize = vm_resident_count(vm); 2034 calctsru(&tu, &ut, &st, NULL); 2035 ki->p_uutime_sec = ut.tv_sec; 2036 ki->p_uutime_usec = ut.tv_nsec/1000; 2037 ki->p_ustime_sec = st.tv_sec; 2038 ki->p_ustime_usec = st.tv_nsec/1000; 2039 2040 /* Convert starting uptime to a starting UTC time. */ 2041 nanoboottime(&booted); 2042 timespecadd(&booted, &pr->ps_start, &utc); 2043 ki->p_ustart_sec = utc.tv_sec; 2044 ki->p_ustart_usec = utc.tv_nsec / 1000; 2045 2046 #ifdef MULTIPROCESSOR 2047 if (p->p_cpu != NULL) 2048 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu); 2049 #endif 2050 } 2051 2052 /* get %cpu and schedule state: just one thread or sum of all? */ 2053 if (isthread) { 2054 ki->p_pctcpu = p->p_pctcpu; 2055 ki->p_stat = p->p_stat; 2056 } else { 2057 ki->p_pctcpu = 0; 2058 ki->p_stat = (pr->ps_flags & PS_ZOMBIE) ? SDEAD : SIDL; 2059 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { 2060 ki->p_pctcpu += p->p_pctcpu; 2061 /* find best state: ONPROC > RUN > STOP > SLEEP > .. */ 2062 if (p->p_stat == SONPROC || ki->p_stat == SONPROC) 2063 ki->p_stat = SONPROC; 2064 else if (p->p_stat == SRUN || ki->p_stat == SRUN) 2065 ki->p_stat = SRUN; 2066 else if (p->p_stat == SSTOP || ki->p_stat == SSTOP) 2067 ki->p_stat = SSTOP; 2068 else if (p->p_stat == SSLEEP) 2069 ki->p_stat = SSLEEP; 2070 } 2071 } 2072 } 2073 2074 int 2075 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2076 struct proc *cp) 2077 { 2078 struct process *vpr; 2079 pid_t pid; 2080 struct ps_strings pss; 2081 struct iovec iov; 2082 struct uio uio; 2083 int error, cnt, op; 2084 size_t limit; 2085 char **rargv, **vargv; /* reader vs. victim */ 2086 char *rarg, *varg, *buf; 2087 struct vmspace *vm; 2088 vaddr_t ps_strings; 2089 2090 if (namelen > 2) 2091 return (ENOTDIR); 2092 if (namelen < 2) 2093 return (EINVAL); 2094 2095 pid = name[0]; 2096 op = name[1]; 2097 2098 switch (op) { 2099 case KERN_PROC_ARGV: 2100 case KERN_PROC_NARGV: 2101 case KERN_PROC_ENV: 2102 case KERN_PROC_NENV: 2103 break; 2104 default: 2105 return (EOPNOTSUPP); 2106 } 2107 2108 if ((vpr = prfind(pid)) == NULL) 2109 return (ESRCH); 2110 2111 if (oldp == NULL) { 2112 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV) 2113 *oldlenp = sizeof(int); 2114 else 2115 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 2116 return (0); 2117 } 2118 2119 /* Either system process or exiting/zombie */ 2120 if (vpr->ps_flags & (PS_SYSTEM | PS_EXITING)) 2121 return (EINVAL); 2122 2123 /* Execing - danger. */ 2124 if ((vpr->ps_flags & PS_INEXEC)) 2125 return (EBUSY); 2126 2127 /* Only owner or root can get env */ 2128 if ((op == KERN_PROC_NENV || op == KERN_PROC_ENV) && 2129 (vpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && 2130 (error = suser(cp)) != 0)) 2131 return (error); 2132 2133 ps_strings = vpr->ps_strings; 2134 vm = vpr->ps_vmspace; 2135 uvmspace_addref(vm); 2136 vpr = NULL; 2137 2138 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 2139 2140 iov.iov_base = &pss; 2141 iov.iov_len = sizeof(pss); 2142 uio.uio_iov = &iov; 2143 uio.uio_iovcnt = 1; 2144 uio.uio_offset = (off_t)ps_strings; 2145 uio.uio_resid = sizeof(pss); 2146 uio.uio_segflg = UIO_SYSSPACE; 2147 uio.uio_rw = UIO_READ; 2148 uio.uio_procp = cp; 2149 2150 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 2151 goto out; 2152 2153 if (op == KERN_PROC_NARGV) { 2154 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 2155 goto out; 2156 } 2157 if (op == KERN_PROC_NENV) { 2158 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 2159 goto out; 2160 } 2161 2162 if (op == KERN_PROC_ARGV) { 2163 cnt = pss.ps_nargvstr; 2164 vargv = pss.ps_argvstr; 2165 } else { 2166 cnt = pss.ps_nenvstr; 2167 vargv = pss.ps_envstr; 2168 } 2169 2170 /* -1 to have space for a terminating NUL */ 2171 limit = *oldlenp - 1; 2172 *oldlenp = 0; 2173 2174 rargv = oldp; 2175 2176 /* 2177 * *oldlenp - number of bytes copied out into readers buffer. 2178 * limit - maximal number of bytes allowed into readers buffer. 2179 * rarg - pointer into readers buffer where next arg will be stored. 2180 * rargv - pointer into readers buffer where the next rarg pointer 2181 * will be stored. 2182 * vargv - pointer into victim address space where the next argument 2183 * will be read. 2184 */ 2185 2186 /* space for cnt pointers and a NULL */ 2187 rarg = (char *)(rargv + cnt + 1); 2188 *oldlenp += (cnt + 1) * sizeof(char **); 2189 2190 while (cnt > 0 && *oldlenp < limit) { 2191 size_t len, vstrlen; 2192 2193 /* Write to readers argv */ 2194 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 2195 goto out; 2196 2197 /* read the victim argv */ 2198 iov.iov_base = &varg; 2199 iov.iov_len = sizeof(varg); 2200 uio.uio_iov = &iov; 2201 uio.uio_iovcnt = 1; 2202 uio.uio_offset = (off_t)(vaddr_t)vargv; 2203 uio.uio_resid = sizeof(varg); 2204 uio.uio_segflg = UIO_SYSSPACE; 2205 uio.uio_rw = UIO_READ; 2206 uio.uio_procp = cp; 2207 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 2208 goto out; 2209 2210 if (varg == NULL) 2211 break; 2212 2213 /* 2214 * read the victim arg. We must jump through hoops to avoid 2215 * crossing a page boundary too much and returning an error. 2216 */ 2217 more: 2218 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 2219 /* leave space for the terminating NUL */ 2220 iov.iov_base = buf; 2221 iov.iov_len = len; 2222 uio.uio_iov = &iov; 2223 uio.uio_iovcnt = 1; 2224 uio.uio_offset = (off_t)(vaddr_t)varg; 2225 uio.uio_resid = len; 2226 uio.uio_segflg = UIO_SYSSPACE; 2227 uio.uio_rw = UIO_READ; 2228 uio.uio_procp = cp; 2229 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0) 2230 goto out; 2231 2232 for (vstrlen = 0; vstrlen < len; vstrlen++) { 2233 if (buf[vstrlen] == '\0') 2234 break; 2235 } 2236 2237 /* Don't overflow readers buffer. */ 2238 if (*oldlenp + vstrlen + 1 >= limit) { 2239 error = ENOMEM; 2240 goto out; 2241 } 2242 2243 if ((error = copyout(buf, rarg, vstrlen)) != 0) 2244 goto out; 2245 2246 *oldlenp += vstrlen; 2247 rarg += vstrlen; 2248 2249 /* The string didn't end in this page? */ 2250 if (vstrlen == len) { 2251 varg += vstrlen; 2252 goto more; 2253 } 2254 2255 /* End of string. Terminate it with a NUL */ 2256 buf[0] = '\0'; 2257 if ((error = copyout(buf, rarg, 1)) != 0) 2258 goto out; 2259 *oldlenp += 1; 2260 rarg += 1; 2261 2262 vargv++; 2263 rargv++; 2264 cnt--; 2265 } 2266 2267 if (*oldlenp >= limit) { 2268 error = ENOMEM; 2269 goto out; 2270 } 2271 2272 /* Write the terminating null */ 2273 rarg = NULL; 2274 error = copyout(&rarg, rargv, sizeof(rarg)); 2275 2276 out: 2277 uvmspace_free(vm); 2278 free(buf, M_TEMP, PAGE_SIZE); 2279 return (error); 2280 } 2281 2282 int 2283 sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2284 struct proc *cp) 2285 { 2286 struct process *findpr; 2287 struct vnode *vp; 2288 pid_t pid; 2289 int error; 2290 size_t lenused, len; 2291 char *path, *bp, *bend; 2292 2293 if (namelen > 1) 2294 return (ENOTDIR); 2295 if (namelen < 1) 2296 return (EINVAL); 2297 2298 pid = name[0]; 2299 if ((findpr = prfind(pid)) == NULL) 2300 return (ESRCH); 2301 2302 if (oldp == NULL) { 2303 *oldlenp = MAXPATHLEN * 4; 2304 return (0); 2305 } 2306 2307 /* Either system process or exiting/zombie */ 2308 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) 2309 return (EINVAL); 2310 2311 /* Only owner or root can get cwd */ 2312 if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && 2313 (error = suser(cp)) != 0) 2314 return (error); 2315 2316 len = *oldlenp; 2317 if (len > MAXPATHLEN * 4) 2318 len = MAXPATHLEN * 4; 2319 else if (len < 2) 2320 return (ERANGE); 2321 *oldlenp = 0; 2322 2323 /* snag a reference to the vnode before we can sleep */ 2324 vp = findpr->ps_fd->fd_cdir; 2325 vref(vp); 2326 2327 path = malloc(len, M_TEMP, M_WAITOK); 2328 2329 bp = &path[len]; 2330 bend = bp; 2331 *(--bp) = '\0'; 2332 2333 /* Same as sys__getcwd */ 2334 error = vfs_getcwd_common(vp, NULL, 2335 &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp); 2336 if (error == 0) { 2337 *oldlenp = lenused = bend - bp; 2338 error = copyout(bp, oldp, lenused); 2339 } 2340 2341 vrele(vp); 2342 free(path, M_TEMP, len); 2343 2344 return (error); 2345 } 2346 2347 int 2348 sysctl_proc_nobroadcastkill(int *name, u_int namelen, void *newp, size_t newlen, 2349 void *oldp, size_t *oldlenp, struct proc *cp) 2350 { 2351 struct process *findpr; 2352 pid_t pid; 2353 int error, flag; 2354 2355 if (namelen > 1) 2356 return (ENOTDIR); 2357 if (namelen < 1) 2358 return (EINVAL); 2359 2360 pid = name[0]; 2361 if ((findpr = prfind(pid)) == NULL) 2362 return (ESRCH); 2363 2364 /* Either system process or exiting/zombie */ 2365 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) 2366 return (EINVAL); 2367 2368 /* Only root can change PS_NOBROADCASTKILL */ 2369 if (newp != NULL && (error = suser(cp)) != 0) 2370 return (error); 2371 2372 /* get the PS_NOBROADCASTKILL flag */ 2373 flag = findpr->ps_flags & PS_NOBROADCASTKILL ? 1 : 0; 2374 2375 error = sysctl_int(oldp, oldlenp, newp, newlen, &flag); 2376 if (error == 0 && newp) { 2377 if (flag) 2378 atomic_setbits_int(&findpr->ps_flags, 2379 PS_NOBROADCASTKILL); 2380 else 2381 atomic_clearbits_int(&findpr->ps_flags, 2382 PS_NOBROADCASTKILL); 2383 } 2384 2385 return (error); 2386 } 2387 2388 /* Arbitrary but reasonable limit for one iteration. */ 2389 #define VMMAP_MAXLEN MAXPHYS 2390 2391 int 2392 sysctl_proc_vmmap(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2393 struct proc *cp) 2394 { 2395 struct process *findpr; 2396 pid_t pid; 2397 int error; 2398 size_t oldlen, len; 2399 struct kinfo_vmentry *kve, *ukve; 2400 u_long *ustart, start; 2401 2402 if (namelen > 1) 2403 return (ENOTDIR); 2404 if (namelen < 1) 2405 return (EINVAL); 2406 2407 /* Provide max buffer length as hint. */ 2408 if (oldp == NULL) { 2409 if (oldlenp == NULL) 2410 return (EINVAL); 2411 else { 2412 *oldlenp = VMMAP_MAXLEN; 2413 return (0); 2414 } 2415 } 2416 2417 pid = name[0]; 2418 if (pid == cp->p_p->ps_pid) { 2419 /* Self process mapping. */ 2420 findpr = cp->p_p; 2421 } else if (pid > 0) { 2422 if ((findpr = prfind(pid)) == NULL) 2423 return (ESRCH); 2424 2425 /* Either system process or exiting/zombie */ 2426 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING)) 2427 return (EINVAL); 2428 2429 #if 1 2430 /* XXX Allow only root for now */ 2431 if ((error = suser(cp)) != 0) 2432 return (error); 2433 #else 2434 /* Only owner or root can get vmmap */ 2435 if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid && 2436 (error = suser(cp)) != 0) 2437 return (error); 2438 #endif 2439 } else { 2440 /* Only root can get kernel_map */ 2441 if ((error = suser(cp)) != 0) 2442 return (error); 2443 findpr = NULL; 2444 } 2445 2446 /* Check the given size. */ 2447 oldlen = *oldlenp; 2448 if (oldlen == 0 || oldlen % sizeof(*kve) != 0) 2449 return (EINVAL); 2450 2451 /* Deny huge allocation. */ 2452 if (oldlen > VMMAP_MAXLEN) 2453 return (EINVAL); 2454 2455 /* 2456 * Iterate from the given address passed as the first element's 2457 * kve_start via oldp. 2458 */ 2459 ukve = (struct kinfo_vmentry *)oldp; 2460 ustart = &ukve->kve_start; 2461 error = copyin(ustart, &start, sizeof(start)); 2462 if (error != 0) 2463 return (error); 2464 2465 /* Allocate wired memory to not block. */ 2466 kve = malloc(oldlen, M_TEMP, M_WAITOK); 2467 2468 /* Set the base address and read entries. */ 2469 kve[0].kve_start = start; 2470 len = oldlen; 2471 error = fill_vmmap(findpr, kve, &len); 2472 if (error != 0 && error != ENOMEM) 2473 goto done; 2474 if (len == 0) 2475 goto done; 2476 2477 KASSERT(len <= oldlen); 2478 KASSERT((len % sizeof(struct kinfo_vmentry)) == 0); 2479 2480 error = copyout(kve, oldp, len); 2481 2482 done: 2483 *oldlenp = len; 2484 2485 free(kve, M_TEMP, oldlen); 2486 2487 return (error); 2488 } 2489 #endif 2490 2491 /* 2492 * Initialize disknames/diskstats for export by sysctl. If update is set, 2493 * then we simply update the disk statistics information. 2494 */ 2495 int 2496 sysctl_diskinit(int update, struct proc *p) 2497 { 2498 struct diskstats *sdk; 2499 struct disk *dk; 2500 const char *duid; 2501 int error, changed = 0; 2502 2503 KERNEL_ASSERT_LOCKED(); 2504 2505 if ((error = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0) 2506 return error; 2507 2508 /* Run in a loop, disks may change while malloc sleeps. */ 2509 while (disk_change) { 2510 int tlen, count; 2511 2512 disk_change = 0; 2513 2514 tlen = 0; 2515 TAILQ_FOREACH(dk, &disklist, dk_link) { 2516 if (dk->dk_name) 2517 tlen += strlen(dk->dk_name); 2518 tlen += 18; /* label uid + separators */ 2519 } 2520 tlen++; 2521 /* disk_count may change when malloc sleeps */ 2522 count = disk_count; 2523 2524 /* 2525 * The sysctl_disklock ensures that no other process can 2526 * allocate disknames and diskstats while our malloc sleeps. 2527 */ 2528 free(disknames, M_SYSCTL, disknameslen); 2529 free(diskstats, M_SYSCTL, diskstatslen); 2530 diskstats = NULL; 2531 disknames = NULL; 2532 diskstats = mallocarray(count, sizeof(struct diskstats), 2533 M_SYSCTL, M_WAITOK|M_ZERO); 2534 diskstatslen = count * sizeof(struct diskstats); 2535 disknames = malloc(tlen, M_SYSCTL, M_WAITOK|M_ZERO); 2536 disknameslen = tlen; 2537 disknames[0] = '\0'; 2538 changed = 1; 2539 } 2540 2541 if (changed) { 2542 int l; 2543 2544 l = 0; 2545 sdk = diskstats; 2546 TAILQ_FOREACH(dk, &disklist, dk_link) { 2547 duid = NULL; 2548 if (dk->dk_label && !duid_iszero(dk->dk_label->d_uid)) 2549 duid = duid_format(dk->dk_label->d_uid); 2550 snprintf(disknames + l, disknameslen - l, "%s:%s,", 2551 dk->dk_name ? dk->dk_name : "", 2552 duid ? duid : ""); 2553 l += strlen(disknames + l); 2554 strlcpy(sdk->ds_name, dk->dk_name, 2555 sizeof(sdk->ds_name)); 2556 mtx_enter(&dk->dk_mtx); 2557 sdk->ds_busy = dk->dk_busy; 2558 sdk->ds_rxfer = dk->dk_rxfer; 2559 sdk->ds_wxfer = dk->dk_wxfer; 2560 sdk->ds_seek = dk->dk_seek; 2561 sdk->ds_rbytes = dk->dk_rbytes; 2562 sdk->ds_wbytes = dk->dk_wbytes; 2563 sdk->ds_attachtime = dk->dk_attachtime; 2564 sdk->ds_timestamp = dk->dk_timestamp; 2565 sdk->ds_time = dk->dk_time; 2566 mtx_leave(&dk->dk_mtx); 2567 sdk++; 2568 } 2569 2570 /* Eliminate trailing comma */ 2571 if (l != 0) 2572 disknames[l - 1] = '\0'; 2573 } else if (update) { 2574 /* Just update, number of drives hasn't changed */ 2575 sdk = diskstats; 2576 TAILQ_FOREACH(dk, &disklist, dk_link) { 2577 strlcpy(sdk->ds_name, dk->dk_name, 2578 sizeof(sdk->ds_name)); 2579 mtx_enter(&dk->dk_mtx); 2580 sdk->ds_busy = dk->dk_busy; 2581 sdk->ds_rxfer = dk->dk_rxfer; 2582 sdk->ds_wxfer = dk->dk_wxfer; 2583 sdk->ds_seek = dk->dk_seek; 2584 sdk->ds_rbytes = dk->dk_rbytes; 2585 sdk->ds_wbytes = dk->dk_wbytes; 2586 sdk->ds_attachtime = dk->dk_attachtime; 2587 sdk->ds_timestamp = dk->dk_timestamp; 2588 sdk->ds_time = dk->dk_time; 2589 mtx_leave(&dk->dk_mtx); 2590 sdk++; 2591 } 2592 } 2593 rw_exit_write(&sysctl_disklock); 2594 return 0; 2595 } 2596 2597 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 2598 int 2599 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 2600 { 2601 #ifdef SYSVSEM 2602 struct sem_sysctl_info *semsi; 2603 #endif 2604 #ifdef SYSVSHM 2605 struct shm_sysctl_info *shmsi; 2606 #endif 2607 size_t infosize, dssize, tsize, buflen, bufsiz; 2608 int i, nds, error, ret; 2609 void *buf; 2610 2611 if (namelen != 1) 2612 return (EINVAL); 2613 2614 buflen = *sizep; 2615 2616 switch (*name) { 2617 case KERN_SYSVIPC_MSG_INFO: 2618 #ifdef SYSVMSG 2619 return (sysctl_sysvmsg(name, namelen, where, sizep)); 2620 #else 2621 return (EOPNOTSUPP); 2622 #endif 2623 case KERN_SYSVIPC_SEM_INFO: 2624 #ifdef SYSVSEM 2625 infosize = sizeof(semsi->seminfo); 2626 nds = seminfo.semmni; 2627 dssize = sizeof(semsi->semids[0]); 2628 break; 2629 #else 2630 return (EOPNOTSUPP); 2631 #endif 2632 case KERN_SYSVIPC_SHM_INFO: 2633 #ifdef SYSVSHM 2634 infosize = sizeof(shmsi->shminfo); 2635 nds = shminfo.shmmni; 2636 dssize = sizeof(shmsi->shmids[0]); 2637 break; 2638 #else 2639 return (EOPNOTSUPP); 2640 #endif 2641 default: 2642 return (EINVAL); 2643 } 2644 tsize = infosize + (nds * dssize); 2645 2646 /* Return just the total size required. */ 2647 if (where == NULL) { 2648 *sizep = tsize; 2649 return (0); 2650 } 2651 2652 /* Not enough room for even the info struct. */ 2653 if (buflen < infosize) { 2654 *sizep = 0; 2655 return (ENOMEM); 2656 } 2657 bufsiz = min(tsize, buflen); 2658 buf = malloc(bufsiz, M_TEMP, M_WAITOK|M_ZERO); 2659 2660 switch (*name) { 2661 #ifdef SYSVSEM 2662 case KERN_SYSVIPC_SEM_INFO: 2663 semsi = (struct sem_sysctl_info *)buf; 2664 semsi->seminfo = seminfo; 2665 break; 2666 #endif 2667 #ifdef SYSVSHM 2668 case KERN_SYSVIPC_SHM_INFO: 2669 shmsi = (struct shm_sysctl_info *)buf; 2670 shmsi->shminfo = shminfo; 2671 break; 2672 #endif 2673 } 2674 buflen -= infosize; 2675 2676 ret = 0; 2677 if (buflen > 0) { 2678 /* Fill in the IPC data structures. */ 2679 for (i = 0; i < nds; i++) { 2680 if (buflen < dssize) { 2681 ret = ENOMEM; 2682 break; 2683 } 2684 switch (*name) { 2685 #ifdef SYSVSEM 2686 case KERN_SYSVIPC_SEM_INFO: 2687 if (sema[i] != NULL) 2688 memcpy(&semsi->semids[i], sema[i], 2689 dssize); 2690 else 2691 memset(&semsi->semids[i], 0, dssize); 2692 break; 2693 #endif 2694 #ifdef SYSVSHM 2695 case KERN_SYSVIPC_SHM_INFO: 2696 if (shmsegs[i] != NULL) 2697 memcpy(&shmsi->shmids[i], shmsegs[i], 2698 dssize); 2699 else 2700 memset(&shmsi->shmids[i], 0, dssize); 2701 break; 2702 #endif 2703 } 2704 buflen -= dssize; 2705 } 2706 } 2707 *sizep -= buflen; 2708 error = copyout(buf, where, *sizep); 2709 free(buf, M_TEMP, bufsiz); 2710 /* If copyout succeeded, use return code set earlier. */ 2711 return (error ? error : ret); 2712 } 2713 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 2714 2715 #ifndef SMALL_KERNEL 2716 2717 int 2718 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 2719 { 2720 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0)); 2721 } 2722 2723 2724 int 2725 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2726 void *newp, size_t newlen) 2727 { 2728 struct ksensor *ks; 2729 struct sensor *us; 2730 struct ksensordev *ksd; 2731 struct sensordev *usd; 2732 int dev, numt, ret; 2733 enum sensor_type type; 2734 2735 if (namelen != 1 && namelen != 3) 2736 return (ENOTDIR); 2737 2738 dev = name[0]; 2739 if (namelen == 1) { 2740 ret = sensordev_get(dev, &ksd); 2741 if (ret) 2742 return (ret); 2743 2744 /* Grab a copy, to clear the kernel pointers */ 2745 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO); 2746 usd->num = ksd->num; 2747 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname)); 2748 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt)); 2749 usd->sensors_count = ksd->sensors_count; 2750 2751 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd, 2752 sizeof(struct sensordev)); 2753 2754 free(usd, M_TEMP, sizeof(*usd)); 2755 return (ret); 2756 } 2757 2758 type = name[1]; 2759 numt = name[2]; 2760 2761 ret = sensor_find(dev, type, numt, &ks); 2762 if (ret) 2763 return (ret); 2764 2765 /* Grab a copy, to clear the kernel pointers */ 2766 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO); 2767 memcpy(us->desc, ks->desc, sizeof(us->desc)); 2768 us->tv = ks->tv; 2769 us->value = ks->value; 2770 us->type = ks->type; 2771 us->status = ks->status; 2772 us->numt = ks->numt; 2773 us->flags = ks->flags; 2774 2775 ret = sysctl_rdstruct(oldp, oldlenp, newp, us, 2776 sizeof(struct sensor)); 2777 free(us, M_TEMP, sizeof(*us)); 2778 return (ret); 2779 } 2780 #endif /* SMALL_KERNEL */ 2781 2782 int 2783 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2784 void *newp, size_t newlen) 2785 { 2786 CPU_INFO_ITERATOR cii; 2787 struct cpu_info *ci; 2788 int found = 0; 2789 2790 if (namelen != 1) 2791 return (ENOTDIR); 2792 2793 CPU_INFO_FOREACH(cii, ci) { 2794 if (name[0] == CPU_INFO_UNIT(ci)) { 2795 found = 1; 2796 break; 2797 } 2798 } 2799 if (!found) 2800 return (ENOENT); 2801 2802 return (sysctl_rdstruct(oldp, oldlenp, newp, 2803 &ci->ci_schedstate.spc_cp_time, 2804 sizeof(ci->ci_schedstate.spc_cp_time))); 2805 } 2806 2807 #if NAUDIO > 0 2808 int 2809 sysctl_audio(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2810 void *newp, size_t newlen) 2811 { 2812 if (namelen != 1) 2813 return (ENOTDIR); 2814 2815 if (name[0] != KERN_AUDIO_RECORD) 2816 return (ENOENT); 2817 2818 return (sysctl_int(oldp, oldlenp, newp, newlen, &audio_record_enable)); 2819 } 2820 #endif 2821 2822 #if NVIDEO > 0 2823 int 2824 sysctl_video(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2825 void *newp, size_t newlen) 2826 { 2827 if (namelen != 1) 2828 return (ENOTDIR); 2829 2830 if (name[0] != KERN_VIDEO_RECORD) 2831 return (ENOENT); 2832 2833 return (sysctl_int(oldp, oldlenp, newp, newlen, &video_record_enable)); 2834 } 2835 #endif 2836 2837 int 2838 sysctl_cpustats(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2839 void *newp, size_t newlen) 2840 { 2841 CPU_INFO_ITERATOR cii; 2842 struct cpustats cs; 2843 struct cpu_info *ci; 2844 int found = 0; 2845 2846 if (namelen != 1) 2847 return (ENOTDIR); 2848 2849 CPU_INFO_FOREACH(cii, ci) { 2850 if (name[0] == CPU_INFO_UNIT(ci)) { 2851 found = 1; 2852 break; 2853 } 2854 } 2855 if (!found) 2856 return (ENOENT); 2857 2858 memset(&cs, 0, sizeof cs); 2859 memcpy(&cs.cs_time, &ci->ci_schedstate.spc_cp_time, sizeof(cs.cs_time)); 2860 cs.cs_flags = 0; 2861 if (cpu_is_online(ci)) 2862 cs.cs_flags |= CPUSTATS_ONLINE; 2863 2864 return (sysctl_rdstruct(oldp, oldlenp, newp, &cs, sizeof(cs))); 2865 } 2866 2867 int 2868 sysctl_utc_offset(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 2869 { 2870 struct timespec adjusted, now; 2871 int adjustment_seconds, error, new_offset_minutes, old_offset_minutes; 2872 2873 old_offset_minutes = utc_offset / 60; /* seconds -> minutes */ 2874 new_offset_minutes = old_offset_minutes; 2875 error = sysctl_securelevel_int(oldp, oldlenp, newp, newlen, 2876 &new_offset_minutes); 2877 if (error) 2878 return error; 2879 if (new_offset_minutes < -24 * 60 || new_offset_minutes > 24 * 60) 2880 return EINVAL; 2881 if (new_offset_minutes == old_offset_minutes) 2882 return 0; 2883 2884 utc_offset = new_offset_minutes * 60; /* minutes -> seconds */ 2885 adjustment_seconds = (new_offset_minutes - old_offset_minutes) * 60; 2886 2887 nanotime(&now); 2888 adjusted = now; 2889 adjusted.tv_sec -= adjustment_seconds; 2890 tc_setrealtimeclock(&adjusted); 2891 resettodr(); 2892 2893 return 0; 2894 } 2895