The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_sysctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
   26 /*-
   27  * Copyright (c) 1982, 1986, 1989, 1993
   28  *      The Regents of the University of California.  All rights reserved.
   29  *
   30  * This code is derived from software contributed to Berkeley by
   31  * Mike Karels at Berkeley Software Design, Inc.
   32  *
   33  * Redistribution and use in source and binary forms, with or without
   34  * modification, are permitted provided that the following conditions
   35  * are met:
   36  * 1. Redistributions of source code must retain the above copyright
   37  *    notice, this list of conditions and the following disclaimer.
   38  * 2. Redistributions in binary form must reproduce the above copyright
   39  *    notice, this list of conditions and the following disclaimer in the
   40  *    documentation and/or other materials provided with the distribution.
   41  * 3. All advertising materials mentioning features or use of this software
   42  *    must display the following acknowledgement:
   43  *      This product includes software developed by the University of
   44  *      California, Berkeley and its contributors.
   45  * 4. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
   62  */
   63 
   64 /*
   65  * sysctl system call.
   66  */
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/kernel.h>
   71 #include <sys/malloc.h>
   72 #include <sys/proc.h>
   73 #include <sys/file.h>
   74 #include <sys/vnode.h>
   75 #include <sys/unistd.h>
   76 #include <sys/buf.h>
   77 #include <sys/ioctl.h>
   78 #include <sys/namei.h>
   79 #include <sys/tty.h>
   80 #include <sys/disklabel.h>
   81 #include <sys/vm.h>
   82 #include <sys/sysctl.h>
   83 #include <sys/user.h>
   84 #include <sys/aio_kern.h>
   85 #include <mach/machine.h>
   86 #include <mach/mach_types.h>
   87 #include <mach/vm_param.h>
   88 #include <kern/task.h>
   89 #include <vm/vm_kern.h>
   90 #include <mach/host_info.h>
   91 
   92 extern vm_map_t bsd_pageable_map;
   93 
   94 #include <sys/mount.h>
   95 #include <sys/kdebug.h>
   96 
   97 #include <IOKit/IOPlatformExpert.h>
   98 #include <pexpert/pexpert.h>
   99 
  100 #include <machine/machine_routines.h>
  101 
  102 sysctlfn kern_sysctl;
  103 #ifdef DEBUG
  104 sysctlfn debug_sysctl;
  105 #endif
  106 extern sysctlfn vm_sysctl;
  107 extern sysctlfn vfs_sysctl;
  108 extern sysctlfn net_sysctl;
  109 extern sysctlfn cpu_sysctl;
  110 extern int aio_max_requests;                            
  111 extern int aio_max_requests_per_process;        
  112 extern int aio_worker_threads;                          
  113 extern int maxprocperuid;
  114 extern int maxfilesperproc;
  115 
  116 
  117 int
  118 userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t 
  119                 *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
  120 
  121 static int
  122 sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  123 static int
  124 sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  125 static int
  126 sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  127 static void
  128 fill_proc(struct proc *p, struct kinfo_proc *kp);
  129 static int
  130 sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  131 static int
  132 sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  133 static int
  134 sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
  135 static int
  136 sysctl_procargs2( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc);
  137 static int
  138 sysctl_procargsx( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc, int argc_yes);
  139 
  140 
  141 /*
  142  * temporary location for vm_sysctl.  This should be machine independant
  143  */
  144 int
  145 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
  146         int *name;
  147         u_int namelen;
  148         void *oldp;
  149         size_t *oldlenp;
  150         void *newp;
  151         size_t newlen;
  152         struct proc *p;
  153 {
  154         extern uint32_t mach_factor[3];
  155         struct loadavg loadinfo;
  156 
  157         switch (name[0]) {
  158         case VM_LOADAVG:
  159                 return (sysctl_struct(oldp, oldlenp, newp, newlen,
  160                                         &averunnable, sizeof(struct loadavg)));
  161         case VM_MACHFACTOR:
  162                 loadinfo.ldavg[0] = mach_factor[0];
  163                 loadinfo.ldavg[1] = mach_factor[1];
  164                 loadinfo.ldavg[2] = mach_factor[2];
  165                 loadinfo.fscale = LSCALE;
  166                 return (sysctl_struct(oldp, oldlenp, newp, newlen,
  167                                         &loadinfo, sizeof(struct loadavg)));
  168         case VM_METER:
  169                 return (EOPNOTSUPP);
  170         case VM_MAXID:
  171                 return (EOPNOTSUPP);
  172         default:
  173                 return (EOPNOTSUPP);
  174         }
  175         /* NOTREACHED */
  176         return (EOPNOTSUPP);
  177 }
  178 
  179 /*
  180  * Locking and stats
  181  */
  182 static struct sysctl_lock {
  183         int     sl_lock;
  184         int     sl_want;
  185         int     sl_locked;
  186 } memlock;
  187 
  188 struct __sysctl_args {
  189         int *name;
  190         u_int namelen;
  191         void *old;
  192         size_t *oldlenp;
  193         void *new;
  194         size_t newlen;
  195 };
  196 int
  197 __sysctl(p, uap, retval)
  198         struct proc *p;
  199         register struct __sysctl_args *uap;
  200         register_t *retval;
  201 {
  202         int error, dolock = 1;
  203         size_t savelen, oldlen = 0;
  204         sysctlfn *fn;
  205         int name[CTL_MAXNAME];
  206         int i;
  207         int error1;
  208 
  209         /*
  210          * all top-level sysctl names are non-terminal
  211          */
  212         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
  213                 return (EINVAL);
  214         if (error =
  215             copyin(uap->name, &name, uap->namelen * sizeof(int)))
  216                 return (error);
  217 
  218         /* CTL_UNSPEC is used to get oid to AUTO_OID */
  219         if (uap->new != NULL
  220                 && ((name[0] == CTL_KERN
  221                                 && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO))
  222                         || (name[0] == CTL_HW)
  223                         || (name[0] == CTL_VM)
  224                         || (name[0] == CTL_VFS))
  225                 && (error = suser(p->p_ucred, &p->p_acflag)))
  226                 return (error);
  227 
  228         switch (name[0]) {
  229         case CTL_KERN:
  230                 fn = kern_sysctl;
  231                 if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE) 
  232                         && (name[1] != KERN_PROC))
  233                         dolock = 0;
  234                 break;
  235         case CTL_VM:
  236                 fn = vm_sysctl;
  237                 break;
  238                 
  239         case CTL_VFS:
  240                 fn = vfs_sysctl;
  241                 break;
  242 #ifdef DEBUG
  243         case CTL_DEBUG:
  244                 fn = debug_sysctl;
  245                 break;
  246 #endif
  247         default:
  248                 fn = 0;
  249         }
  250 
  251         if (uap->oldlenp &&
  252             (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
  253                 return (error);
  254 
  255         if (uap->old != NULL) {
  256                 if (!useracc(uap->old, oldlen, B_WRITE))
  257                         return (EFAULT);
  258 
  259                 /* The pc sampling mechanism does not need to take this lock */
  260                 if ((name[1] != KERN_PCSAMPLES) &&
  261                     (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
  262                   while (memlock.sl_lock) {
  263                         memlock.sl_want = 1;
  264                         sleep((caddr_t)&memlock, PRIBIO+1);
  265                         memlock.sl_locked++;
  266                   }
  267                   memlock.sl_lock = 1;
  268                 }
  269 
  270                 if (dolock && oldlen && (error = vslock(uap->old, oldlen))) {
  271                         if ((name[1] != KERN_PCSAMPLES) &&
  272                            (! ((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
  273                                 memlock.sl_lock = 0;
  274                                 if (memlock.sl_want) {
  275                                 memlock.sl_want = 0;
  276                                         wakeup((caddr_t)&memlock);
  277                                 }
  278                         }
  279                         return(error);
  280                 }
  281                 savelen = oldlen;
  282         }
  283 
  284         if (fn)
  285             error = (*fn)(name + 1, uap->namelen - 1, uap->old,
  286                           &oldlen, uap->new, uap->newlen, p);
  287         else
  288             error = EOPNOTSUPP;
  289 
  290         if ( (name[0] != CTL_VFS) && (error == EOPNOTSUPP))
  291                 error = userland_sysctl(p, name, uap->namelen,
  292                                         uap->old, uap->oldlenp, 0,
  293                                         uap->new, uap->newlen, &oldlen);
  294 
  295         if (uap->old != NULL) {
  296                 if (dolock && savelen) {
  297                         error1 = vsunlock(uap->old, savelen, B_WRITE);
  298                         if (!error &&  error1)
  299                                 error = error1;
  300                 }
  301                 if (name[1] != KERN_PCSAMPLES) {
  302                   memlock.sl_lock = 0;
  303                   if (memlock.sl_want) {
  304                         memlock.sl_want = 0;
  305                         wakeup((caddr_t)&memlock);
  306                   }
  307                 }
  308         }
  309         if ((error) && (error != ENOMEM))
  310                 return (error);
  311 
  312         if (uap->oldlenp) {
  313                 i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
  314                 if (i) 
  315                     return i;
  316         }
  317 
  318         return (error);
  319 }
  320 
  321 /*
  322  * Attributes stored in the kernel.
  323  */
  324 extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
  325 extern int hostnamelen;
  326 extern char domainname[MAXHOSTNAMELEN];
  327 extern int domainnamelen;
  328 extern char classichandler[32];
  329 extern long classichandler_fsid;
  330 extern long classichandler_fileid;
  331 
  332 extern long hostid;
  333 #ifdef INSECURE
  334 int securelevel = -1;
  335 #else
  336 int securelevel;
  337 #endif
  338 
  339 static int
  340 sysctl_affinity(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
  341         int *name;
  342         u_int namelen;
  343         char *oldBuf;
  344         size_t *oldSize;
  345         char *newBuf;
  346         size_t newSize;
  347         struct proc *cur_proc;
  348 {
  349         if (namelen < 1)
  350                 return (EOPNOTSUPP);
  351 
  352         if (name[0] == 0 && 1 == namelen) {
  353                 return sysctl_rdint(oldBuf, oldSize, newBuf,
  354                         (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
  355         } else if (name[0] == 1 && 2 == namelen) {
  356                 if (name[1] == 0) {
  357                         cur_proc->p_flag &= ~P_AFFINITY;
  358                 } else {
  359                         cur_proc->p_flag |= P_AFFINITY;
  360                 }
  361                 return 0;
  362         }
  363         return (EOPNOTSUPP);
  364 }
  365 
  366 static int
  367 sysctl_classic(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
  368         int *name;
  369         u_int namelen;
  370         char *oldBuf;
  371         size_t *oldSize;
  372         char *newBuf;
  373         size_t newSize;
  374         struct proc *cur_proc;
  375 {
  376         int newVal;
  377         int err;
  378         struct proc *p;
  379 
  380         if (namelen != 1)
  381                 return (EOPNOTSUPP);
  382 
  383         p = pfind(name[0]);
  384         if (p == NULL)
  385                 return (EINVAL);
  386 
  387         if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid) 
  388                 && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
  389                 return (EPERM);
  390 
  391         return sysctl_rdint(oldBuf, oldSize, newBuf,
  392                 (p->p_flag & P_CLASSIC) ? 1 : 0);
  393 }
  394 
  395 static int
  396 sysctl_classichandler(name, namelen, oldBuf, oldSize, newBuf, newSize, p)
  397         int *name;
  398         u_int namelen;
  399         char *oldBuf;
  400         size_t *oldSize;
  401         char *newBuf;
  402         size_t newSize;
  403         struct proc *p;
  404 {
  405         int error;
  406         int len;
  407         struct nameidata nd;
  408         struct vattr vattr;
  409         char handler[sizeof(classichandler)];
  410 
  411         if ((error = suser(p->p_ucred, &p->p_acflag)))
  412                 return (error);
  413         len = strlen(classichandler) + 1;
  414         if (oldBuf && *oldSize < len)
  415                 return (ENOMEM);
  416         if (newBuf && newSize >= sizeof(classichandler))
  417                 return (ENAMETOOLONG);
  418         *oldSize = len - 1;
  419         if (newBuf) {
  420                 error = copyin(newBuf, handler, newSize);
  421                 if (error)
  422                         return (error);
  423                 handler[newSize] = 0;
  424 
  425                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
  426                                 handler, p);
  427                 error = namei(&nd);
  428                 if (error)
  429                         return (error);
  430                 /* Check mount point */
  431                 if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||
  432                         (nd.ni_vp->v_type != VREG)) {
  433                         vput(nd.ni_vp);
  434                         return (EACCES);
  435                 }
  436                 error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
  437                 if (error) {
  438                         vput(nd.ni_vp);
  439                         return (error);
  440                 }
  441                 classichandler_fsid = vattr.va_fsid;
  442                 classichandler_fileid = vattr.va_fileid;
  443                 vput(nd.ni_vp);
  444         }
  445         if (oldBuf) {
  446                 error = copyout(classichandler, oldBuf, len);
  447                 if (error)
  448                         return (error);
  449         }
  450         if (newBuf) {
  451                 strcpy(classichandler, handler);
  452         }
  453         return (error);
  454 }
  455 
  456 
  457 extern int get_kernel_symfile( struct proc *, char **);
  458 extern int sysctl_dopanicinfo(int *, u_int, void *, size_t *,
  459                         void *, size_t, struct proc *);
  460 
  461 /*
  462  * kernel related system variables.
  463  */
  464 int
  465 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
  466         int *name;
  467         u_int namelen;
  468         void *oldp;
  469         size_t *oldlenp;
  470         void *newp;
  471         size_t newlen;
  472         struct proc *p;
  473 {
  474         int error, level, inthostid;
  475         unsigned int oldval=0;
  476         char *str;
  477         extern char ostype[], osrelease[], version[];
  478         extern int netboot_root();
  479 
  480         /* all sysctl names not listed below are terminal at this level */
  481         if (namelen != 1
  482                 && !(name[0] == KERN_PROC
  483                         || name[0] == KERN_PROF 
  484                         || name[0] == KERN_KDEBUG
  485                         || name[0] == KERN_PROCARGS
  486                         || name[0] == KERN_PROCARGS2
  487                         || name[0] == KERN_PCSAMPLES
  488                         || name[0] == KERN_IPC
  489                         || name[0] == KERN_SYSV
  490                         || name[0] == KERN_AFFINITY
  491                         || name[0] == KERN_CLASSIC
  492                         || name[0] == KERN_PANICINFO)
  493                 )
  494                 return (ENOTDIR);               /* overloaded */
  495 
  496         switch (name[0]) {
  497         case KERN_OSTYPE:
  498                 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
  499         case KERN_OSRELEASE:
  500                 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
  501         case KERN_OSREV:
  502                 return (sysctl_rdint(oldp, oldlenp, newp, BSD));
  503         case KERN_VERSION:
  504                 return (sysctl_rdstring(oldp, oldlenp, newp, version));
  505         case KERN_MAXVNODES:
  506                 oldval = desiredvnodes;
  507                 error = sysctl_int(oldp, oldlenp, newp, 
  508                                 newlen, &desiredvnodes);
  509                 reset_vmobjectcache(oldval, desiredvnodes);
  510                 resize_namecache(desiredvnodes);
  511                 return(error);
  512         case KERN_MAXPROC:
  513                 return (sysctl_maxproc(oldp, oldlenp, newp, newlen));
  514         case KERN_MAXFILES:
  515                 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
  516         case KERN_MAXPROCPERUID:
  517                 return( sysctl_maxprocperuid( oldp, oldlenp, newp, newlen ) );
  518         case KERN_MAXFILESPERPROC:
  519                 return( sysctl_maxfilesperproc( oldp, oldlenp, newp, newlen ) );
  520         case KERN_ARGMAX:
  521                 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
  522         case KERN_SECURELVL:
  523                 level = securelevel;
  524                 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
  525                     newp == NULL)
  526                         return (error);
  527                 if (level < securelevel && p->p_pid != 1)
  528                         return (EPERM);
  529                 securelevel = level;
  530                 return (0);
  531         case KERN_HOSTNAME:
  532                 error = sysctl_string(oldp, oldlenp, newp, newlen,
  533                     hostname, sizeof(hostname));
  534                 if (newp && !error)
  535                         hostnamelen = newlen;
  536                 return (error);
  537         case KERN_DOMAINNAME:
  538                 error = sysctl_string(oldp, oldlenp, newp, newlen,
  539                     domainname, sizeof(domainname));
  540                 if (newp && !error)
  541                         domainnamelen = newlen;
  542                 return (error);
  543         case KERN_HOSTID:
  544                 inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
  545                 error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
  546                 hostid = inthostid;
  547                 return (error);
  548         case KERN_CLOCKRATE:
  549                 return (sysctl_clockrate(oldp, oldlenp));
  550         case KERN_BOOTTIME:
  551                 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
  552                     sizeof(struct timeval)));
  553         case KERN_VNODE:
  554                 return (sysctl_vnode(oldp, oldlenp));
  555         case KERN_PROC:
  556                 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
  557         case KERN_FILE:
  558                 return (sysctl_file(oldp, oldlenp));
  559 #ifdef GPROF
  560         case KERN_PROF:
  561                 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
  562                     newp, newlen));
  563 #endif
  564         case KERN_POSIX1:
  565                 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
  566         case KERN_NGROUPS:
  567                 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
  568         case KERN_JOB_CONTROL:
  569                 return (sysctl_rdint(oldp, oldlenp, newp, 1));
  570         case KERN_SAVED_IDS:
  571 #ifdef _POSIX_SAVED_IDS
  572                 return (sysctl_rdint(oldp, oldlenp, newp, 1));
  573 #else
  574                 return (sysctl_rdint(oldp, oldlenp, newp, 0));
  575 #endif
  576         case KERN_KDEBUG:
  577                 return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
  578         case KERN_PCSAMPLES:
  579                 return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
  580         case KERN_PROCARGS:
  581                 /* new one as it does not use kinfo_proc */
  582                 return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
  583         case KERN_PROCARGS2:
  584                 /* new one as it does not use kinfo_proc */
  585                 return (sysctl_procargs2(name + 1, namelen - 1, oldp, oldlenp, p));
  586         case KERN_SYMFILE:
  587                 error = get_kernel_symfile( p, &str );
  588                 if ( error )
  589                         return error;
  590                 return (sysctl_rdstring(oldp, oldlenp, newp, str));
  591         case KERN_NETBOOT:
  592                 return (sysctl_rdint(oldp, oldlenp, newp, netboot_root()));
  593         case KERN_PANICINFO:
  594                 return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
  595                         newp, newlen, p));
  596         case KERN_AFFINITY:
  597                 return sysctl_affinity(name+1, namelen-1, oldp, oldlenp,
  598                                                                         newp, newlen, p);
  599         case KERN_CLASSIC:
  600                 return sysctl_classic(name+1, namelen-1, oldp, oldlenp,
  601                                                                 newp, newlen, p);
  602         case KERN_CLASSICHANDLER:
  603                 return sysctl_classichandler(name+1, namelen-1, oldp, oldlenp,
  604                                                                                 newp, newlen, p);
  605         case KERN_AIOMAX:
  606                 return( sysctl_aiomax( oldp, oldlenp, newp, newlen ) );
  607         case KERN_AIOPROCMAX:
  608                 return( sysctl_aioprocmax( oldp, oldlenp, newp, newlen ) );
  609         case KERN_AIOTHREADS:
  610                 return( sysctl_aiothreads( oldp, oldlenp, newp, newlen ) );
  611         default:
  612                 return (EOPNOTSUPP);
  613         }
  614         /* NOTREACHED */
  615 }
  616 
  617 #ifdef DEBUG
  618 /*
  619  * Debugging related system variables.
  620  */
  621 #if DIAGNOSTIC
  622 extern
  623 #endif /* DIAGNOSTIC */
  624 struct ctldebug debug0, debug1;
  625 struct ctldebug debug2, debug3, debug4;
  626 struct ctldebug debug5, debug6, debug7, debug8, debug9;
  627 struct ctldebug debug10, debug11, debug12, debug13, debug14;
  628 struct ctldebug debug15, debug16, debug17, debug18, debug19;
  629 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
  630         &debug0, &debug1, &debug2, &debug3, &debug4,
  631         &debug5, &debug6, &debug7, &debug8, &debug9,
  632         &debug10, &debug11, &debug12, &debug13, &debug14,
  633         &debug15, &debug16, &debug17, &debug18, &debug19,
  634 };
  635 int
  636 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
  637         int *name;
  638         u_int namelen;
  639         void *oldp;
  640         size_t *oldlenp;
  641         void *newp;
  642         size_t newlen;
  643         struct proc *p;
  644 {
  645         struct ctldebug *cdp;
  646 
  647         /* all sysctl names at this level are name and field */
  648         if (namelen != 2)
  649                 return (ENOTDIR);               /* overloaded */
  650         cdp = debugvars[name[0]];
  651         if (cdp->debugname == 0)
  652                 return (EOPNOTSUPP);
  653         switch (name[1]) {
  654         case CTL_DEBUG_NAME:
  655                 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
  656         case CTL_DEBUG_VALUE:
  657                 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
  658         default:
  659                 return (EOPNOTSUPP);
  660         }
  661         /* NOTREACHED */
  662 }
  663 #endif /* DEBUG */
  664 
  665 /*
  666  * Validate parameters and get old / set new parameters
  667  * for an integer-valued sysctl function.
  668  */
  669 int
  670 sysctl_int(oldp, oldlenp, newp, newlen, valp)
  671         void *oldp;
  672         size_t *oldlenp;
  673         void *newp;
  674         size_t newlen;
  675         int *valp;
  676 {
  677         int error = 0;
  678 
  679         if (oldp && *oldlenp < sizeof(int))
  680                 return (ENOMEM);
  681         if (newp && newlen != sizeof(int))
  682                 return (EINVAL);
  683         *oldlenp = sizeof(int);
  684         if (oldp)
  685                 error = copyout(valp, oldp, sizeof(int));
  686         if (error == 0 && newp)
  687                 error = copyin(newp, valp, sizeof(int));
  688         return (error);
  689 }
  690 
  691 /*
  692  * As above, but read-only.
  693  */
  694 int
  695 sysctl_rdint(oldp, oldlenp, newp, val)
  696         void *oldp;
  697         size_t *oldlenp;
  698         void *newp;
  699         int val;
  700 {
  701         int error = 0;
  702 
  703         if (oldp && *oldlenp < sizeof(int))
  704                 return (ENOMEM);
  705         if (newp)
  706                 return (EPERM);
  707         *oldlenp = sizeof(int);
  708         if (oldp)
  709                 error = copyout((caddr_t)&val, oldp, sizeof(int));
  710         return (error);
  711 }
  712 
  713 /*
  714  * Validate parameters and get old / set new parameters
  715  * for an quad(64bit)-valued sysctl function.
  716  */
  717 int
  718 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
  719         void *oldp;
  720         size_t *oldlenp;
  721         void *newp;
  722         size_t newlen;
  723         quad_t *valp;
  724 {
  725         int error = 0;
  726 
  727         if (oldp && *oldlenp < sizeof(quad_t))
  728                 return (ENOMEM);
  729         if (newp && newlen != sizeof(quad_t))
  730                 return (EINVAL);
  731         *oldlenp = sizeof(quad_t);
  732         if (oldp)
  733                 error = copyout(valp, oldp, sizeof(quad_t));
  734         if (error == 0 && newp)
  735                 error = copyin(newp, valp, sizeof(quad_t));
  736         return (error);
  737 }
  738 
  739 /*
  740  * As above, but read-only.
  741  */
  742 int
  743 sysctl_rdquad(oldp, oldlenp, newp, val)
  744         void *oldp;
  745         size_t *oldlenp;
  746         void *newp;
  747         quad_t val;
  748 {
  749         int error = 0;
  750 
  751         if (oldp && *oldlenp < sizeof(quad_t))
  752                 return (ENOMEM);
  753         if (newp)
  754                 return (EPERM);
  755         *oldlenp = sizeof(quad_t);
  756         if (oldp)
  757                 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
  758         return (error);
  759 }
  760 
  761 /*
  762  * Validate parameters and get old / set new parameters
  763  * for a string-valued sysctl function.
  764  */
  765 int
  766 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
  767         void *oldp;
  768         size_t *oldlenp;
  769         void *newp;
  770         size_t newlen;
  771         char *str;
  772         int maxlen;
  773 {
  774         int len, error = 0;
  775 
  776         len = strlen(str) + 1;
  777         if (oldp && *oldlenp < len)
  778                 return (ENOMEM);
  779         if (newp && newlen >= maxlen)
  780                 return (EINVAL);
  781         *oldlenp = len -1; /* deal with NULL strings correctly */
  782         if (oldp) {
  783                 error = copyout(str, oldp, len);
  784         }
  785         if (error == 0 && newp) {
  786                 error = copyin(newp, str, newlen);
  787                 str[newlen] = 0;
  788         }
  789         return (error);
  790 }
  791 
  792 /*
  793  * As above, but read-only.
  794  */
  795 int
  796 sysctl_rdstring(oldp, oldlenp, newp, str)
  797         void *oldp;
  798         size_t *oldlenp;
  799         void *newp;
  800         char *str;
  801 {
  802         int len, error = 0;
  803 
  804         len = strlen(str) + 1;
  805         if (oldp && *oldlenp < len)
  806                 return (ENOMEM);
  807         if (newp)
  808                 return (EPERM);
  809         *oldlenp = len;
  810         if (oldp)
  811                 error = copyout(str, oldp, len);
  812         return (error);
  813 }
  814 
  815 /*
  816  * Validate parameters and get old / set new parameters
  817  * for a structure oriented sysctl function.
  818  */
  819 int
  820 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
  821         void *oldp;
  822         size_t *oldlenp;
  823         void *newp;
  824         size_t newlen;
  825         void *sp;
  826         int len;
  827 {
  828         int error = 0;
  829 
  830         if (oldp && *oldlenp < len)
  831                 return (ENOMEM);
  832         if (newp && newlen > len)
  833                 return (EINVAL);
  834         if (oldp) {
  835                 *oldlenp = len;
  836                 error = copyout(sp, oldp, len);
  837         }
  838         if (error == 0 && newp)
  839                 error = copyin(newp, sp, len);
  840         return (error);
  841 }
  842 
  843 /*
  844  * Validate parameters and get old parameters
  845  * for a structure oriented sysctl function.
  846  */
  847 int
  848 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
  849         void *oldp;
  850         size_t *oldlenp;
  851         void *newp, *sp;
  852         int len;
  853 {
  854         int error = 0;
  855 
  856         if (oldp && *oldlenp < len)
  857                 return (ENOMEM);
  858         if (newp)
  859                 return (EPERM);
  860         *oldlenp = len;
  861         if (oldp)
  862                 error = copyout(sp, oldp, len);
  863         return (error);
  864 }
  865 
  866 /*
  867  * Get file structures.
  868  */
  869 int
  870 sysctl_file(where, sizep)
  871         char *where;
  872         size_t *sizep;
  873 {
  874         int buflen, error;
  875         struct file *fp;
  876         char *start = where;
  877 
  878         buflen = *sizep;
  879         if (where == NULL) {
  880                 /*
  881                  * overestimate by 10 files
  882                  */
  883                 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
  884                 return (0);
  885         }
  886 
  887         /*
  888          * first copyout filehead
  889          */
  890         if (buflen < sizeof(filehead)) {
  891                 *sizep = 0;
  892                 return (0);
  893         }
  894         if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
  895                 return (error);
  896         buflen -= sizeof(filehead);
  897         where += sizeof(filehead);
  898 
  899         /*
  900          * followed by an array of file structures
  901          */
  902         for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
  903                 if (buflen < sizeof(struct file)) {
  904                         *sizep = where - start;
  905                         return (ENOMEM);
  906                 }
  907                 if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
  908                         return (error);
  909                 buflen -= sizeof(struct file);
  910                 where += sizeof(struct file);
  911         }
  912         *sizep = where - start;
  913         return (0);
  914 }
  915 
  916 /*
  917  * try over estimating by 5 procs
  918  */
  919 #define KERN_PROCSLOP   (5 * sizeof (struct kinfo_proc))
  920 
  921 int
  922 sysctl_doproc(name, namelen, where, sizep)
  923         int *name;
  924         u_int namelen;
  925         char *where;
  926         size_t *sizep;
  927 {
  928         register struct proc *p;
  929         register struct kinfo_proc *dp = (struct kinfo_proc *)where;
  930         register int needed = 0;
  931         int buflen = where != NULL ? *sizep : 0;
  932         int doingzomb;
  933         struct kinfo_proc kproc;
  934         int error = 0;
  935 
  936         if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
  937                 return (EINVAL);
  938         p = allproc.lh_first;
  939         doingzomb = 0;
  940 again:
  941         for (; p != 0; p = p->p_list.le_next) {
  942                 /*
  943                  * Skip embryonic processes.
  944                  */
  945                 if (p->p_stat == SIDL)
  946                         continue;
  947                 /*
  948                  * TODO - make more efficient (see notes below).
  949                  * do by session.
  950                  */
  951                 switch (name[0]) {
  952 
  953                 case KERN_PROC_PID:
  954                         /* could do this with just a lookup */
  955                         if (p->p_pid != (pid_t)name[1])
  956                                 continue;
  957                         break;
  958 
  959                 case KERN_PROC_PGRP:
  960                         /* could do this by traversing pgrp */
  961                         if (p->p_pgrp->pg_id != (pid_t)name[1])
  962                                 continue;
  963                         break;
  964 
  965                 case KERN_PROC_TTY:
  966                         if ((p->p_flag & P_CONTROLT) == 0 ||
  967                                 (p->p_session == NULL) ||
  968                             p->p_session->s_ttyp == NULL ||
  969                             p->p_session->s_ttyp->t_dev != (dev_t)name[1])
  970                                 continue;
  971                         break;
  972 
  973                 case KERN_PROC_UID:
  974                         if ((p->p_ucred == NULL) ||
  975                                 (p->p_ucred->cr_uid != (uid_t)name[1]))
  976                                 continue;
  977                         break;
  978 
  979                 case KERN_PROC_RUID:
  980                         if ((p->p_ucred == NULL) ||
  981                                 (p->p_cred->p_ruid != (uid_t)name[1]))
  982                                 continue;
  983                         break;
  984                 }
  985                 if (buflen >= sizeof(struct kinfo_proc)) {
  986                         bzero(&kproc, sizeof(struct kinfo_proc));
  987                         fill_proc(p, &kproc);
  988                         if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
  989                             sizeof(struct kinfo_proc)))
  990                                 return (error);
  991                         dp++;
  992                         buflen -= sizeof(struct kinfo_proc);
  993                 }
  994                 needed += sizeof(struct kinfo_proc);
  995         }
  996         if (doingzomb == 0) {
  997                 p = zombproc.lh_first;
  998                 doingzomb++;
  999                 goto again;
 1000         }
 1001         if (where != NULL) {
 1002                 *sizep = (caddr_t)dp - where;
 1003                 if (needed > *sizep)
 1004                         return (ENOMEM);
 1005         } else {
 1006                 needed += KERN_PROCSLOP;
 1007                 *sizep = needed;
 1008         }
 1009         return (0);
 1010 }
 1011 
 1012 /*
 1013  * Fill in an eproc structure for the specified process.
 1014  */
 1015 static void
 1016 fill_eproc(p, ep)
 1017         register struct proc *p;
 1018         register struct eproc *ep;
 1019 {
 1020         register struct tty *tp;
 1021 
 1022         ep->e_paddr = p;
 1023         if (p->p_pgrp) {
 1024                 ep->e_sess = p->p_pgrp->pg_session;
 1025                 ep->e_pgid = p->p_pgrp->pg_id;
 1026                 ep->e_jobc = p->p_pgrp->pg_jobc;
 1027                 if (ep->e_sess && ep->e_sess->s_ttyvp)
 1028                         ep->e_flag = EPROC_CTTY;
 1029         } else {
 1030                 ep->e_sess = (struct session *)0;
 1031                 ep->e_pgid = 0;
 1032                 ep->e_jobc = 0;
 1033         }
 1034         ep->e_ppid = (p->p_pptr) ? p->p_pptr->p_pid : 0;
 1035         if (p->p_cred) {
 1036                 ep->e_pcred = *p->p_cred;
 1037                 if (p->p_ucred)
 1038                         ep->e_ucred = *p->p_ucred;
 1039         }
 1040         if (p->p_stat == SIDL || p->p_stat == SZOMB) {
 1041                 ep->e_vm.vm_tsize = 0;
 1042                 ep->e_vm.vm_dsize = 0;
 1043                 ep->e_vm.vm_ssize = 0;
 1044         }
 1045         ep->e_vm.vm_rssize = 0;
 1046 
 1047         if ((p->p_flag & P_CONTROLT) && (ep->e_sess) &&
 1048              (tp = ep->e_sess->s_ttyp)) {
 1049                 ep->e_tdev = tp->t_dev;
 1050                 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
 1051                 ep->e_tsess = tp->t_session;
 1052         } else
 1053                 ep->e_tdev = NODEV;
 1054 
 1055         if (SESS_LEADER(p))
 1056                 ep->e_flag |= EPROC_SLEADER;
 1057         if (p->p_wmesg)
 1058                 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
 1059         ep->e_xsize = ep->e_xrssize = 0;
 1060         ep->e_xccount = ep->e_xswrss = 0;
 1061 }
 1062 
 1063 /*
 1064  * Fill in an eproc structure for the specified process.
 1065  */
 1066 static void
 1067 fill_externproc(p, exp)
 1068         register struct proc *p;
 1069         register struct extern_proc *exp;
 1070 {
 1071         exp->p_forw = exp->p_back = NULL;
 1072         if (p->p_stats)
 1073                 exp->p_starttime = p->p_stats->p_start;
 1074         exp->p_vmspace = NULL;
 1075         exp->p_sigacts = p->p_sigacts;
 1076         exp->p_flag  = p->p_flag;
 1077         exp->p_stat  = p->p_stat ;
 1078         exp->p_pid  = p->p_pid ;
 1079         exp->p_oppid  = p->p_oppid ;
 1080         exp->p_dupfd  = p->p_dupfd ;
 1081         /* Mach related  */
 1082         exp->user_stack  = p->user_stack ;
 1083         exp->exit_thread  = p->exit_thread ;
 1084         exp->p_debugger  = p->p_debugger ;
 1085         exp->sigwait  = p->sigwait ;
 1086         /* scheduling */
 1087         exp->p_estcpu  = p->p_estcpu ;
 1088         exp->p_cpticks  = p->p_cpticks ;
 1089         exp->p_pctcpu  = p->p_pctcpu ;
 1090         exp->p_wchan  = p->p_wchan ;
 1091         exp->p_wmesg  = p->p_wmesg ;
 1092         exp->p_swtime  = p->p_swtime ;
 1093         exp->p_slptime  = p->p_slptime ;
 1094         bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
 1095         bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
 1096         exp->p_uticks  = p->p_uticks ;
 1097         exp->p_sticks  = p->p_sticks ;
 1098         exp->p_iticks  = p->p_iticks ;
 1099         exp->p_traceflag  = p->p_traceflag ;
 1100         exp->p_tracep  = p->p_tracep ;
 1101         exp->p_siglist  = 0 ;   /* No longer relevant */
 1102         exp->p_textvp  = p->p_textvp ;
 1103         exp->p_holdcnt = 0 ;
 1104         exp->p_sigmask  = 0 ;   /* no longer avaialable */
 1105         exp->p_sigignore  = p->p_sigignore ;
 1106         exp->p_sigcatch  = p->p_sigcatch ;
 1107         exp->p_priority  = p->p_priority ;
 1108         exp->p_usrpri  = p->p_usrpri ;
 1109         exp->p_nice  = p->p_nice ;
 1110         bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
 1111         exp->p_comm[MAXCOMLEN] = '\0';
 1112         exp->p_pgrp  = p->p_pgrp ;
 1113         exp->p_addr  = NULL;
 1114         exp->p_xstat  = p->p_xstat ;
 1115         exp->p_acflag  = p->p_acflag ;
 1116         exp->p_ru  = p->p_ru ;
 1117 }
 1118 
 1119 static void
 1120 fill_proc(p, kp)
 1121         register struct proc *p;
 1122         register struct kinfo_proc *kp;
 1123 {
 1124         fill_externproc(p, &kp->kp_proc);
 1125         fill_eproc(p, &kp->kp_eproc);
 1126 }
 1127 
 1128 int
 1129 kdebug_ops(name, namelen, where, sizep, p)
 1130 int *name;
 1131 u_int namelen;
 1132 char *where;
 1133 size_t *sizep;
 1134 struct proc *p;
 1135 {
 1136         int size=*sizep;
 1137         int ret=0;
 1138         extern int kdbg_control(int *name, u_int namelen,
 1139                 char * where,size_t * sizep);
 1140 
 1141         if (ret = suser(p->p_ucred, &p->p_acflag))
 1142                 return(ret);
 1143 
 1144         switch(name[0]) {
 1145         case KERN_KDEFLAGS:
 1146         case KERN_KDDFLAGS:
 1147         case KERN_KDENABLE:
 1148         case KERN_KDGETBUF:
 1149         case KERN_KDSETUP:
 1150         case KERN_KDREMOVE:
 1151         case KERN_KDSETREG:
 1152         case KERN_KDGETREG:
 1153         case KERN_KDREADTR:
 1154         case KERN_KDPIDTR:
 1155         case KERN_KDTHRMAP:
 1156         case KERN_KDPIDEX:
 1157         case KERN_KDSETRTCDEC:
 1158         case KERN_KDSETBUF:
 1159         case KERN_KDGETENTROPY:
 1160                 ret = kdbg_control(name, namelen, where, sizep);
 1161                 break;
 1162         default:
 1163                 ret= EOPNOTSUPP;
 1164                 break;
 1165         }
 1166         return(ret);
 1167 }
 1168 
 1169 int
 1170 pcsamples_ops(name, namelen, where, sizep, p)
 1171 int *name;
 1172 u_int namelen;
 1173 char *where;
 1174 size_t *sizep;
 1175 struct proc *p;
 1176 {
 1177         int ret=0;
 1178         extern int pcsamples_control(int *name, u_int namelen,
 1179                 char * where,size_t * sizep);
 1180 
 1181         if (ret = suser(p->p_ucred, &p->p_acflag))
 1182                 return(ret);
 1183 
 1184         switch(name[0]) {
 1185         case KERN_PCDISABLE:
 1186         case KERN_PCGETBUF:
 1187         case KERN_PCSETUP:
 1188         case KERN_PCREMOVE:
 1189         case KERN_PCREADBUF:
 1190         case KERN_PCSETREG:
 1191         case KERN_PCSETBUF:
 1192         case KERN_PCCOMM:
 1193                 ret = pcsamples_control(name, namelen, where, sizep);
 1194                 break;
 1195         default:
 1196                 ret= EOPNOTSUPP;
 1197                 break;
 1198         }
 1199         return(ret);
 1200 }
 1201 
 1202 /*
 1203  * Return the top *sizep bytes of the user stack, or the entire area of the
 1204  * user stack down through the saved exec_path, whichever is smaller.
 1205  */
 1206 int
 1207 sysctl_procargs(name, namelen, where, sizep, cur_proc)
 1208         int *name;
 1209         u_int namelen;
 1210         char *where;
 1211         size_t *sizep;
 1212         struct proc *cur_proc;
 1213 {
 1214         return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 0);
 1215 }
 1216 
 1217 static int
 1218 sysctl_procargs2(name, namelen, where, sizep, cur_proc)
 1219         int *name;
 1220         u_int namelen;
 1221         char *where;
 1222         size_t *sizep;
 1223         struct proc *cur_proc;
 1224 {
 1225         return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 1);
 1226 }
 1227 
 1228 static int
 1229 sysctl_procargsx(name, namelen, where, sizep, cur_proc, argc_yes)
 1230         int *name;
 1231         u_int namelen;
 1232         char *where;
 1233         size_t *sizep;
 1234         struct proc *cur_proc;
 1235         int argc_yes;
 1236 {
 1237         register struct proc *p;
 1238         register int needed = 0;
 1239         int buflen = where != NULL ? *sizep : 0;
 1240         int error = 0;
 1241         struct vm_map *proc_map;
 1242         struct task * task;
 1243         vm_map_copy_t   tmp;
 1244         vm_offset_t     arg_addr;
 1245         vm_size_t       arg_size;
 1246         caddr_t data;
 1247         unsigned size;
 1248         vm_offset_t     copy_start, copy_end;
 1249         int             *ip;
 1250         kern_return_t ret;
 1251         int pid;
 1252 
 1253         if (argc_yes)
 1254                 buflen -= NBPW;         /* reserve first word to return argc */
 1255 
 1256         if ((buflen <= 0) || (buflen > ARG_MAX)) {
 1257                 return(EINVAL);
 1258         }
 1259         arg_size = buflen;
 1260 
 1261         /*
 1262          *      Lookup process by pid
 1263          */
 1264         pid = name[0];
 1265 
 1266  restart:
 1267         p = pfind(pid);
 1268         if (p == NULL) {
 1269                 return(EINVAL);
 1270         }
 1271 
 1272         /*
 1273          *      Copy the top N bytes of the stack.
 1274          *      On all machines we have so far, the stack grows
 1275          *      downwards.
 1276          *
 1277          *      If the user expects no more than N bytes of
 1278          *      argument list, use that as a guess for the
 1279          *      size.
 1280          */
 1281 
 1282         if (!p->user_stack)
 1283                 return(EINVAL);
 1284 
 1285         if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid) 
 1286                 && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
 1287                 return (EINVAL);
 1288         arg_addr = (vm_offset_t)(p->user_stack - arg_size);
 1289 
 1290 
 1291         /*
 1292          *      Before we can block (any VM code), make another
 1293          *      reference to the map to keep it alive.  We do
 1294          *      that by getting a reference on the task itself.
 1295          */
 1296         task = p->task;
 1297         if (task == NULL)
 1298                 return(EINVAL);
 1299         
 1300         /*
 1301          * A regular task_reference call can block, causing the funnel
 1302          * to be dropped and allowing the proc/task to get freed.
 1303          * Instead, we issue a non-blocking attempt at the task reference,
 1304          * and look up the proc/task all over again if that fails.
 1305          */
 1306         if (!task_reference_try(task)) {
 1307                 mutex_pause();
 1308                 goto restart;
 1309         }
 1310 
 1311         ret = kmem_alloc(kernel_map, &copy_start, round_page_32(arg_size));
 1312         if (ret != KERN_SUCCESS) {
 1313                 task_deallocate(task);
 1314                 return(ENOMEM);
 1315         }
 1316 
 1317         proc_map = get_task_map(task);
 1318         copy_end = round_page_32(copy_start + arg_size);
 1319 
 1320         if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page_32(arg_size), 
 1321                         FALSE, &tmp) != KERN_SUCCESS) {
 1322                         task_deallocate(task);
 1323                         kmem_free(kernel_map, copy_start,
 1324                                         round_page_32(arg_size));
 1325                         return (EIO);
 1326         }
 1327 
 1328         /*
 1329          *      Now that we've done the copyin from the process'
 1330          *      map, we can release the reference to it.
 1331          */
 1332         task_deallocate(task);
 1333 
 1334         if( vm_map_copy_overwrite(kernel_map, copy_start, 
 1335                 tmp, FALSE) != KERN_SUCCESS) {
 1336                         kmem_free(kernel_map, copy_start,
 1337                                         round_page_32(arg_size));
 1338                         return (EIO);
 1339         }
 1340 
 1341         data = (caddr_t) (copy_end - arg_size);
 1342 
 1343         if (buflen > p->p_argslen) {
 1344                 data = &data[buflen - p->p_argslen];
 1345                 size = p->p_argslen;
 1346         } else {
 1347                 size = buflen;
 1348         }
 1349 
 1350         if (argc_yes) {
 1351                 /* Put processes argc as the first word in the copyout buffer */
 1352                 suword(where, p->p_argc);
 1353                 error = copyout(data, where + NBPW, size);
 1354         } else {
 1355                 error = copyout(data, where, size);
 1356 
 1357                 /*
 1358                  * Make the old PROCARGS work to return the executable's path
 1359                  * But, only if there is enough space in the provided buffer
 1360                  *
 1361                  * on entry: data [possibily] points to the beginning of the path 
 1362                  * 
 1363                  * Note: we keep all pointers&sizes aligned to word boundries
 1364                  */
 1365 
 1366                 if ( (! error) && (buflen > p->p_argslen) )
 1367                 {
 1368                         int binPath_sz;
 1369                         int extraSpaceNeeded, addThis;
 1370                         char * placeHere;
 1371                         char * str = (char *) data;
 1372                         unsigned int max_len = size;
 1373 
 1374                         /* Some apps are really bad about messing up their stacks
 1375                            So, we have to be extra careful about getting the length
 1376                            of the executing binary.  If we encounter an error, we bail.
 1377                         */
 1378 
 1379                         /* Limit ourselves to PATH_MAX paths */
 1380                         if ( max_len > PATH_MAX ) max_len = PATH_MAX;
 1381 
 1382                         binPath_sz = 0;
 1383 
 1384                         while ( (binPath_sz < max_len-1) && (*str++ != 0) )
 1385                                 binPath_sz++;
 1386 
 1387                         if (binPath_sz < max_len-1) binPath_sz += 1;
 1388 
 1389                         /* Pre-Flight the space requiremnts */
 1390 
 1391                         /* Account for the padding that fills out binPath to the next word */
 1392                         binPath_sz += (binPath_sz & (NBPW-1)) ? (NBPW-(binPath_sz & (NBPW-1))) : 0;
 1393 
 1394                         placeHere = where + size;
 1395 
 1396                         /* Account for the bytes needed to keep placeHere word aligned */ 
 1397                         addThis = ((unsigned long)placeHere & (NBPW-1)) ? (NBPW-((unsigned long)placeHere & (NBPW-1))) : 0;
 1398 
 1399                         /* Add up all the space that is needed */
 1400                         extraSpaceNeeded = binPath_sz + addThis + (4 * NBPW);
 1401 
 1402                         /* is there is room to tack on argv[0]? */
 1403                         if ( (buflen & ~(NBPW-1)) >= ( p->p_argslen + extraSpaceNeeded ))
 1404                         {
 1405                                 placeHere += addThis;
 1406                                 suword(placeHere, 0);
 1407                                 placeHere += NBPW;
 1408                                 suword(placeHere, 0xBFFF0000);
 1409                                 placeHere += NBPW;
 1410                                 suword(placeHere, 0);
 1411                                 placeHere += NBPW;
 1412                                 error = copyout(data, placeHere, binPath_sz);
 1413                                 if ( ! error )
 1414                                 {
 1415                                         placeHere += binPath_sz;
 1416                                         suword(placeHere, 0);
 1417                                         size += extraSpaceNeeded;
 1418                                 }
 1419                         }
 1420                 }
 1421         }
 1422 
 1423         if (copy_start != (vm_offset_t) 0) {
 1424                 kmem_free(kernel_map, copy_start, copy_end - copy_start);
 1425         }
 1426         if (error) {
 1427                 return(error);
 1428         }
 1429 
 1430         if (where != NULL)
 1431                 *sizep = size;
 1432         return (0);
 1433 }
 1434 
 1435 
 1436 /*
 1437  * Validate parameters and get old / set new parameters
 1438  * for max number of concurrent aio requests.  Makes sure
 1439  * the system wide limit is greater than the per process
 1440  * limit.
 1441  */
 1442 static int
 1443 sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1444 {
 1445         int     error = 0;
 1446         int             new_value;
 1447 
 1448         if ( oldp && *oldlenp < sizeof(int) )
 1449                 return (ENOMEM);
 1450         if ( newp && newlen != sizeof(int) )
 1451                 return (EINVAL);
 1452                 
 1453         *oldlenp = sizeof(int);
 1454         if ( oldp )
 1455                 error = copyout( &aio_max_requests, oldp, sizeof(int) );
 1456         if ( error == 0 && newp )
 1457                 error = copyin( newp, &new_value, sizeof(int) );
 1458         if ( error == 0 && newp ) {
 1459                 if ( new_value >= aio_max_requests_per_process )
 1460                         aio_max_requests = new_value;
 1461                 else
 1462                         error = EINVAL;
 1463         }
 1464         return( error );
 1465         
 1466 } /* sysctl_aiomax */
 1467 
 1468 
 1469 /*
 1470  * Validate parameters and get old / set new parameters
 1471  * for max number of concurrent aio requests per process.  
 1472  * Makes sure per process limit is less than the system wide
 1473  * limit.
 1474  */
 1475 static int
 1476 sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1477 {
 1478         int     error = 0;
 1479         int             new_value = 0;
 1480 
 1481         if ( oldp && *oldlenp < sizeof(int) )
 1482                 return (ENOMEM);
 1483         if ( newp && newlen != sizeof(int) )
 1484                 return (EINVAL);
 1485                 
 1486         *oldlenp = sizeof(int);
 1487         if ( oldp )
 1488                 error = copyout( &aio_max_requests_per_process, oldp, sizeof(int) );
 1489         if ( error == 0 && newp )
 1490                 error = copyin( newp, &new_value, sizeof(int) );
 1491         if ( error == 0 && newp ) {
 1492                 if ( new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX )
 1493                         aio_max_requests_per_process = new_value;
 1494                 else
 1495                         error = EINVAL;
 1496         }
 1497         return( error );
 1498         
 1499 } /* sysctl_aioprocmax */
 1500 
 1501 
 1502 /*
 1503  * Validate parameters and get old / set new parameters
 1504  * for max number of async IO worker threads.  
 1505  * We only allow an increase in the number of worker threads.
 1506  */
 1507 static int
 1508 sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1509 {
 1510         int     error = 0;
 1511         int             new_value;
 1512 
 1513         if ( oldp && *oldlenp < sizeof(int) )
 1514                 return (ENOMEM);
 1515         if ( newp && newlen != sizeof(int) )
 1516                 return (EINVAL);
 1517                 
 1518         *oldlenp = sizeof(int);
 1519         if ( oldp )
 1520                 error = copyout( &aio_worker_threads, oldp, sizeof(int) );
 1521         if ( error == 0 && newp )
 1522                 error = copyin( newp, &new_value, sizeof(int) );
 1523         if ( error == 0 && newp ) {
 1524                 if (new_value > aio_worker_threads ) {
 1525                         _aio_create_worker_threads( (new_value - aio_worker_threads) );
 1526                         aio_worker_threads = new_value;
 1527                 }
 1528                 else
 1529                         error = EINVAL;
 1530         }
 1531         return( error );
 1532         
 1533 } /* sysctl_aiothreads */
 1534 
 1535 
 1536 /*
 1537  * Validate parameters and get old / set new parameters
 1538  * for max number of processes per UID.
 1539  * Makes sure per UID limit is less than the system wide limit.
 1540  */
 1541 static int
 1542 sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1543 {
 1544         int     error = 0;
 1545         int             new_value;
 1546 
 1547         if ( oldp != NULL && *oldlenp < sizeof(int) )
 1548                 return (ENOMEM);
 1549         if ( newp != NULL && newlen != sizeof(int) )
 1550                 return (EINVAL);
 1551                 
 1552         *oldlenp = sizeof(int);
 1553         if ( oldp != NULL )
 1554                 error = copyout( &maxprocperuid, oldp, sizeof(int) );
 1555         if ( error == 0 && newp != NULL ) {
 1556                 error = copyin( newp, &new_value, sizeof(int) );
 1557                 if ( error == 0 && new_value <= maxproc && new_value > 0 )
 1558                         maxprocperuid = new_value;
 1559                 else
 1560                         error = EINVAL;
 1561         }
 1562         return( error );
 1563         
 1564 } /* sysctl_maxprocperuid */
 1565 
 1566 
 1567 /*
 1568  * Validate parameters and get old / set new parameters
 1569  * for max number of files per process.
 1570  * Makes sure per process limit is less than the system-wide limit.
 1571  */
 1572 static int
 1573 sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1574 {
 1575         int     error = 0;
 1576         int             new_value;
 1577 
 1578         if ( oldp != NULL && *oldlenp < sizeof(int) )
 1579                 return (ENOMEM);
 1580         if ( newp != NULL && newlen != sizeof(int) )
 1581                 return (EINVAL);
 1582                 
 1583         *oldlenp = sizeof(int);
 1584         if ( oldp != NULL )
 1585                 error = copyout( &maxfilesperproc, oldp, sizeof(int) );
 1586         if ( error == 0 && newp != NULL ) {
 1587                 error = copyin( newp, &new_value, sizeof(int) );
 1588                 if ( error == 0 && new_value < maxfiles && new_value > 0 )
 1589                         maxfilesperproc = new_value;
 1590                 else
 1591                         error = EINVAL;
 1592         }
 1593         return( error );
 1594         
 1595 } /* sysctl_maxfilesperproc */
 1596 
 1597 
 1598 /*
 1599  * Validate parameters and get old / set new parameters
 1600  * for the system-wide limit on the max number of processes.
 1601  * Makes sure the system-wide limit is less than the configured hard
 1602  * limit set at kernel compilation.
 1603  */
 1604 static int
 1605 sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
 1606 {
 1607         int     error = 0;
 1608         int     new_value;
 1609 
 1610         if ( oldp != NULL && *oldlenp < sizeof(int) )
 1611                 return (ENOMEM);
 1612         if ( newp != NULL && newlen != sizeof(int) )
 1613                 return (EINVAL);
 1614                 
 1615         *oldlenp = sizeof(int);
 1616         if ( oldp != NULL )
 1617                 error = copyout( &maxproc, oldp, sizeof(int) );
 1618         if ( error == 0 && newp != NULL ) {
 1619                 error = copyin( newp, &new_value, sizeof(int) );
 1620                 if ( error == 0 && new_value <= hard_maxproc && new_value > 0 )
 1621                         maxproc = new_value;
 1622                 else
 1623                         error = EINVAL;
 1624         }
 1625         return( error );
 1626         
 1627 } /* sysctl_maxproc */

Cache object: 7a223a9385bf9d0f6b62f197d2248ec8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.