]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sysctl.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
index c7332ad0517ae7dcb575a3ded7141b79887ded45..afff9561865a85abcf0edf26dae2a124c309a25b 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <sys/unistd.h>
 #include <sys/buf.h>
 #include <sys/ioctl.h>
 #include <sys/unistd.h>
 #include <sys/buf.h>
 #include <sys/ioctl.h>
+#include <sys/namei.h>
 #include <sys/tty.h>
 #include <sys/disklabel.h>
 #include <sys/vm.h>
 #include <sys/sysctl.h>
 #include <sys/tty.h>
 #include <sys/disklabel.h>
 #include <sys/vm.h>
 #include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/aio_kern.h>
+
+#include <bsm/audit_kernel.h>
+
 #include <mach/machine.h>
 #include <mach/mach_types.h>
 #include <mach/vm_param.h>
 #include <mach/machine.h>
 #include <mach/mach_types.h>
 #include <mach/vm_param.h>
@@ -91,12 +97,9 @@ extern vm_map_t bsd_pageable_map;
 #include <IOKit/IOPlatformExpert.h>
 #include <pexpert/pexpert.h>
 
 #include <IOKit/IOPlatformExpert.h>
 #include <pexpert/pexpert.h>
 
-#if __ppc__
-#include <osfmk/ppc/machine_routines.h>
-#endif
+#include <machine/machine_routines.h>
 
 sysctlfn kern_sysctl;
 
 sysctlfn kern_sysctl;
-sysctlfn hw_sysctl;
 #ifdef DEBUG
 sysctlfn debug_sysctl;
 #endif
 #ifdef DEBUG
 sysctlfn debug_sysctl;
 #endif
@@ -104,23 +107,41 @@ extern sysctlfn vm_sysctl;
 extern sysctlfn vfs_sysctl;
 extern sysctlfn net_sysctl;
 extern sysctlfn cpu_sysctl;
 extern sysctlfn vfs_sysctl;
 extern sysctlfn net_sysctl;
 extern sysctlfn cpu_sysctl;
+extern int aio_max_requests;                           
+extern int aio_max_requests_per_process;       
+extern int aio_worker_threads;                         
+extern int maxprocperuid;
+extern int maxfilesperproc;
 
 
 int
 userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t 
                *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
 
 
 
 int
 userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t 
                *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
 
-void
-fill_proc(struct proc *p,struct kinfo_proc *kp, int doingzomb);
-
-void
-fill_externproc(struct proc *p, struct extern_proc *exp);
-
+static int
+sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static int
+sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static int
+sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static void
+fill_proc(struct proc *p, struct kinfo_proc *kp);
+static int
+sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static int
+sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static int
+sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
+static int
+sysctl_procargs2( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc);
+static int
+sysctl_procargsx( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc, int argc_yes);
 
 
 /*
  * temporary location for vm_sysctl.  This should be machine independant
  */
 
 
 /*
  * temporary location for vm_sysctl.  This should be machine independant
  */
+int
 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        int *name;
        u_int namelen;
 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        int *name;
        u_int namelen;
@@ -130,26 +151,20 @@ vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        size_t newlen;
        struct proc *p;
 {
        size_t newlen;
        struct proc *p;
 {
-       int error, level, inthostid;
-       extern long avenrun[3], mach_factor[3];
+       extern uint32_t mach_factor[3];
        struct loadavg loadinfo;
 
        struct loadavg loadinfo;
 
-       //if (namelen != 1 && !(name[0] == VM_LOADAVG))
-               //return (ENOTDIR);             /* overloaded */
-
        switch (name[0]) {
        case VM_LOADAVG:
        switch (name[0]) {
        case VM_LOADAVG:
-               loadinfo.ldavg[0] = avenrun[0];
-               loadinfo.ldavg[1] = avenrun[1];
-               loadinfo.ldavg[2] = avenrun[2];
-               loadinfo.fscale = LSCALE;
-               return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
+               return (sysctl_struct(oldp, oldlenp, newp, newlen,
+                                       &averunnable, sizeof(struct loadavg)));
        case VM_MACHFACTOR:
                loadinfo.ldavg[0] = mach_factor[0];
                loadinfo.ldavg[1] = mach_factor[1];
                loadinfo.ldavg[2] = mach_factor[2];
                loadinfo.fscale = LSCALE;
        case VM_MACHFACTOR:
                loadinfo.ldavg[0] = mach_factor[0];
                loadinfo.ldavg[1] = mach_factor[1];
                loadinfo.ldavg[2] = mach_factor[2];
                loadinfo.fscale = LSCALE;
-               return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
+               return (sysctl_struct(oldp, oldlenp, newp, newlen,
+                                       &loadinfo, sizeof(struct loadavg)));
        case VM_METER:
                return (EOPNOTSUPP);
        case VM_MAXID:
        case VM_METER:
                return (EOPNOTSUPP);
        case VM_MAXID:
@@ -189,6 +204,7 @@ __sysctl(p, uap, retval)
        sysctlfn *fn;
        int name[CTL_MAXNAME];
        int i;
        sysctlfn *fn;
        int name[CTL_MAXNAME];
        int i;
+       int error1;
 
        /*
         * all top-level sysctl names are non-terminal
 
        /*
         * all top-level sysctl names are non-terminal
@@ -199,23 +215,25 @@ __sysctl(p, uap, retval)
            copyin(uap->name, &name, uap->namelen * sizeof(int)))
                return (error);
 
            copyin(uap->name, &name, uap->namelen * sizeof(int)))
                return (error);
 
+       AUDIT_ARG(ctlname, name, uap->namelen);
+
        /* CTL_UNSPEC is used to get oid to AUTO_OID */
        /* CTL_UNSPEC is used to get oid to AUTO_OID */
-       if (uap->new != NULL && 
-               (((name[0] == CTL_KERN) && (name[1] != KERN_IPC)) || 
-                (name[0] == CTL_HW) || (name[0] == CTL_VM) ||
-                (name[0] == CTL_VFS)) &&
-           (error = suser(p->p_ucred, &p->p_acflag)))
+       if (uap->new != NULL
+               && ((name[0] == CTL_KERN
+                               && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO))
+                       || (name[0] == CTL_HW)
+                       || (name[0] == CTL_VM)
+                       || (name[0] == CTL_VFS))
+               && (error = suser(p->p_ucred, &p->p_acflag)))
                return (error);
 
        switch (name[0]) {
        case CTL_KERN:
                fn = kern_sysctl;
                return (error);
 
        switch (name[0]) {
        case CTL_KERN:
                fn = kern_sysctl;
-               if (name[1] != KERN_VNODE)      /* XXX */
+               if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE) 
+                       && (name[1] != KERN_PROC))
                        dolock = 0;
                break;
                        dolock = 0;
                break;
-       case CTL_HW:
-               fn = hw_sysctl;
-               break;
        case CTL_VM:
                fn = vm_sysctl;
                break;
        case CTL_VM:
                fn = vm_sysctl;
                break;
@@ -223,11 +241,6 @@ __sysctl(p, uap, retval)
        case CTL_VFS:
                fn = vfs_sysctl;
                break;
        case CTL_VFS:
                fn = vfs_sysctl;
                break;
-#if FIXME  /* [ */
-       case CTL_MACHDEP:
-               fn = cpu_sysctl;
-               break;
-#endif  /* FIXME ] */
 #ifdef DEBUG
        case CTL_DEBUG:
                fn = debug_sysctl;
 #ifdef DEBUG
        case CTL_DEBUG:
                fn = debug_sysctl;
@@ -246,7 +259,8 @@ __sysctl(p, uap, retval)
                        return (EFAULT);
 
                /* The pc sampling mechanism does not need to take this lock */
                        return (EFAULT);
 
                /* The pc sampling mechanism does not need to take this lock */
-               if (name[1] != KERN_PCSAMPLES) {
+               if ((name[1] != KERN_PCSAMPLES) &&
+                   (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
                  while (memlock.sl_lock) {
                        memlock.sl_want = 1;
                        sleep((caddr_t)&memlock, PRIBIO+1);
                  while (memlock.sl_lock) {
                        memlock.sl_want = 1;
                        sleep((caddr_t)&memlock, PRIBIO+1);
@@ -255,8 +269,17 @@ __sysctl(p, uap, retval)
                  memlock.sl_lock = 1;
                }
 
                  memlock.sl_lock = 1;
                }
 
-               if (dolock)
-                       vslock(uap->old, oldlen);
+               if (dolock && oldlen && (error = vslock(uap->old, oldlen))) {
+                       if ((name[1] != KERN_PCSAMPLES) &&
+                          (! ((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
+                               memlock.sl_lock = 0;
+                               if (memlock.sl_want) {
+                               memlock.sl_want = 0;
+                                       wakeup((caddr_t)&memlock);
+                               }
+                       }
+                       return(error);
+               }
                savelen = oldlen;
        }
 
                savelen = oldlen;
        }
 
@@ -272,8 +295,11 @@ __sysctl(p, uap, retval)
                                        uap->new, uap->newlen, &oldlen);
 
        if (uap->old != NULL) {
                                        uap->new, uap->newlen, &oldlen);
 
        if (uap->old != NULL) {
-               if (dolock)
-                       vsunlock(uap->old, savelen, B_WRITE);
+               if (dolock && savelen) {
+                       error1 = vsunlock(uap->old, savelen, B_WRITE);
+                       if (!error &&  error1)
+                               error = error1;
+               }
                if (name[1] != KERN_PCSAMPLES) {
                  memlock.sl_lock = 0;
                  if (memlock.sl_want) {
                if (name[1] != KERN_PCSAMPLES) {
                  memlock.sl_lock = 0;
                  if (memlock.sl_want) {
@@ -301,6 +327,14 @@ extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
 extern int hostnamelen;
 extern char domainname[MAXHOSTNAMELEN];
 extern int domainnamelen;
 extern int hostnamelen;
 extern char domainname[MAXHOSTNAMELEN];
 extern int domainnamelen;
+extern char classichandler[32];
+extern long classichandler_fsid;
+extern long classichandler_fileid;
+__private_extern__ char corefilename[MAXPATHLEN+1];
+__private_extern__ do_coredump;
+__private_extern__ sugid_coredump;
+
+
 extern long hostid;
 #ifdef INSECURE
 int securelevel = -1;
 extern long hostid;
 #ifdef INSECURE
 int securelevel = -1;
@@ -308,11 +342,132 @@ int securelevel = -1;
 int securelevel;
 #endif
 
 int securelevel;
 #endif
 
-int get_kernel_symfile( struct proc *p, char **symfile );
+static int
+sysctl_affinity(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
+       int *name;
+       u_int namelen;
+       char *oldBuf;
+       size_t *oldSize;
+       char *newBuf;
+       size_t newSize;
+       struct proc *cur_proc;
+{
+       if (namelen < 1)
+               return (EOPNOTSUPP);
+
+       if (name[0] == 0 && 1 == namelen) {
+               return sysctl_rdint(oldBuf, oldSize, newBuf,
+                       (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
+       } else if (name[0] == 1 && 2 == namelen) {
+               if (name[1] == 0) {
+                       cur_proc->p_flag &= ~P_AFFINITY;
+               } else {
+                       cur_proc->p_flag |= P_AFFINITY;
+               }
+               return 0;
+       }
+       return (EOPNOTSUPP);
+}
+
+static int
+sysctl_classic(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
+       int *name;
+       u_int namelen;
+       char *oldBuf;
+       size_t *oldSize;
+       char *newBuf;
+       size_t newSize;
+       struct proc *cur_proc;
+{
+       int newVal;
+       int err;
+       struct proc *p;
+
+       if (namelen != 1)
+               return (EOPNOTSUPP);
+
+       p = pfind(name[0]);
+       if (p == NULL)
+               return (EINVAL);
+
+       if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid) 
+               && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
+               return (EPERM);
+
+       return sysctl_rdint(oldBuf, oldSize, newBuf,
+               (p->p_flag & P_CLASSIC) ? 1 : 0);
+}
+
+static int
+sysctl_classichandler(name, namelen, oldBuf, oldSize, newBuf, newSize, p)
+       int *name;
+       u_int namelen;
+       char *oldBuf;
+       size_t *oldSize;
+       char *newBuf;
+       size_t newSize;
+       struct proc *p;
+{
+       int error;
+       int len;
+       struct nameidata nd;
+       struct vattr vattr;
+       char handler[sizeof(classichandler)];
+
+       if ((error = suser(p->p_ucred, &p->p_acflag)))
+               return (error);
+       len = strlen(classichandler) + 1;
+       if (oldBuf && *oldSize < len)
+               return (ENOMEM);
+       if (newBuf && newSize >= sizeof(classichandler))
+               return (ENAMETOOLONG);
+       *oldSize = len - 1;
+       if (newBuf) {
+               error = copyin(newBuf, handler, newSize);
+               if (error)
+                       return (error);
+               handler[newSize] = 0;
+
+               NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
+                               handler, p);
+               error = namei(&nd);
+               if (error)
+                       return (error);
+               /* Check mount point */
+               if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||
+                       (nd.ni_vp->v_type != VREG)) {
+                       vput(nd.ni_vp);
+                       return (EACCES);
+               }
+               error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
+               if (error) {
+                       vput(nd.ni_vp);
+                       return (error);
+               }
+               classichandler_fsid = vattr.va_fsid;
+               classichandler_fileid = vattr.va_fileid;
+               vput(nd.ni_vp);
+       }
+       if (oldBuf) {
+               error = copyout(classichandler, oldBuf, len);
+               if (error)
+                       return (error);
+       }
+       if (newBuf) {
+               strcpy(classichandler, handler);
+       }
+       return (error);
+}
+
+
+extern int get_kernel_symfile( struct proc *, char **);
+extern int sysctl_dopanicinfo(int *, u_int, void *, size_t *,
+                       void *, size_t, struct proc *);
 
 /*
  * kernel related system variables.
  */
 
 /*
  * kernel related system variables.
  */
+int
 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        int *name;
        u_int namelen;
 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        int *name;
        u_int namelen;
@@ -322,17 +477,26 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        size_t newlen;
        struct proc *p;
 {
        size_t newlen;
        struct proc *p;
 {
-       int error, level, inthostid;
+       int error, level, inthostid, tmp;
        unsigned int oldval=0;
        unsigned int oldval=0;
+       char *str;
        extern char ostype[], osrelease[], version[];
        extern char ostype[], osrelease[], version[];
-
-       /* all sysctl names at this level are terminal */
-       if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 
-               || name[0] == KERN_KDEBUG
-               || name[0] == KERN_PROCARGS
-                || name[0] == KERN_PCSAMPLES
-                || name[0] == KERN_IPC
-       ))
+       extern int netboot_root();
+
+       /* all sysctl names not listed below are terminal at this level */
+       if (namelen != 1
+               && !(name[0] == KERN_PROC
+                       || name[0] == KERN_PROF 
+                       || name[0] == KERN_KDEBUG
+                       || name[0] == KERN_PROCARGS
+                       || name[0] == KERN_PROCARGS2
+                       || name[0] == KERN_PCSAMPLES
+                       || name[0] == KERN_IPC
+                       || name[0] == KERN_SYSV
+                       || name[0] == KERN_AFFINITY
+                       || name[0] == KERN_CLASSIC
+                       || name[0] == KERN_PANICINFO)
+               )
                return (ENOTDIR);               /* overloaded */
 
        switch (name[0]) {
                return (ENOTDIR);               /* overloaded */
 
        switch (name[0]) {
@@ -349,11 +513,16 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                error = sysctl_int(oldp, oldlenp, newp, 
                                newlen, &desiredvnodes);
                reset_vmobjectcache(oldval, desiredvnodes);
                error = sysctl_int(oldp, oldlenp, newp, 
                                newlen, &desiredvnodes);
                reset_vmobjectcache(oldval, desiredvnodes);
+               resize_namecache(desiredvnodes);
                return(error);
        case KERN_MAXPROC:
                return(error);
        case KERN_MAXPROC:
-               return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
+               return (sysctl_maxproc(oldp, oldlenp, newp, newlen));
        case KERN_MAXFILES:
                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
        case KERN_MAXFILES:
                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
+       case KERN_MAXPROCPERUID:
+               return( sysctl_maxprocperuid( oldp, oldlenp, newp, newlen ) );
+       case KERN_MAXFILESPERPROC:
+               return( sysctl_maxfilesperproc( oldp, oldlenp, newp, newlen ) );
        case KERN_ARGMAX:
                return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
        case KERN_SECURELVL:
        case KERN_ARGMAX:
                return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
        case KERN_SECURELVL:
@@ -410,121 +579,65 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
 #else
                return (sysctl_rdint(oldp, oldlenp, newp, 0));
 #endif
 #else
                return (sysctl_rdint(oldp, oldlenp, newp, 0));
 #endif
-#if FIXME  /* [ */
-       case KERN_MAXPARTITIONS:
-               return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
-#endif  /* FIXME ] */
        case KERN_KDEBUG:
                return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
        case KERN_PCSAMPLES:
                return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
        case KERN_PROCARGS:
                /* new one as it does not use kinfo_proc */
        case KERN_KDEBUG:
                return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
        case KERN_PCSAMPLES:
                return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
        case KERN_PROCARGS:
                /* new one as it does not use kinfo_proc */
-               return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp));
-        case KERN_SYMFILE:
-                {
-                    char *str;
-                    error = get_kernel_symfile( p, &str );
-                    if ( error ) return error;
-                    return (sysctl_rdstring(oldp, oldlenp, newp, str));
-                }    
-       default:
-               return (EOPNOTSUPP);
-       }
-       /* NOTREACHED */
-}
-
-/*
- * hardware related system variables.
- */
-hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
-       int *name;
-       u_int namelen;
-       void *oldp;
-       size_t *oldlenp;
-       void *newp;
-       size_t newlen;
-       struct proc *p;
-{
-       char dummy[65];
-       int  epochTemp;
-       extern int vm_page_wire_count;
-#if __ppc__
-       ml_ppc_cpu_info_t cpu_info;
-
-       ml_ppc_get_info(&cpu_info);
-#endif
-
-       /* all sysctl names at this level are terminal */
-       if (namelen != 1)
-               return (ENOTDIR);               /* overloaded */
-
-       switch (name[0]) {
-       case HW_MACHINE:
-               if(!PEGetMachineName(dummy,64))
-                       return(EINVAL);
-               return (sysctl_rdstring(oldp, oldlenp, newp, dummy));
-       case HW_MODEL:
-               if(!PEGetModelName(dummy,64))
-                       return(EINVAL);
-               return (sysctl_rdstring(oldp, oldlenp, newp, dummy));
-       case HW_NCPU: {
-               int numcpus=1;
-               host_basic_info_data_t hinfo;
-               kern_return_t kret;
-               int count= HOST_BASIC_INFO_COUNT;
-#define BSD_HOST 1
-
-                       kret = host_info(BSD_HOST, HOST_BASIC_INFO, &hinfo, &count);
-                       if (kret == KERN_SUCCESS) {
-                               numcpus = hinfo.avail_cpus;
-                               return (sysctl_rdint(oldp, oldlenp, newp, numcpus));
-                       } else {
-                               return(EINVAL);
-                       }
+               return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
+       case KERN_PROCARGS2:
+               /* new one as it does not use kinfo_proc */
+               return (sysctl_procargs2(name + 1, namelen - 1, oldp, oldlenp, p));
+       case KERN_SYMFILE:
+               error = get_kernel_symfile( p, &str );
+               if ( error )
+                       return error;
+               return (sysctl_rdstring(oldp, oldlenp, newp, str));
+       case KERN_NETBOOT:
+               return (sysctl_rdint(oldp, oldlenp, newp, netboot_root()));
+       case KERN_PANICINFO:
+               return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
+                       newp, newlen, p));
+       case KERN_AFFINITY:
+               return sysctl_affinity(name+1, namelen-1, oldp, oldlenp,
+                                                                       newp, newlen, p);
+       case KERN_CLASSIC:
+               return sysctl_classic(name+1, namelen-1, oldp, oldlenp,
+                                                               newp, newlen, p);
+       case KERN_CLASSICHANDLER:
+               return sysctl_classichandler(name+1, namelen-1, oldp, oldlenp,
+                                                                               newp, newlen, p);
+       case KERN_AIOMAX:
+               return( sysctl_aiomax( oldp, oldlenp, newp, newlen ) );
+       case KERN_AIOPROCMAX:
+               return( sysctl_aioprocmax( oldp, oldlenp, newp, newlen ) );
+       case KERN_AIOTHREADS:
+               return( sysctl_aiothreads( oldp, oldlenp, newp, newlen ) );
+       case KERN_COREFILE:
+               error = sysctl_string(oldp, oldlenp, newp, newlen,
+                   corefilename, sizeof(corefilename));
+               return (error);
+       case KERN_COREDUMP:
+               tmp = do_coredump;
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &do_coredump);
+               if (!error && (do_coredump < 0) || (do_coredump > 1)) {
+                       do_coredump = tmp;
+                       error = EINVAL;
                }
                }
-       case HW_BYTEORDER:
-               return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
-       case HW_PHYSMEM:
-               return (sysctl_rdint(oldp, oldlenp, newp, mem_size));
-       case HW_USERMEM:
-               return (sysctl_rdint(oldp, oldlenp, newp,
-                   (mem_size - vm_page_wire_count * page_size)));
-       case HW_PAGESIZE:
-               return (sysctl_rdint(oldp, oldlenp, newp, page_size));
-       case HW_EPOCH:
-               epochTemp = PEGetPlatformEpoch();
-               if (epochTemp == -1) return(EINVAL);
-               return (sysctl_rdint(oldp, oldlenp, newp, epochTemp));
-       case HW_BUS_FREQ:
-               return (sysctl_rdint(oldp, oldlenp, newp, gPEClockFrequencyInfo.bus_clock_rate_hz));
-       case HW_CPU_FREQ:
-               return (sysctl_rdint(oldp, oldlenp, newp, gPEClockFrequencyInfo.cpu_clock_rate_hz));
-#if __ppc__
-       case HW_VECTORUNIT:
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.vector_unit));
-       case HW_CACHELINE:
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.cache_line_size));
-       case HW_L1ICACHESIZE:
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l1_icache_size));
-       case HW_L1DCACHESIZE:
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l1_dcache_size));
-       case HW_L2SETTINGS:
-               if (cpu_info.l2_cache_size == 0xFFFFFFFF) return(EINVAL);
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l2_settings));
-       case HW_L2CACHESIZE:
-               if (cpu_info.l2_cache_size == 0xFFFFFFFF) return(EINVAL);
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l2_cache_size));
-       case HW_L3SETTINGS:
-               if (cpu_info.l3_cache_size == 0xFFFFFFFF) return(EINVAL);
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l3_settings));
-       case HW_L3CACHESIZE:
-               if (cpu_info.l3_cache_size == 0xFFFFFFFF) return(EINVAL);
-               return (sysctl_rdint(oldp, oldlenp, newp, cpu_info.l3_cache_size));
-#endif
+               return (error);
+       case KERN_SUGID_COREDUMP:
+               tmp = sugid_coredump;
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &sugid_coredump);
+               if (!error && (sugid_coredump < 0) || (sugid_coredump > 1)) {
+                       sugid_coredump = tmp;
+                       error = EINVAL;
+               }
+               return (error);
        default:
                return (EOPNOTSUPP);
        }
        default:
                return (EOPNOTSUPP);
        }
+       /* NOTREACHED */
 }
 
 #ifdef DEBUG
 }
 
 #ifdef DEBUG
@@ -579,6 +692,7 @@ debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
  * Validate parameters and get old / set new parameters
  * for an integer-valued sysctl function.
  */
  * Validate parameters and get old / set new parameters
  * for an integer-valued sysctl function.
  */
+int
 sysctl_int(oldp, oldlenp, newp, newlen, valp)
        void *oldp;
        size_t *oldlenp;
 sysctl_int(oldp, oldlenp, newp, newlen, valp)
        void *oldp;
        size_t *oldlenp;
@@ -595,14 +709,17 @@ sysctl_int(oldp, oldlenp, newp, newlen, valp)
        *oldlenp = sizeof(int);
        if (oldp)
                error = copyout(valp, oldp, sizeof(int));
        *oldlenp = sizeof(int);
        if (oldp)
                error = copyout(valp, oldp, sizeof(int));
-       if (error == 0 && newp)
+       if (error == 0 && newp) {
                error = copyin(newp, valp, sizeof(int));
                error = copyin(newp, valp, sizeof(int));
+               AUDIT_ARG(value, *valp);
+       }
        return (error);
 }
 
 /*
  * As above, but read-only.
  */
        return (error);
 }
 
 /*
  * As above, but read-only.
  */
+int
 sysctl_rdint(oldp, oldlenp, newp, val)
        void *oldp;
        size_t *oldlenp;
 sysctl_rdint(oldp, oldlenp, newp, val)
        void *oldp;
        size_t *oldlenp;
@@ -621,10 +738,59 @@ sysctl_rdint(oldp, oldlenp, newp, val)
        return (error);
 }
 
        return (error);
 }
 
+/*
+ * Validate parameters and get old / set new parameters
+ * for an quad(64bit)-valued sysctl function.
+ */
+int
+sysctl_quad(oldp, oldlenp, newp, newlen, valp)
+       void *oldp;
+       size_t *oldlenp;
+       void *newp;
+       size_t newlen;
+       quad_t *valp;
+{
+       int error = 0;
+
+       if (oldp && *oldlenp < sizeof(quad_t))
+               return (ENOMEM);
+       if (newp && newlen != sizeof(quad_t))
+               return (EINVAL);
+       *oldlenp = sizeof(quad_t);
+       if (oldp)
+               error = copyout(valp, oldp, sizeof(quad_t));
+       if (error == 0 && newp)
+               error = copyin(newp, valp, sizeof(quad_t));
+       return (error);
+}
+
+/*
+ * As above, but read-only.
+ */
+int
+sysctl_rdquad(oldp, oldlenp, newp, val)
+       void *oldp;
+       size_t *oldlenp;
+       void *newp;
+       quad_t val;
+{
+       int error = 0;
+
+       if (oldp && *oldlenp < sizeof(quad_t))
+               return (ENOMEM);
+       if (newp)
+               return (EPERM);
+       *oldlenp = sizeof(quad_t);
+       if (oldp)
+               error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
+       return (error);
+}
+
 /*
  * Validate parameters and get old / set new parameters
  * for a string-valued sysctl function.
  */
 /*
  * Validate parameters and get old / set new parameters
  * for a string-valued sysctl function.
  */
+int
 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
        void *oldp;
        size_t *oldlenp;
 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
        void *oldp;
        size_t *oldlenp;
@@ -640,13 +806,14 @@ sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
                return (ENOMEM);
        if (newp && newlen >= maxlen)
                return (EINVAL);
                return (ENOMEM);
        if (newp && newlen >= maxlen)
                return (EINVAL);
+       *oldlenp = len -1; /* deal with NULL strings correctly */
        if (oldp) {
        if (oldp) {
-               *oldlenp = len;
                error = copyout(str, oldp, len);
        }
        if (error == 0 && newp) {
                error = copyin(newp, str, newlen);
                str[newlen] = 0;
                error = copyout(str, oldp, len);
        }
        if (error == 0 && newp) {
                error = copyin(newp, str, newlen);
                str[newlen] = 0;
+               AUDIT_ARG(text, (char *)str);
        }
        return (error);
 }
        }
        return (error);
 }
@@ -654,6 +821,7 @@ sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
 /*
  * As above, but read-only.
  */
 /*
  * As above, but read-only.
  */
+int
 sysctl_rdstring(oldp, oldlenp, newp, str)
        void *oldp;
        size_t *oldlenp;
 sysctl_rdstring(oldp, oldlenp, newp, str)
        void *oldp;
        size_t *oldlenp;
@@ -677,6 +845,7 @@ sysctl_rdstring(oldp, oldlenp, newp, str)
  * Validate parameters and get old / set new parameters
  * for a structure oriented sysctl function.
  */
  * Validate parameters and get old / set new parameters
  * for a structure oriented sysctl function.
  */
+int
 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
        void *oldp;
        size_t *oldlenp;
 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
        void *oldp;
        size_t *oldlenp;
@@ -704,6 +873,7 @@ sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
  * Validate parameters and get old parameters
  * for a structure oriented sysctl function.
  */
  * Validate parameters and get old parameters
  * for a structure oriented sysctl function.
  */
+int
 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
        void *oldp;
        size_t *oldlenp;
 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
        void *oldp;
        size_t *oldlenp;
@@ -725,6 +895,7 @@ sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
 /*
  * Get file structures.
  */
 /*
  * Get file structures.
  */
+int
 sysctl_file(where, sizep)
        char *where;
        size_t *sizep;
 sysctl_file(where, sizep)
        char *where;
        size_t *sizep;
@@ -776,6 +947,7 @@ sysctl_file(where, sizep)
  */
 #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
 
  */
 #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
 
+int
 sysctl_doproc(name, namelen, where, sizep)
        int *name;
        u_int namelen;
 sysctl_doproc(name, namelen, where, sizep)
        int *name;
        u_int namelen;
@@ -820,24 +992,28 @@ again:
                        break;
 
                case KERN_PROC_TTY:
                        break;
 
                case KERN_PROC_TTY:
-                       if ( doingzomb || (p->p_flag & P_CONTROLT) == 0 ||
+                       if ((p->p_flag & P_CONTROLT) == 0 ||
+                               (p->p_session == NULL) ||
                            p->p_session->s_ttyp == NULL ||
                            p->p_session->s_ttyp->t_dev != (dev_t)name[1])
                                continue;
                        break;
 
                case KERN_PROC_UID:
                            p->p_session->s_ttyp == NULL ||
                            p->p_session->s_ttyp->t_dev != (dev_t)name[1])
                                continue;
                        break;
 
                case KERN_PROC_UID:
-                       if (doingzomb || (p->p_ucred->cr_uid != (uid_t)name[1]))
+                       if ((p->p_ucred == NULL) ||
+                               (p->p_ucred->cr_uid != (uid_t)name[1]))
                                continue;
                        break;
 
                case KERN_PROC_RUID:
                                continue;
                        break;
 
                case KERN_PROC_RUID:
-                       if ( doingzomb || (p->p_cred->p_ruid != (uid_t)name[1]))
+                       if ((p->p_ucred == NULL) ||
+                               (p->p_cred->p_ruid != (uid_t)name[1]))
                                continue;
                        break;
                }
                if (buflen >= sizeof(struct kinfo_proc)) {
                                continue;
                        break;
                }
                if (buflen >= sizeof(struct kinfo_proc)) {
-                       fill_proc(p, &kproc, doingzomb);
+                       bzero(&kproc, sizeof(struct kinfo_proc));
+                       fill_proc(p, &kproc);
                        if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
                            sizeof(struct kinfo_proc)))
                                return (error);
                        if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
                            sizeof(struct kinfo_proc)))
                                return (error);
@@ -862,20 +1038,10 @@ again:
        return (0);
 }
 
        return (0);
 }
 
-void
-fill_proc(p,kp, doingzomb)
-       register struct proc *p;
-       register struct kinfo_proc *kp;
-       int doingzomb;
-{
-       fill_externproc(p, &kp->kp_proc);
-       if (!doingzomb)
-               fill_eproc(p, &kp->kp_eproc);
-}
 /*
  * Fill in an eproc structure for the specified process.
  */
 /*
  * Fill in an eproc structure for the specified process.
  */
-void
+static void
 fill_eproc(p, ep)
        register struct proc *p;
        register struct eproc *ep;
 fill_eproc(p, ep)
        register struct proc *p;
        register struct eproc *ep;
@@ -883,41 +1049,38 @@ fill_eproc(p, ep)
        register struct tty *tp;
 
        ep->e_paddr = p;
        register struct tty *tp;
 
        ep->e_paddr = p;
-       ep->e_sess = p->p_pgrp->pg_session;
-       ep->e_pcred = *p->p_cred;
-       ep->e_ucred = *p->p_ucred;
+       if (p->p_pgrp) {
+               ep->e_sess = p->p_pgrp->pg_session;
+               ep->e_pgid = p->p_pgrp->pg_id;
+               ep->e_jobc = p->p_pgrp->pg_jobc;
+               if (ep->e_sess && ep->e_sess->s_ttyvp)
+                       ep->e_flag = EPROC_CTTY;
+       } else {
+               ep->e_sess = (struct session *)0;
+               ep->e_pgid = 0;
+               ep->e_jobc = 0;
+       }
+       ep->e_ppid = (p->p_pptr) ? p->p_pptr->p_pid : 0;
+       if (p->p_cred) {
+               ep->e_pcred = *p->p_cred;
+               if (p->p_ucred)
+                       ep->e_ucred = *p->p_ucred;
+       }
        if (p->p_stat == SIDL || p->p_stat == SZOMB) {
        if (p->p_stat == SIDL || p->p_stat == SZOMB) {
-               ep->e_vm.vm_rssize = 0;
                ep->e_vm.vm_tsize = 0;
                ep->e_vm.vm_dsize = 0;
                ep->e_vm.vm_ssize = 0;
                ep->e_vm.vm_tsize = 0;
                ep->e_vm.vm_dsize = 0;
                ep->e_vm.vm_ssize = 0;
-               /* ep->e_vm.vm_pmap = XXX; */
-       } else {
-#if FIXME  /* [ */
-               register vm_map_t vm = ((task_t)p->task)->map;
-
-               ep->e_vm.vm_rssize = pmap_resident_count(vm->pmap); /*XXX*/
-//             ep->e_vm.vm_tsize = vm->vm_tsize;
-//             ep->e_vm.vm_dsize = vm->vm_dsize;
-//             ep->e_vm.vm_ssize = vm->vm_ssize;
-#else  /* FIXME ][ */
-               ep->e_vm.vm_rssize = 0; /*XXX*/
-#endif  /* FIXME ] */
        }
        }
-       if (p->p_pptr)
-               ep->e_ppid = p->p_pptr->p_pid;
-       else
-               ep->e_ppid = 0;
-       ep->e_pgid = p->p_pgrp->pg_id;
-       ep->e_jobc = p->p_pgrp->pg_jobc;
-       if ((p->p_flag & P_CONTROLT) &&
+       ep->e_vm.vm_rssize = 0;
+
+       if ((p->p_flag & P_CONTROLT) && (ep->e_sess) &&
             (tp = ep->e_sess->s_ttyp)) {
                ep->e_tdev = tp->t_dev;
                ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
                ep->e_tsess = tp->t_session;
        } else
                ep->e_tdev = NODEV;
             (tp = ep->e_sess->s_ttyp)) {
                ep->e_tdev = tp->t_dev;
                ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
                ep->e_tsess = tp->t_session;
        } else
                ep->e_tdev = NODEV;
-       ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
+
        if (SESS_LEADER(p))
                ep->e_flag |= EPROC_SLEADER;
        if (p->p_wmesg)
        if (SESS_LEADER(p))
                ep->e_flag |= EPROC_SLEADER;
        if (p->p_wmesg)
@@ -925,15 +1088,18 @@ fill_eproc(p, ep)
        ep->e_xsize = ep->e_xrssize = 0;
        ep->e_xccount = ep->e_xswrss = 0;
 }
        ep->e_xsize = ep->e_xrssize = 0;
        ep->e_xccount = ep->e_xswrss = 0;
 }
+
 /*
  * Fill in an eproc structure for the specified process.
  */
 /*
  * Fill in an eproc structure for the specified process.
  */
-void
+static void
 fill_externproc(p, exp)
        register struct proc *p;
        register struct extern_proc *exp;
 {
        exp->p_forw = exp->p_back = NULL;
 fill_externproc(p, exp)
        register struct proc *p;
        register struct extern_proc *exp;
 {
        exp->p_forw = exp->p_back = NULL;
+       if (p->p_stats)
+               exp->p_starttime = p->p_stats->p_start;
        exp->p_vmspace = NULL;
        exp->p_sigacts = p->p_sigacts;
        exp->p_flag  = p->p_flag;
        exp->p_vmspace = NULL;
        exp->p_sigacts = p->p_sigacts;
        exp->p_flag  = p->p_flag;
@@ -961,10 +1127,10 @@ fill_externproc(p, exp)
        exp->p_iticks  = p->p_iticks ;
        exp->p_traceflag  = p->p_traceflag ;
        exp->p_tracep  = p->p_tracep ;
        exp->p_iticks  = p->p_iticks ;
        exp->p_traceflag  = p->p_traceflag ;
        exp->p_tracep  = p->p_tracep ;
-       exp->p_siglist  = p->p_siglist ;
+       exp->p_siglist  = 0 ;   /* No longer relevant */
        exp->p_textvp  = p->p_textvp ;
        exp->p_holdcnt = 0 ;
        exp->p_textvp  = p->p_textvp ;
        exp->p_holdcnt = 0 ;
-       exp->p_sigmask  = p->p_sigmask ;
+       exp->p_sigmask  = 0 ;   /* no longer avaialable */
        exp->p_sigignore  = p->p_sigignore ;
        exp->p_sigcatch  = p->p_sigcatch ;
        exp->p_priority  = p->p_priority ;
        exp->p_sigignore  = p->p_sigignore ;
        exp->p_sigcatch  = p->p_sigcatch ;
        exp->p_priority  = p->p_priority ;
@@ -979,6 +1145,16 @@ fill_externproc(p, exp)
        exp->p_ru  = p->p_ru ;
 }
 
        exp->p_ru  = p->p_ru ;
 }
 
+static void
+fill_proc(p, kp)
+       register struct proc *p;
+       register struct kinfo_proc *kp;
+{
+       fill_externproc(p, &kp->kp_proc);
+       fill_eproc(p, &kp->kp_eproc);
+}
+
+int
 kdebug_ops(name, namelen, where, sizep, p)
 int *name;
 u_int namelen;
 kdebug_ops(name, namelen, where, sizep, p)
 int *name;
 u_int namelen;
@@ -986,12 +1162,13 @@ char *where;
 size_t *sizep;
 struct proc *p;
 {
 size_t *sizep;
 struct proc *p;
 {
-int size=*sizep;
-int ret=0;
-extern int kdbg_control(int *name, u_int namelen, char * where,size_t * sizep);
+       int size=*sizep;
+       int ret=0;
+       extern int kdbg_control(int *name, u_int namelen,
+               char * where,size_t * sizep);
 
 
-        if (ret = suser(p->p_ucred, &p->p_acflag))
-               return(ret);
+       if (ret = suser(p->p_ucred, &p->p_acflag))
+               return(ret);
 
        switch(name[0]) {
        case KERN_KDEFLAGS:
 
        switch(name[0]) {
        case KERN_KDEFLAGS:
@@ -1008,6 +1185,7 @@ extern int kdbg_control(int *name, u_int namelen, char * where,size_t * sizep);
        case KERN_KDPIDEX:
        case KERN_KDSETRTCDEC:
        case KERN_KDSETBUF:
        case KERN_KDPIDEX:
        case KERN_KDSETRTCDEC:
        case KERN_KDSETBUF:
+       case KERN_KDGETENTROPY:
                ret = kdbg_control(name, namelen, where, sizep);
                break;
        default:
                ret = kdbg_control(name, namelen, where, sizep);
                break;
        default:
@@ -1017,6 +1195,7 @@ extern int kdbg_control(int *name, u_int namelen, char * where,size_t * sizep);
        return(ret);
 }
 
        return(ret);
 }
 
+int
 pcsamples_ops(name, namelen, where, sizep, p)
 int *name;
 u_int namelen;
 pcsamples_ops(name, namelen, where, sizep, p)
 int *name;
 u_int namelen;
@@ -1024,11 +1203,12 @@ char *where;
 size_t *sizep;
 struct proc *p;
 {
 size_t *sizep;
 struct proc *p;
 {
-int ret=0;
-extern int pcsamples_control(int *name, u_int namelen, char * where,size_t * sizep);
+       int ret=0;
+       extern int pcsamples_control(int *name, u_int namelen,
+               char * where,size_t * sizep);
 
 
-        if (ret = suser(p->p_ucred, &p->p_acflag))
-               return(ret);
+       if (ret = suser(p->p_ucred, &p->p_acflag))
+               return(ret);
 
        switch(name[0]) {
        case KERN_PCDISABLE:
 
        switch(name[0]) {
        case KERN_PCDISABLE:
@@ -1049,16 +1229,39 @@ extern int pcsamples_control(int *name, u_int namelen, char * where,size_t * siz
 }
 
 /*
 }
 
 /*
- *     Returns the top N bytes of the user stack, with
- *     everything below the first argument character
- *     zeroed for security reasons.
- *     Odd data structure is for compatibility.
+ * Return the top *sizep bytes of the user stack, or the entire area of the
+ * user stack down through the saved exec_path, whichever is smaller.
  */
  */
-sysctl_procargs(name, namelen, where, sizep)
+int
+sysctl_procargs(name, namelen, where, sizep, cur_proc)
+       int *name;
+       u_int namelen;
+       char *where;
+       size_t *sizep;
+       struct proc *cur_proc;
+{
+       return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 0);
+}
+
+static int
+sysctl_procargs2(name, namelen, where, sizep, cur_proc)
        int *name;
        u_int namelen;
        char *where;
        size_t *sizep;
        int *name;
        u_int namelen;
        char *where;
        size_t *sizep;
+       struct proc *cur_proc;
+{
+       return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 1);
+}
+
+static int
+sysctl_procargsx(name, namelen, where, sizep, cur_proc, argc_yes)
+       int *name;
+       u_int namelen;
+       char *where;
+       size_t *sizep;
+       struct proc *cur_proc;
+       int argc_yes;
 {
        register struct proc *p;
        register int needed = 0;
 {
        register struct proc *p;
        register int needed = 0;
@@ -1072,14 +1275,14 @@ sysctl_procargs(name, namelen, where, sizep)
        caddr_t data;
        unsigned size;
        vm_offset_t     copy_start, copy_end;
        caddr_t data;
        unsigned size;
        vm_offset_t     copy_start, copy_end;
-       vm_offset_t     dealloc_start;  /* area to remove from kernel map */
-       vm_offset_t     dealloc_end;
        int             *ip;
        kern_return_t ret;
        int pid;
 
        int             *ip;
        kern_return_t ret;
        int pid;
 
+       if (argc_yes)
+               buflen -= NBPW;         /* reserve first word to return argc */
 
 
-       if ((buflen <= 0) || (buflen > (PAGE_SIZE << 1))) {
+       if ((buflen <= 0) || (buflen > ARG_MAX)) {
                return(EINVAL);
        }
        arg_size = buflen;
                return(EINVAL);
        }
        arg_size = buflen;
@@ -1089,6 +1292,7 @@ sysctl_procargs(name, namelen, where, sizep)
         */
        pid = name[0];
 
         */
        pid = name[0];
 
+ restart:
        p = pfind(pid);
        if (p == NULL) {
                return(EINVAL);
        p = pfind(pid);
        if (p == NULL) {
                return(EINVAL);
@@ -1107,6 +1311,9 @@ sysctl_procargs(name, namelen, where, sizep)
        if (!p->user_stack)
                return(EINVAL);
 
        if (!p->user_stack)
                return(EINVAL);
 
+       if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid) 
+               && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
+               return (EINVAL);
        arg_addr = (vm_offset_t)(p->user_stack - arg_size);
 
 
        arg_addr = (vm_offset_t)(p->user_stack - arg_size);
 
 
@@ -1119,22 +1326,31 @@ sysctl_procargs(name, namelen, where, sizep)
        if (task == NULL)
                return(EINVAL);
        
        if (task == NULL)
                return(EINVAL);
        
-       task_reference(task);
+       /*
+        * A regular task_reference call can block, causing the funnel
+        * to be dropped and allowing the proc/task to get freed.
+        * Instead, we issue a non-blocking attempt at the task reference,
+        * and look up the proc/task all over again if that fails.
+        */
+       if (!task_reference_try(task)) {
+               mutex_pause();
+               goto restart;
+       }
 
 
-       ret = kmem_alloc(kernel_map, &copy_start, round_page(arg_size));
+       ret = kmem_alloc(kernel_map, &copy_start, round_page_32(arg_size));
        if (ret != KERN_SUCCESS) {
                task_deallocate(task);
                return(ENOMEM);
        }
 
        proc_map = get_task_map(task);
        if (ret != KERN_SUCCESS) {
                task_deallocate(task);
                return(ENOMEM);
        }
 
        proc_map = get_task_map(task);
-       copy_end = round_page(copy_start + arg_size);
+       copy_end = round_page_32(copy_start + arg_size);
 
 
-       if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page(arg_size), 
+       if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page_32(arg_size), 
                        FALSE, &tmp) != KERN_SUCCESS) {
                        task_deallocate(task);
                        kmem_free(kernel_map, copy_start,
                        FALSE, &tmp) != KERN_SUCCESS) {
                        task_deallocate(task);
                        kmem_free(kernel_map, copy_start,
-                                       round_page(arg_size));
+                                       round_page_32(arg_size));
                        return (EIO);
        }
 
                        return (EIO);
        }
 
@@ -1147,61 +1363,94 @@ sysctl_procargs(name, namelen, where, sizep)
        if( vm_map_copy_overwrite(kernel_map, copy_start, 
                tmp, FALSE) != KERN_SUCCESS) {
                        kmem_free(kernel_map, copy_start,
        if( vm_map_copy_overwrite(kernel_map, copy_start, 
                tmp, FALSE) != KERN_SUCCESS) {
                        kmem_free(kernel_map, copy_start,
-                                       round_page(arg_size));
+                                       round_page_32(arg_size));
                        return (EIO);
        }
 
        data = (caddr_t) (copy_end - arg_size);
                        return (EIO);
        }
 
        data = (caddr_t) (copy_end - arg_size);
-       ip = (int *) copy_end;          
-       size = arg_size;
 
 
-       /*
-        *      Now look down the stack for the bottom of the
-        *      argument list.  Since this call is otherwise
-        *      unprotected, we can't let the nosy user see
-        *      anything else on the stack.
-        *
-        *      The arguments are pushed on the stack by
-        *      execve() as:
-        *
-        *              .long   0
-        *              arg 0   (null-terminated)
-        *              arg 1
-        *              ...
-        *              arg N
-        *              .long   0
-        *
-        */
+       if (buflen > p->p_argslen) {
+               data = &data[buflen - p->p_argslen];
+               size = p->p_argslen;
+       } else {
+               size = buflen;
+       }
 
 
-       ip -= 2; /*skip trailing 0 word and assume at least one
-                 argument.  The last word of argN may be just
-                 the trailing 0, in which case we'd stop
-                 there */
-       while (*--ip)
-               if (ip == (int *)data)
-                       break;
-        /* 
-         *  To account for saved path name and not having a null after that
-         *  Run the sweep again. If we have already sweeped entire range skip this
-         */
-         if (ip != (int *)data) {
-                while (*--ip)
-                    if (ip == (int *)data)
-                            break;
-        }
-        
-       bzero(data, (unsigned) ((int)ip - (int)data));
-
-       dealloc_start = copy_start;
-       dealloc_end = copy_end;
-
-
-       size = MIN(size, buflen);
-       error = copyout(data, where, size);
-
-       if (dealloc_start != (vm_offset_t) 0) {
-               kmem_free(kernel_map, dealloc_start,
-                       dealloc_end - dealloc_start);
+       if (argc_yes) {
+               /* Put processes argc as the first word in the copyout buffer */
+               suword(where, p->p_argc);
+               error = copyout(data, where + NBPW, size);
+       } else {
+               error = copyout(data, where, size);
+
+               /*
+                * Make the old PROCARGS work to return the executable's path
+                * But, only if there is enough space in the provided buffer
+                *
+                * on entry: data [possibily] points to the beginning of the path 
+                * 
+                * Note: we keep all pointers&sizes aligned to word boundries
+                */
+
+               if ( (! error) && (buflen > p->p_argslen) )
+               {
+                       int binPath_sz;
+                       int extraSpaceNeeded, addThis;
+                       char * placeHere;
+                       char * str = (char *) data;
+                       unsigned int max_len = size;
+
+                       /* Some apps are really bad about messing up their stacks
+                          So, we have to be extra careful about getting the length
+                          of the executing binary.  If we encounter an error, we bail.
+                       */
+
+                       /* Limit ourselves to PATH_MAX paths */
+                       if ( max_len > PATH_MAX ) max_len = PATH_MAX;
+
+                       binPath_sz = 0;
+
+                       while ( (binPath_sz < max_len-1) && (*str++ != 0) )
+                               binPath_sz++;
+
+                       if (binPath_sz < max_len-1) binPath_sz += 1;
+
+                       /* Pre-Flight the space requiremnts */
+
+                       /* Account for the padding that fills out binPath to the next word */
+                       binPath_sz += (binPath_sz & (NBPW-1)) ? (NBPW-(binPath_sz & (NBPW-1))) : 0;
+
+                       placeHere = where + size;
+
+                       /* Account for the bytes needed to keep placeHere word aligned */ 
+                       addThis = ((unsigned long)placeHere & (NBPW-1)) ? (NBPW-((unsigned long)placeHere & (NBPW-1))) : 0;
+
+                       /* Add up all the space that is needed */
+                       extraSpaceNeeded = binPath_sz + addThis + (4 * NBPW);
+
+                       /* is there is room to tack on argv[0]? */
+                       if ( (buflen & ~(NBPW-1)) >= ( p->p_argslen + extraSpaceNeeded ))
+                       {
+                               placeHere += addThis;
+                               suword(placeHere, 0);
+                               placeHere += NBPW;
+                               suword(placeHere, 0xBFFF0000);
+                               placeHere += NBPW;
+                               suword(placeHere, 0);
+                               placeHere += NBPW;
+                               error = copyout(data, placeHere, binPath_sz);
+                               if ( ! error )
+                               {
+                                       placeHere += binPath_sz;
+                                       suword(placeHere, 0);
+                                       size += extraSpaceNeeded;
+                               }
+                       }
+               }
+       }
+
+       if (copy_start != (vm_offset_t) 0) {
+               kmem_free(kernel_map, copy_start, copy_end - copy_start);
        }
        if (error) {
                return(error);
        }
        if (error) {
                return(error);
@@ -1211,3 +1460,212 @@ sysctl_procargs(name, namelen, where, sizep)
                *sizep = size;
        return (0);
 }
                *sizep = size;
        return (0);
 }
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of concurrent aio requests.  Makes sure
+ * the system wide limit is greater than the per process
+ * limit.
+ */
+static int
+sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int             new_value;
+
+       if ( oldp && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp )
+               error = copyout( &aio_max_requests, oldp, sizeof(int) );
+       if ( error == 0 && newp )
+               error = copyin( newp, &new_value, sizeof(int) );
+       if ( error == 0 && newp ) {
+               if ( new_value >= aio_max_requests_per_process )
+                       aio_max_requests = new_value;
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_aiomax */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of concurrent aio requests per process.  
+ * Makes sure per process limit is less than the system wide
+ * limit.
+ */
+static int
+sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int             new_value = 0;
+
+       if ( oldp && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp )
+               error = copyout( &aio_max_requests_per_process, oldp, sizeof(int) );
+       if ( error == 0 && newp )
+               error = copyin( newp, &new_value, sizeof(int) );
+       if ( error == 0 && newp ) {
+               if ( new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX )
+                       aio_max_requests_per_process = new_value;
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_aioprocmax */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of async IO worker threads.  
+ * We only allow an increase in the number of worker threads.
+ */
+static int
+sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int             new_value;
+
+       if ( oldp && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp )
+               error = copyout( &aio_worker_threads, oldp, sizeof(int) );
+       if ( error == 0 && newp )
+               error = copyin( newp, &new_value, sizeof(int) );
+       if ( error == 0 && newp ) {
+               if (new_value > aio_worker_threads ) {
+                       _aio_create_worker_threads( (new_value - aio_worker_threads) );
+                       aio_worker_threads = new_value;
+               }
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_aiothreads */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of processes per UID.
+ * Makes sure per UID limit is less than the system wide limit.
+ */
+static int
+sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int             new_value;
+
+       if ( oldp != NULL && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp != NULL && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp != NULL )
+               error = copyout( &maxprocperuid, oldp, sizeof(int) );
+       if ( error == 0 && newp != NULL ) {
+               error = copyin( newp, &new_value, sizeof(int) );
+               if ( error == 0 ) {
+                       AUDIT_ARG(value, new_value);
+                       if ( new_value <= maxproc && new_value > 0 )
+                               maxprocperuid = new_value;
+                       else
+                               error = EINVAL;
+               }
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_maxprocperuid */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of files per process.
+ * Makes sure per process limit is less than the system-wide limit.
+ */
+static int
+sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int             new_value;
+
+       if ( oldp != NULL && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp != NULL && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp != NULL )
+               error = copyout( &maxfilesperproc, oldp, sizeof(int) );
+       if ( error == 0 && newp != NULL ) {
+               error = copyin( newp, &new_value, sizeof(int) );
+               if ( error == 0 ) {
+                       AUDIT_ARG(value, new_value);
+                       if ( new_value < maxfiles && new_value > 0 )
+                               maxfilesperproc = new_value;
+                       else
+                               error = EINVAL;
+               }
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_maxfilesperproc */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for the system-wide limit on the max number of processes.
+ * Makes sure the system-wide limit is less than the configured hard
+ * limit set at kernel compilation.
+ */
+static int
+sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
+{
+       int     error = 0;
+       int     new_value;
+
+       if ( oldp != NULL && *oldlenp < sizeof(int) )
+               return (ENOMEM);
+       if ( newp != NULL && newlen != sizeof(int) )
+               return (EINVAL);
+               
+       *oldlenp = sizeof(int);
+       if ( oldp != NULL )
+               error = copyout( &maxproc, oldp, sizeof(int) );
+       if ( error == 0 && newp != NULL ) {
+               error = copyin( newp, &new_value, sizeof(int) );
+               if ( error == 0 ) {
+                       AUDIT_ARG(value, new_value);
+                       if ( new_value <= hard_maxproc && new_value > 0 )
+                               maxproc = new_value;
+                       else
+                               error = EINVAL;
+               }
+               else
+                       error = EINVAL;
+       }
+       return( error );
+       
+} /* sysctl_maxproc */