LCOV - code coverage report
Current view: top level - kern - kern_sysctl.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1155 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13