]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_prot.c
xnu-4903.231.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_prot.c
index 46ab8bf1bce557f9ec7da33cf08d57b2a2c9618c..36beb273735e442be113b9625ba29f5e9051053c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * limitations under the License.
  * 
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
-/*
+ *
+ *
+ * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved
+ * 
+ *
  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
  *     The Regents of the University of California.  All rights reserved.
  * (c) UNIX System Laboratories, Inc.
  * SUCH DAMAGE.
  *
  *     @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
- */
-/*
+ * 
+ *
  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
  * support for mandatory and extensible security protections.  This notice
  * is included in support of clause 2.2 (b) of the Apple Public License,
  * Version 2.0.
- */
-/*
+ *
+ *
  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
  * support for mandatory and extensible security protections.  This notice
  * is included in support of clause 2.2 (b) of the Apple Public License,
  * Version 2.0.
+ *
  */
 
 /*
 #include <sys/timeb.h>
 #include <sys/times.h>
 #include <sys/malloc.h>
+#include <sys/persona.h>
 
-#include <bsm/audit_kernel.h>
-
-#if CONFIG_LCTX
-#include <sys/lctx.h>
-#endif
+#include <security/audit/audit.h>
 
 #if CONFIG_MACF
 #include <security/mac_framework.h>
-#if CONFIG_MACF_MACH
-#include <secuity/mac_mach_internal.h>
-#endif
 #endif
 
 #include <sys/mount_internal.h>
 #include <kern/assert.h>
 
 
-int groupmember(gid_t gid, kauth_cred_t cred);
-
 /*
  * Credential debugging; we can track entry into a function that might
  * change a credential, and we can track actual credential changes that
@@ -137,6 +132,9 @@ extern void kauth_cred_print(kauth_cred_t cred);
 #define        DEBUG_CRED_CHANGE(fmt, ...)     do {} while (0)
 #endif /* !DEBUG_CRED */
 
+#if DEVELOPMENT || DEBUG
+extern void task_importance_update_owner_info(task_t);
+#endif
 
 
 /*
@@ -152,9 +150,9 @@ extern void kauth_cred_print(kauth_cred_t cred);
  * XXX:                Belongs in kern_proc.c
  */
 int
-setprivexec(proc_t p, struct setprivexec_args *uap, register_t *retval)
+setprivexec(proc_t p, struct setprivexec_args *uap, int32_t *retval)
 {
-       AUDIT_ARG(value, uap->flag);
+       AUDIT_ARG(value32, uap->flag);
        *retval = p->p_debugger;
        p->p_debugger = (uap->flag != 0);
        return(0);
@@ -173,7 +171,7 @@ setprivexec(proc_t p, struct setprivexec_args *uap, register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-getpid(proc_t p, __unused struct getpid_args *uap, register_t *retval)
+getpid(proc_t p, __unused struct getpid_args *uap, int32_t *retval)
 {
 
        *retval = p->p_pid;
@@ -193,7 +191,7 @@ getpid(proc_t p, __unused struct getpid_args *uap, register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-getppid(proc_t p, __unused struct getppid_args *uap, register_t *retval)
+getppid(proc_t p, __unused struct getppid_args *uap, int32_t *retval)
 {
 
        *retval = p->p_ppid;
@@ -213,7 +211,7 @@ getppid(proc_t p, __unused struct getppid_args *uap, register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-getpgrp(proc_t p, __unused struct getpgrp_args *uap, register_t *retval)
+getpgrp(proc_t p, __unused struct getpgrp_args *uap, int32_t *retval)
 {
 
        *retval = p->p_pgrpid;
@@ -238,7 +236,7 @@ getpgrp(proc_t p, __unused struct getpgrp_args *uap, register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-getpgid(proc_t p, struct getpgid_args *uap, register_t *retval)
+getpgid(proc_t p, struct getpgid_args *uap, int32_t *retval)
 {
        proc_t pt;
        int refheld = 0;
@@ -275,7 +273,7 @@ found:
  * XXX:                Belongs in kern_proc.c
  */
 int
-getsid(proc_t p, struct getsid_args *uap, register_t *retval)
+getsid(proc_t p, struct getsid_args *uap, int32_t *retval)
 {
        proc_t pt;
        int refheld = 0;
@@ -309,7 +307,7 @@ found:
  * Returns:    uid_t                           The real uid of the caller
  */
 int
-getuid(__unused proc_t p, __unused struct getuid_args *uap, register_t *retval)
+getuid(__unused proc_t p, __unused struct getuid_args *uap, int32_t *retval)
 {
 
        *retval = kauth_getruid();
@@ -327,7 +325,7 @@ getuid(__unused proc_t p, __unused struct getuid_args *uap, register_t *retval)
  * Returns:    uid_t                           The effective uid of the caller
  */
 int
-geteuid(__unused proc_t p, __unused struct geteuid_args *uap, register_t *retval)
+geteuid(__unused proc_t p, __unused struct geteuid_args *uap, int32_t *retval)
 {
 
        *retval = kauth_getuid();
@@ -347,7 +345,7 @@ geteuid(__unused proc_t p, __unused struct geteuid_args *uap, register_t *retval
  *             ESRCH                           No per thread identity active
  */
 int
-gettid(__unused proc_t p, struct gettid_args *uap, register_t *retval)
+gettid(__unused proc_t p, struct gettid_args *uap, int32_t *retval)
 {
        struct uthread *uthread = get_bsdthread_info(current_thread());
        int     error;
@@ -359,9 +357,9 @@ gettid(__unused proc_t p, struct gettid_args *uap, register_t *retval)
        if (!(uthread->uu_flag & UT_SETUID))
                return (ESRCH);
 
-       if ((error = suword(uap->uidp, uthread->uu_ucred->cr_ruid)))
+       if ((error = suword(uap->uidp, kauth_cred_getruid(uthread->uu_ucred))))
                return (error);
-       if ((error = suword(uap->gidp, uthread->uu_ucred->cr_rgid)))
+       if ((error = suword(uap->gidp, kauth_cred_getrgid(uthread->uu_ucred))))
                return (error);
 
        *retval = 0;
@@ -379,7 +377,7 @@ gettid(__unused proc_t p, struct gettid_args *uap, register_t *retval)
  * Returns:    gid_t                           The real gid of the caller
  */
 int
-getgid(__unused proc_t p, __unused struct getgid_args *uap, register_t *retval)
+getgid(__unused proc_t p, __unused struct getgid_args *uap, int32_t *retval)
 {
 
        *retval = kauth_getrgid();
@@ -403,7 +401,7 @@ getgid(__unused proc_t p, __unused struct getgid_args *uap, register_t *retval)
  *             detail.
  */
 int
-getegid(__unused proc_t p, __unused struct getegid_args *uap, register_t *retval)
+getegid(__unused proc_t p, __unused struct getegid_args *uap, int32_t *retval)
 {
 
        *retval = kauth_getgid();
@@ -442,26 +440,28 @@ getegid(__unused proc_t p, __unused struct getegid_args *uap, register_t *retval
  *             be returned by this call.
  */
 int
-getgroups(__unused proc_t p, struct getgroups_args *uap, register_t *retval)
+getgroups(__unused proc_t p, struct getgroups_args *uap, int32_t *retval)
 {
        int ngrp;
        int error;
        kauth_cred_t cred;
+       posix_cred_t pcred;
 
        /* grab reference while we muck around with the credential */
        cred = kauth_cred_get_with_ref();
+       pcred = posix_cred_get(cred);
 
        if ((ngrp = uap->gidsetsize) == 0) {
-               *retval = cred->cr_ngroups;
+               *retval = pcred->cr_ngroups;
                kauth_cred_unref(&cred);
                return (0);
        }
-       if (ngrp < cred->cr_ngroups) {
+       if (ngrp < pcred->cr_ngroups) {
                kauth_cred_unref(&cred);
                return (EINVAL);
        }
-       ngrp = cred->cr_ngroups;
-       if ((error = copyout((caddr_t)cred->cr_groups,
+       ngrp = pcred->cr_ngroups;
+       if ((error = copyout((caddr_t)pcred->cr_groups,
                                        uap->gidset, 
                                        ngrp * sizeof(gid_t)))) {
                kauth_cred_unref(&cred);
@@ -475,23 +475,27 @@ getgroups(__unused proc_t p, struct getgroups_args *uap, register_t *retval)
 
 /*
  * Return the per-thread/per-process supplementary groups list.
+ *
+ * XXX implement getsgroups
+ *
  */
-#warning XXX implement getsgroups
+
 int
-getsgroups(__unused proc_t p, __unused struct getsgroups_args *uap, __unused register_t *retval)
+getsgroups(__unused proc_t p, __unused struct getsgroups_args *uap, __unused int32_t *retval)
 {
-       /* XXX implement */
        return(ENOTSUP);
 }
 
 /*
  * Return the per-thread/per-process whiteout groups list.
+ * 
+ * XXX implement getwgroups
+ *
  */
-#warning XXX implement getwgroups
+
 int
-getwgroups(__unused proc_t p, __unused struct getwgroups_args *uap, __unused register_t *retval)
+getwgroups(__unused proc_t p, __unused struct getwgroups_args *uap, __unused int32_t *retval)
 {
-       /* XXX implement */
        return(ENOTSUP);
 }
 
@@ -521,7 +525,7 @@ getwgroups(__unused proc_t p, __unused struct getwgroups_args *uap, __unused reg
  * XXX:                Belongs in kern_proc.c
  */
 int
-setsid(proc_t p, __unused struct setsid_args *uap, register_t *retval)
+setsid(proc_t p, __unused struct setsid_args *uap, int32_t *retval)
 {
        struct pgrp * pg = PGRP_NULL;
 
@@ -576,7 +580,7 @@ setsid(proc_t p, __unused struct setsid_args *uap, register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-setpgid(proc_t curp, register struct setpgid_args *uap, __unused register_t *retval)
+setpgid(proc_t curp, struct setpgid_args *uap, __unused int32_t *retval)
 {
        proc_t targp = PROC_NULL;       /* target process */
        struct pgrp *pg = PGRP_NULL;    /* target pgrp */
@@ -666,7 +670,13 @@ out:
  *             execution.
  */
 int
-issetugid(proc_t p, __unused struct issetugid_args *uap, register_t *retval)
+proc_issetugid (proc_t p)
+{
+       return (p->p_flag & P_SUGID) ? 1 : 0;
+}
+
+int
+issetugid(proc_t p, __unused struct issetugid_args *uap, int32_t *retval)
 {
        /*
         * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
@@ -677,7 +687,7 @@ issetugid(proc_t p, __unused struct issetugid_args *uap, register_t *retval)
         * that libc *might* have put in their data segment.
         */
 
-       *retval = (p->p_flag & P_SUGID) ? 1 : 0;
+       *retval = proc_issetugid(p);
        return (0);
 }
 
@@ -703,7 +713,7 @@ issetugid(proc_t p, __unused struct issetugid_args *uap, register_t *retval)
  *             flag the process as having set privilege since the last exec.
  */
 int
-setuid(proc_t p, struct setuid_args *uap, __unused register_t *retval)
+setuid(proc_t p, struct setuid_args *uap, __unused int32_t *retval)
 {
        uid_t uid;
        uid_t svuid = KAUTH_UID_NONE;
@@ -711,42 +721,36 @@ setuid(proc_t p, struct setuid_args *uap, __unused register_t *retval)
        uid_t gmuid = KAUTH_UID_NONE;
        int error;
        kauth_cred_t my_cred, my_new_cred;
-
+       posix_cred_t my_pcred;
 
        uid = uap->uid;
 
+       /* get current credential and take a reference while we muck with it */
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
        DEBUG_CRED_ENTER("setuid (%d/%d): %p %d\n", p->p_pid, (p->p_pptr ? p->p_pptr->p_pid : 0), my_cred, uap->uid);
-       AUDIT_ARG(uid, uid, 0, 0, 0);
+       AUDIT_ARG(uid, uid);
 
-       if (uid != my_cred->cr_ruid &&  /* allow setuid(getuid()) */
-           uid != my_cred->cr_svuid && /* allow setuid(saved uid) */
-           (error = suser(my_cred, &p->p_acflag))) {
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
-       /*
-        * Everything's okay, do it.
-        */
+       for (;;) {
+               if (uid != my_pcred->cr_ruid &&         /* allow setuid(getuid()) */
+                   uid != my_pcred->cr_svuid &&        /* allow setuid(saved uid) */
+                   (error = suser(my_cred, &p->p_acflag))) {
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
 
-       /*
-        * If we are priviledged, then set the saved and real UID too;
-        * otherwise, just set the effective UID
-        */
-       if (suser(my_cred, &p->p_acflag) == 0) {
-               svuid = uid;
-               ruid = uid;
                /*
-                * Transfer proc count to new user.
-                * chgproccnt uses list lock for protection
+                * If we are privileged, then set the saved and real UID too;
+                * otherwise, just set the effective UID
                 */
-               (void)chgproccnt(uid, 1);
-               (void)chgproccnt(kauth_getruid(), -1);
-       }
-
-       /* get current credential and take a reference while we muck with it */
-       for (;;) {
+               if (suser(my_cred, &p->p_acflag) == 0) {
+                       svuid = uid;
+                       ruid = uid;
+               } else {
+                       svuid = KAUTH_UID_NONE;
+                       ruid = KAUTH_UID_NONE;
+               }
                /*
                 * Only set the gmuid if the current cred has not opt'ed out;
                 * this normally only happens when calling setgroups() instead
@@ -756,7 +760,7 @@ setuid(proc_t p, struct setuid_args *uap, __unused register_t *retval)
                 * to something other than the default list for the user, as
                 * in entering a group or leaving an exclusion group).
                 */
-               if (!(my_cred->cr_flags & CRF_NOMEMBERD))
+               if (!(my_pcred->cr_flags & CRF_NOMEMBERD))
                        gmuid = uid;
 
                /* 
@@ -769,25 +773,57 @@ setuid(proc_t p, struct setuid_args *uap, __unused register_t *retval)
                my_new_cred = kauth_cred_setresuid(my_cred, ruid, uid, svuid, gmuid);
                if (my_cred != my_new_cred) {
 
-                       DEBUG_CRED_CHANGE("setuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
+                       DEBUG_CRED_CHANGE("setuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_pcred->cr_flags, my_new_cred, posix_cred_get(my_new_cred)->cr_flags);
+
+                       /*
+                        * If we're changing the ruid from A to B, we might race with another thread that's setting ruid from B to A.
+                        * The current locking mechanisms don't allow us to make the entire credential switch operation atomic,
+                        * thus we may be able to change the process credentials from ruid A to B, but get preempted before incrementing the proc
+                        * count of B. If a second thread sees the new process credentials and switches back to ruid A, that other thread
+                        * may be able to decrement the proc count of B before we can increment it. This results in a panic.
+                        * Incrementing the proc count of the target ruid, B, before setting the process credentials prevents this race.
+                        */
+                       if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                               (void)chgproccnt(ruid, 1);
+                       }
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
                         * reference.  If p_ucred has changed then we should
                         * restart this again with the new cred.
+                        *
+                        * Note: the kauth_cred_setresuid has consumed a reference to my_cred, it p_ucred != my_cred, then my_cred must not be dereferenced!
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
+                               /*
+                                * We didn't successfully switch to the new ruid, so decrement
+                                * the procs/uid count that we incremented above.
+                                */
+                               if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                                       (void)chgproccnt(ruid, -1);
+                               }
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                /* try again */
                                continue;
                        }
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
+                       proc_ucred_unlock(p);
+                       /*
+                        * If we've updated the ruid, decrement the count of procs running
+                        * under the previous ruid
+                        */
+                       if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                               (void)chgproccnt(my_pcred->cr_ruid, -1);
+                       }
                }
                break;
        }
@@ -818,31 +854,29 @@ setuid(proc_t p, struct setuid_args *uap, __unused register_t *retval)
  *             flag the process as having set privilege since the last exec.
  */
 int
-seteuid(proc_t p, struct seteuid_args *uap, __unused register_t *retval)
+seteuid(proc_t p, struct seteuid_args *uap, __unused int32_t *retval)
 {
        uid_t euid;
        int error;
        kauth_cred_t my_cred, my_new_cred;
+       posix_cred_t my_pcred;
 
        DEBUG_CRED_ENTER("seteuid: %d\n", uap->euid);
 
        euid = uap->euid;
-       AUDIT_ARG(uid, 0, euid, 0, 0);
+       AUDIT_ARG(euid, euid);
 
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
-       if (euid != my_cred->cr_ruid && euid != my_cred->cr_svuid &&
-           (error = suser(my_cred, &p->p_acflag))) {
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
-
-       /*
-        * Everything's okay, do it.  Copy credentials so other references do
-        * not see our changes.  get current credential and take a reference 
-        * while we muck with it
-        */
        for (;;) {
+
+               if (euid != my_pcred->cr_ruid && euid != my_pcred->cr_svuid &&
+                       (error = suser(my_cred, &p->p_acflag))) {
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
+
                /* 
                 * Set the credential with new info.  If there is no change,
                 * we get back the same credential we passed in; if there is
@@ -850,13 +884,13 @@ seteuid(proc_t p, struct seteuid_args *uap, __unused register_t *retval)
                 * passed in.  The subsequent compare is safe, because it is
                 * a pointer compare rather than a contents compare.
                 */
-               my_new_cred = kauth_cred_setresuid(my_cred, KAUTH_UID_NONE, euid, KAUTH_UID_NONE, my_cred->cr_gmuid);
+               my_new_cred = kauth_cred_setresuid(my_cred, KAUTH_UID_NONE, euid, KAUTH_UID_NONE, my_pcred->cr_gmuid);
        
                if (my_cred != my_new_cred) {
 
-                       DEBUG_CRED_CHANGE("seteuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
+                       DEBUG_CRED_CHANGE("seteuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_pcred->cr_flags, my_new_cred, posix_cred_get(my_new_cred)->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
@@ -864,15 +898,18 @@ seteuid(proc_t p, struct seteuid_args *uap, __unused register_t *retval)
                         * should restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                /* try again */
                                continue;
                        }
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
+                       proc_ucred_unlock(p);
                }
                break;
        }
@@ -916,11 +953,12 @@ seteuid(proc_t p, struct seteuid_args *uap, __unused register_t *retval)
  *             flag the process as having set privilege since the last exec.
  */
 int
-setreuid(proc_t p, struct setreuid_args *uap, __unused register_t *retval)
+setreuid(proc_t p, struct setreuid_args *uap, __unused int32_t *retval)
 {
        uid_t ruid, euid;
        int error;
        kauth_cred_t my_cred, my_new_cred;
+       posix_cred_t my_pcred;
 
        DEBUG_CRED_ENTER("setreuid %d %d\n", uap->ruid, uap->euid);
 
@@ -930,36 +968,31 @@ setreuid(proc_t p, struct setreuid_args *uap, __unused register_t *retval)
                ruid = KAUTH_UID_NONE;
        if (euid == (uid_t)-1)
                euid = KAUTH_UID_NONE;
-       AUDIT_ARG(uid, euid, ruid, 0, 0);
+       AUDIT_ARG(euid, euid);
+       AUDIT_ARG(ruid, ruid);
 
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
-       if (((ruid != KAUTH_UID_NONE &&         /* allow no change of ruid */
-             ruid != my_cred->cr_ruid &&       /* allow ruid = ruid */
-             ruid != my_cred->cr_uid &&        /* allow ruid = euid */
-             ruid != my_cred->cr_svuid) ||     /* allow ruid = svuid */
-            (euid != KAUTH_UID_NONE &&         /* allow no change of euid */
-             euid != my_cred->cr_uid &&        /* allow euid = euid */
-             euid != my_cred->cr_ruid &&       /* allow euid = ruid */
-             euid != my_cred->cr_svuid)) &&    /* allow euid = svui */
-           (error = suser(my_cred, &p->p_acflag))) { /* allow root user any */
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
-
-       /*
-        * Everything's okay, do it.  Copy credentials so other references do
-        * not see our changes.  get current credential and take a reference 
-        * while we muck with it
-        */
        for (;;) {
+
+               if (((ruid != KAUTH_UID_NONE &&         /* allow no change of ruid */
+                     ruid != my_pcred->cr_ruid &&      /* allow ruid = ruid */
+                     ruid != my_pcred->cr_uid &&       /* allow ruid = euid */
+                     ruid != my_pcred->cr_svuid) ||    /* allow ruid = svuid */
+                    (euid != KAUTH_UID_NONE &&         /* allow no change of euid */
+                     euid != my_pcred->cr_uid &&       /* allow euid = euid */
+                     euid != my_pcred->cr_ruid &&      /* allow euid = ruid */
+                     euid != my_pcred->cr_svuid)) &&   /* allow euid = svuid */
+                   (error = suser(my_cred, &p->p_acflag))) { /* allow root user any */
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
+
                uid_t new_euid;
-               uid_t new_ruid;
                uid_t svuid = KAUTH_UID_NONE;
 
-               new_euid = my_cred->cr_uid;
-               new_ruid = my_cred->cr_ruid;
-       
+               new_euid = my_pcred->cr_uid;
                /* 
                 * Set the credential with new info.  If there is no change,
                 * we get back the same credential we passed in; if there is
@@ -967,18 +1000,10 @@ setreuid(proc_t p, struct setreuid_args *uap, __unused register_t *retval)
                 * passed in.  The subsequent compare is safe, because it is
                 * a pointer compare rather than a contents compare.
                 */
-               if (euid == KAUTH_UID_NONE && my_cred->cr_uid != euid) {
+               if (euid != KAUTH_UID_NONE && my_pcred->cr_uid != euid) {
                        /* changing the effective UID */
                        new_euid = euid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-               }
-               if (ruid != KAUTH_UID_NONE && my_cred->cr_ruid != ruid) {
-                       /* changing the real UID; must do user accounting */
-                       /* chgproccnt uses list lock for protection */
-                       (void)chgproccnt(ruid, 1);
-                       (void)chgproccnt(my_cred->cr_ruid, -1);
-                       new_ruid = ruid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
                }
                /*
                 * If the newly requested real uid or effective uid does
@@ -986,35 +1011,68 @@ setreuid(proc_t p, struct setreuid_args *uap, __unused register_t *retval)
                 * new effective uid.  We are protected from escalation
                 * by the prechecking.
                 */
-               if (my_cred->cr_svuid != uap->ruid &&
-                   my_cred->cr_svuid != uap->euid) {
+               if (my_pcred->cr_svuid != uap->ruid &&
+                   my_pcred->cr_svuid != uap->euid) {
                        svuid = new_euid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
                }
 
-               my_new_cred = kauth_cred_setresuid(my_cred, ruid, euid, svuid, my_cred->cr_gmuid);
+               my_new_cred = kauth_cred_setresuid(my_cred, ruid, euid, svuid, my_pcred->cr_gmuid);
        
                if (my_cred != my_new_cred) {
 
-                       DEBUG_CRED_CHANGE("setreuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
+                       DEBUG_CRED_CHANGE("setreuid CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_pcred->cr_flags, my_new_cred, posix_cred_get(my_new_cred)->cr_flags);
+
+                       /*
+                        * If we're changing the ruid from A to B, we might race with another thread that's setting ruid from B to A.
+                        * The current locking mechanisms don't allow us to make the entire credential switch operation atomic,
+                        * thus we may be able to change the process credentials from ruid A to B, but get preempted before incrementing the proc
+                        * count of B. If a second thread sees the new process credentials and switches back to ruid A, that other thread
+                        * may be able to decrement the proc count of B before we can increment it. This results in a panic.
+                        * Incrementing the proc count of the target ruid, B, before setting the process credentials prevents this race.
+                        */
+                       if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                               (void)chgproccnt(ruid, 1);
+                       }
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
                         * reference.  If p_ucred has changed then we should
                         * restart this again with the new cred.
+                        *
+                        * Note: the kauth_cred_setresuid has consumed a reference to my_cred, it p_ucred != my_cred, then my_cred must not be dereferenced!
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
+                               if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                                       /*
+                                        * We didn't successfully switch to the new ruid, so decrement
+                                        * the procs/uid count that we incremented above.
+                                        */
+                                       (void)chgproccnt(ruid, -1);
+                               }
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                /* try again */
                                continue;
                        }
+
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag); /* XXX redundant? */
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
+                       proc_ucred_unlock(p);
+
+                       if (ruid != KAUTH_UID_NONE && !proc_has_persona(p)) {
+                               /*
+                                * We switched to a new ruid, so decrement the count of procs running
+                                * under the previous ruid
+                                */
+                               (void)chgproccnt(my_pcred->cr_ruid, -1);
+                       }
                }
                break;
        }
@@ -1052,40 +1110,44 @@ setreuid(proc_t p, struct setreuid_args *uap, __unused register_t *retval)
  *             the supplementary group list unchanged.
  */
 int
-setgid(proc_t p, struct setgid_args *uap, __unused register_t *retval)
+setgid(proc_t p, struct setgid_args *uap, __unused int32_t *retval)
 {
        gid_t gid;
        gid_t rgid = KAUTH_GID_NONE;
        gid_t svgid = KAUTH_GID_NONE;
        int error;
        kauth_cred_t my_cred, my_new_cred;
+       posix_cred_t my_pcred;
 
        DEBUG_CRED_ENTER("setgid(%d/%d): %d\n", p->p_pid, (p->p_pptr ? p->p_pptr->p_pid : 0), uap->gid);
 
        gid = uap->gid;
-       AUDIT_ARG(gid, gid, 0, 0, 0);
+       AUDIT_ARG(gid, gid);
 
+       /* get current credential and take a reference while we muck with it */
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
-       if (gid != my_cred->cr_rgid &&  /* allow setgid(getgid()) */
-           gid != my_cred->cr_svgid && /* allow setgid(saved gid) */
-           (error = suser(my_cred, &p->p_acflag))) {
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
+       for (;;) {
+               if (gid != my_pcred->cr_rgid &&         /* allow setgid(getgid()) */
+                   gid != my_pcred->cr_svgid &&        /* allow setgid(saved gid) */
+                   (error = suser(my_cred, &p->p_acflag))) {
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
 
-       /*
-        * If we are priviledged, then set the saved and real GID too;
-        * otherwise, just set the effective GID
-        */
-       if (suser(my_cred,  &p->p_acflag) == 0) {
-               svgid = gid;
-               rgid = gid;
-       }
+               /*
+                * If we are privileged, then set the saved and real GID too;
+                * otherwise, just set the effective GID
+                */
+               if (suser(my_cred,  &p->p_acflag) == 0) {
+                       svgid = gid;
+                       rgid = gid;
+               } else {
+                       svgid = KAUTH_GID_NONE;
+                       rgid = KAUTH_GID_NONE;
+               }
 
-       /* get current credential and take a reference while we muck with it */
-       for (;;) {
-               
                /* 
                 * Set the credential with new info.  If there is no change,
                 * we get back the same credential we passed in; if there is
@@ -1098,7 +1160,7 @@ setgid(proc_t p, struct setgid_args *uap, __unused register_t *retval)
 
                        DEBUG_CRED_CHANGE("setgid(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
@@ -1106,15 +1168,18 @@ setgid(proc_t p, struct setgid_args *uap, __unused register_t *retval)
                         * should restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                /* try again */
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                continue;
                        }
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
+                       proc_ucred_unlock(p);
                }
                break;
        }
@@ -1150,28 +1215,30 @@ setgid(proc_t p, struct setgid_args *uap, __unused register_t *retval)
  *             the supplementary group list unchanged.
  */
 int
-setegid(proc_t p, struct setegid_args *uap, __unused register_t *retval)
+setegid(proc_t p, struct setegid_args *uap, __unused int32_t *retval)
 {
        gid_t egid;
        int error;
        kauth_cred_t my_cred, my_new_cred;
+       posix_cred_t my_pcred;
 
        DEBUG_CRED_ENTER("setegid %d\n", uap->egid);
 
        egid = uap->egid;
-       AUDIT_ARG(gid, 0, egid, 0, 0);
+       AUDIT_ARG(egid, egid);
 
+       /* get current credential and take a reference while we muck with it */
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
-       if (egid != my_cred->cr_rgid &&
-           egid != my_cred->cr_svgid &&
-           (error = suser(my_cred, &p->p_acflag))) {
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
 
-       /* get current credential and take a reference while we muck with it */
        for (;;) {
+               if (egid != my_pcred->cr_rgid &&
+                   egid != my_pcred->cr_svgid &&
+                   (error = suser(my_cred, &p->p_acflag))) {
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
                /* 
                 * Set the credential with new info.  If there is no change,
                 * we get back the same credential we passed in; if there is
@@ -1182,9 +1249,9 @@ setegid(proc_t p, struct setegid_args *uap, __unused register_t *retval)
                my_new_cred = kauth_cred_setresgid(my_cred, KAUTH_GID_NONE, egid, KAUTH_GID_NONE);
                if (my_cred != my_new_cred) {
 
-                       DEBUG_CRED_CHANGE("setegid(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
+                       DEBUG_CRED_CHANGE("setegid(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_pcred->cr_flags, my_new_cred, posix_cred_get(my_new_cred)->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
@@ -1192,15 +1259,18 @@ setegid(proc_t p, struct setegid_args *uap, __unused register_t *retval)
                         * should restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                /* try again */
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                continue;
                        }
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
+                       proc_ucred_unlock(p);
                }
                break;
        }
@@ -1250,11 +1320,12 @@ setegid(proc_t p, struct setegid_args *uap, __unused register_t *retval)
  *             the supplementary group list unchanged.
  */
 int
-setregid(proc_t p, struct setregid_args *uap, __unused register_t *retval)
+setregid(proc_t p, struct setregid_args *uap, __unused int32_t *retval)
 {
        gid_t rgid, egid;
        int error;
        kauth_cred_t my_cred, my_new_cred;
+       posix_cred_t my_pcred;
 
        DEBUG_CRED_ENTER("setregid %d %d\n", uap->rgid, uap->egid);
 
@@ -1265,28 +1336,31 @@ setregid(proc_t p, struct setregid_args *uap, __unused register_t *retval)
                rgid = KAUTH_GID_NONE;
        if (egid == (uid_t)-1)
                egid = KAUTH_GID_NONE;
-       AUDIT_ARG(gid, egid, rgid, 0, 0);
+       AUDIT_ARG(egid, egid);
+       AUDIT_ARG(rgid, rgid);
 
+       /* get current credential and take a reference while we muck with it */
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
 
-       if (((rgid != KAUTH_UID_NONE &&         /* allow no change of rgid */
-             rgid != my_cred->cr_rgid &&       /* allow rgid = rgid */
-             rgid != my_cred->cr_gid &&        /* allow rgid = egid */
-             rgid != my_cred->cr_svgid) ||     /* allow rgid = svgid */
-            (egid != KAUTH_UID_NONE &&         /* allow no change of egid */
-             egid != my_cred->cr_groups[0] &&  /* allow no change of egid */
-             egid != my_cred->cr_gid &&        /* allow egid = egid */
-             egid != my_cred->cr_rgid &&       /* allow egid = rgid */
-             egid != my_cred->cr_svgid)) &&    /* allow egid = svgid */
-           (error = suser(my_cred, &p->p_acflag))) { /* allow root user any */
-               kauth_cred_unref(&my_cred);
-               return (error);
-       }
-
-       /* get current credential and take a reference while we muck with it */
        for (;;) {
-               uid_t new_egid = my_cred->cr_gid;
-               uid_t new_rgid = my_cred->cr_rgid;
+
+               if (((rgid != KAUTH_UID_NONE &&         /* allow no change of rgid */
+                     rgid != my_pcred->cr_rgid &&      /* allow rgid = rgid */
+                     rgid != my_pcred->cr_gid &&       /* allow rgid = egid */
+                     rgid != my_pcred->cr_svgid) ||    /* allow rgid = svgid */
+                    (egid != KAUTH_UID_NONE &&         /* allow no change of egid */
+                     egid != my_pcred->cr_groups[0] && /* allow no change of egid */
+                     egid != my_pcred->cr_gid &&       /* allow egid = egid */
+                     egid != my_pcred->cr_rgid &&      /* allow egid = rgid */
+                     egid != my_pcred->cr_svgid)) &&   /* allow egid = svgid */
+                   (error = suser(my_cred, &p->p_acflag))) { /* allow root user any */
+                       kauth_cred_unref(&my_cred);
+                       return (error);
+               }
+
+               uid_t new_egid = my_pcred->cr_gid;
+               uid_t new_rgid = my_pcred->cr_rgid;
                uid_t svgid = KAUTH_UID_NONE;
 
                
@@ -1297,15 +1371,15 @@ setregid(proc_t p, struct setregid_args *uap, __unused register_t *retval)
                 * passed in.  The subsequent compare is safe, because it is
                 * a pointer compare rather than a contents compare.
                 */
-               if (egid == KAUTH_UID_NONE && my_cred->cr_groups[0] != egid) {
+               if (egid != KAUTH_UID_NONE && my_pcred->cr_gid != egid) {
                        /* changing the effective GID */
                        new_egid = egid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
                }
-               if (rgid != KAUTH_UID_NONE && my_cred->cr_rgid != rgid) {
+               if (rgid != KAUTH_UID_NONE && my_pcred->cr_rgid != rgid) {
                        /* changing the real GID */
                        new_rgid = rgid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
                }
                /*
                 * If the newly requested real gid or effective gid does
@@ -1313,33 +1387,36 @@ setregid(proc_t p, struct setregid_args *uap, __unused register_t *retval)
                 * new effective gid.  We are protected from escalation
                 * by the prechecking.
                 */
-               if (my_cred->cr_svgid != uap->rgid &&
-                   my_cred->cr_svgid != uap->egid) {
+               if (my_pcred->cr_svgid != uap->rgid &&
+                   my_pcred->cr_svgid != uap->egid) {
                        svgid = new_egid;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag);
                }
 
                my_new_cred = kauth_cred_setresgid(my_cred, rgid, egid, svgid);
                if (my_cred != my_new_cred) {
 
-                       DEBUG_CRED_CHANGE("setregid(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
+                       DEBUG_CRED_CHANGE("setregid(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_pcred->cr_flags, my_new_cred, posix_cred_get(my_new_cred)->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /* need to protect for a race where another thread
                         * also changed the credential after we took our
                         * reference.  If p_ucred has changed then we
                         * should restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                /* try again */
                                my_cred = kauth_cred_proc_ref(p);
+                               my_pcred = posix_cred_get(my_cred);
                                continue;
                        }
                        p->p_ucred = my_new_cred;
-                       OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag); /* XXX redundant? */
-                       proc_unlock(p);
+                       /* update cred on proc */
+                       PROC_UPDATE_CREDS_ONPROC(p);
+                       OSBitOrAtomic(P_SUGID, &p->p_flag); /* XXX redundant? */
+                       proc_ucred_unlock(p);
                }
                break;
        }
@@ -1353,14 +1430,14 @@ setregid(proc_t p, struct setregid_args *uap, __unused register_t *retval)
 
 /*
  * Set the per-thread override identity.  The first parameter can be the
- * current real UID, KAUTH_UID_NONE, or, if the caller is priviledged, it
+ * current real UID, KAUTH_UID_NONE, or, if the caller is privileged, it
  * can be any UID.  If it is KAUTH_UID_NONE, then as a special case, this
  * means "revert to the per process credential"; otherwise, if permitted,
  * it changes the effective, real, and saved UIDs and GIDs for the current
  * thread to the requested UID and single GID, and clears all other GIDs.
  */
 int
-settid(proc_t p, struct settid_args *uap, __unused register_t *retval)
+settid(proc_t p, struct settid_args *uap, __unused int32_t *retval)
 {
        kauth_cred_t uc;
        struct uthread *uthread = get_bsdthread_info(current_thread());
@@ -1369,7 +1446,8 @@ settid(proc_t p, struct settid_args *uap, __unused register_t *retval)
 
        uid = uap->uid;
        gid = uap->gid;
-       AUDIT_ARG(uid, uid, gid, gid, 0);
+       AUDIT_ARG(uid, uid);
+       AUDIT_ARG(gid, gid);
 
        if (proc_suser(p) != 0) 
                return (EPERM);
@@ -1431,14 +1509,15 @@ settid(proc_t p, struct settid_args *uap, __unused register_t *retval)
  * When the assume argument is zero we revert back to our normal identity.
  */
 int
-settid_with_pid(proc_t p, struct settid_with_pid_args *uap, __unused register_t *retval)
+settid_with_pid(proc_t p, struct settid_with_pid_args *uap, __unused int32_t *retval)
 {
        proc_t target_proc;
        struct uthread *uthread = get_bsdthread_info(current_thread());
        kauth_cred_t my_cred, my_target_cred, my_new_cred;
+       posix_cred_t my_target_pcred;
 
        AUDIT_ARG(pid, uap->pid);
-       AUDIT_ARG(value, uap->assume);
+       AUDIT_ARG(value32, uap->assume);
 
        if (proc_suser(p) != 0) {
                return (EPERM);
@@ -1483,7 +1562,8 @@ settid_with_pid(proc_t p, struct settid_with_pid_args *uap, __unused register_t
                kauth_cred_ref(uthread->uu_ucred); 
                my_cred = uthread->uu_ucred;
                my_target_cred = kauth_cred_proc_ref(target_proc);
-               my_new_cred = kauth_cred_setuidgid(my_cred, my_target_cred->cr_uid, my_target_cred->cr_gid);
+               my_target_pcred = posix_cred_get(my_target_cred);
+               my_new_cred = kauth_cred_setuidgid(my_cred, my_target_pcred->cr_uid, my_target_pcred->cr_gid);
                if (my_cred != my_new_cred)
                        uthread->uu_ucred = my_new_cred;
        
@@ -1551,7 +1631,7 @@ settid_with_pid(proc_t p, struct settid_with_pid_args *uap, __unused register_t
  *             flag the process as having set privilege since the last exec.
  */
 static int
-setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused register_t *retval)
+setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused int32_t *retval)
 {
        u_int ngrp;
        gid_t   newgroups[NGROUPS] = { 0 };
@@ -1623,7 +1703,7 @@ setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused
 
                                DEBUG_CRED_CHANGE("setgroups1(CH)%d: %p/0x%08x->%p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
-                               proc_lock(p);
+                               proc_ucred_lock(p);
                                /*
                                 * We need to protect for a race where another
                                 * thread also changed the credential after we
@@ -1632,20 +1712,22 @@ setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused
                                 * with the new cred.
                                 */
                                if (p->p_ucred != my_cred) {
-                                       proc_unlock(p);
+                                       proc_ucred_unlock(p);
                                        kauth_cred_unref(&my_new_cred);
                                        my_cred = kauth_cred_proc_ref(p);
                                        /* try again */
                                        continue;
                                }
                                p->p_ucred = my_new_cred;
-                               OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
-                               proc_unlock(p);
+                               /* update cred on proc */
+                               PROC_UPDATE_CREDS_ONPROC(p);
+                               OSBitOrAtomic(P_SUGID, &p->p_flag);
+                               proc_ucred_unlock(p);
                        }
                        break;
                }
                /* Drop old proc reference or our extra reference */
-               AUDIT_ARG(groupset, my_cred->cr_groups, ngrp);
+               AUDIT_ARG(groupset, posix_cred_get(my_cred)->cr_groups, ngrp);
                kauth_cred_unref(&my_cred);
 
 
@@ -1686,7 +1768,7 @@ setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused
  * See also:   setgroups1()
  */
 int
-initgroups(proc_t p, struct initgroups_args *uap, __unused register_t *retval)
+initgroups(proc_t p, struct initgroups_args *uap, __unused int32_t *retval)
 {
        DEBUG_CRED_ENTER("initgroups\n");
 
@@ -1720,7 +1802,7 @@ initgroups(proc_t p, struct initgroups_args *uap, __unused register_t *retval)
  * See also:   setgroups1()
  */
 int
-setgroups(proc_t p, struct setgroups_args *uap, __unused register_t *retval)
+setgroups(proc_t p, struct setgroups_args *uap, __unused int32_t *retval)
 {
        DEBUG_CRED_ENTER("setgroups\n");
 
@@ -1730,20 +1812,26 @@ setgroups(proc_t p, struct setgroups_args *uap, __unused register_t *retval)
 
 /*
  * Set the per-thread/per-process supplementary groups list.
+ * 
+ * XXX implement setsgroups
+ *
  */
-#warning XXX implement setsgroups
+
 int
-setsgroups(__unused proc_t p, __unused struct setsgroups_args *uap, __unused register_t *retval)
+setsgroups(__unused proc_t p, __unused struct setsgroups_args *uap, __unused int32_t *retval)
 {
        return(ENOTSUP);
 }
 
 /*
  * Set the per-thread/per-process whiteout groups list.
+ * 
+ * XXX implement setwgroups
+ *
  */
-#warning XXX implement setwgroups
+
 int
-setwgroups(__unused proc_t p, __unused struct setwgroups_args *uap, __unused register_t *retval)
+setwgroups(__unused proc_t p, __unused struct setwgroups_args *uap, __unused int32_t *retval)
 {
        return(ENOTSUP);
 }
@@ -1796,45 +1884,6 @@ suser(kauth_cred_t cred, u_short *acflag)
 }
 
 
-/*
- * XXX This interface is going away; use kauth_cred_issuser() directly
- * XXX instead.
- */
-int
-is_suser(void)
-{
-       proc_t p = current_proc();
-
-       if (!p)
-               return (0);
-
-       return (proc_suser(p) == 0);
-}
-
-
-/*
- * XXX This interface is going away; use kauth_cred_issuser() directly
- * XXX instead.
- */
-int
-is_suser1(void)
-{
-       proc_t p = current_proc();
-       kauth_cred_t my_cred;
-       int err;
-
-       if (!p)
-               return (0);
-
-       my_cred = kauth_cred_proc_ref(p);
-
-       err =  (suser(my_cred, &p->p_acflag) == 0 ||
-                       my_cred->cr_ruid == 0 || my_cred->cr_svuid == 0);
-       kauth_cred_unref(&my_cred);
-       return(err);
-}
-
-
 /*
  * getlogin
  *
@@ -1859,7 +1908,7 @@ is_suser1(void)
  * XXX:                Belongs in kern_proc.c
  */
 int
-getlogin(proc_t p, struct getlogin_args *uap, __unused register_t *retval)
+getlogin(proc_t p, struct getlogin_args *uap, __unused int32_t *retval)
 {
        char buffer[MAXLOGNAME+1];
        struct session * sessp;
@@ -1899,10 +1948,10 @@ getlogin(proc_t p, struct getlogin_args *uap, __unused register_t *retval)
  * XXX:                Belongs in kern_proc.c
  */
 int
-setlogin(proc_t p, struct setlogin_args *uap, __unused register_t *retval)
+setlogin(proc_t p, struct setlogin_args *uap, __unused int32_t *retval)
 {
        int error;
-       int dummy=0;
+       size_t dummy=0;
        char buffer[MAXLOGNAME+1];
        struct session * sessp;
 
@@ -1941,11 +1990,25 @@ setlogin(proc_t p, struct setlogin_args *uap, __unused register_t *retval)
  */
 int
 set_security_token(proc_t p)
+{
+       return set_security_token_task_internal(p, p->task);
+}
+
+/*
+ * Set the secrity token of the task with current euid and eguid
+ * The function takes a proc and a task, where proc->task might point to a
+ * different task if called from exec.
+ */
+
+int
+set_security_token_task_internal(proc_t p, void *t)
 {
        security_token_t sec_token;
        audit_token_t    audit_token;
        kauth_cred_t my_cred;
+       posix_cred_t my_pcred;
        host_priv_t host_priv;
+       task_t task = t;
 
        /*
         * Don't allow a vfork child to override the parent's token settings
@@ -1953,7 +2016,7 @@ set_security_token(proc_t p)
         * suffer along using the parent's token until the exec().  It's all
         * undefined behavior anyway, right?
         */
-       if (p->task == current_task()) {
+       if (task == current_task()) {
                uthread_t        uthread;
                uthread = (uthread_t)get_bsdthread_info(current_thread());
                if (uthread->uu_flag & UT_VFORK)
@@ -1961,10 +2024,12 @@ set_security_token(proc_t p)
        }
                
        my_cred = kauth_cred_proc_ref(p);
+       my_pcred = posix_cred_get(my_cred);
+
        /* XXX mach_init doesn't have a p_ucred when it calls this function */
        if (IS_VALID_CRED(my_cred)) {
                sec_token.val[0] = kauth_cred_getuid(my_cred);
-               sec_token.val[1] = my_cred->cr_gid;
+               sec_token.val[1] = kauth_cred_getgid(my_cred);
        } else {
                sec_token.val[0] = 0;
                sec_token.val[1] = 0;
@@ -1979,19 +2044,15 @@ set_security_token(proc_t p)
         * the user of the trailer from future representation
         * changes.
         */
-       audit_token.val[0] = my_cred->cr_au.ai_auid;
-       audit_token.val[1] = my_cred->cr_uid;
-       audit_token.val[2] = my_cred->cr_gid;
-       audit_token.val[3] = my_cred->cr_ruid;
-       audit_token.val[4] = my_cred->cr_rgid;
+       audit_token.val[0] = my_cred->cr_audit.as_aia_p->ai_auid;
+       audit_token.val[1] = my_pcred->cr_uid;
+       audit_token.val[2] = my_pcred->cr_gid;
+       audit_token.val[3] = my_pcred->cr_ruid;
+       audit_token.val[4] = my_pcred->cr_rgid;
        audit_token.val[5] = p->p_pid;
-       audit_token.val[6] = my_cred->cr_au.ai_asid;
+       audit_token.val[6] = my_cred->cr_audit.as_aia_p->ai_asid;
        audit_token.val[7] = p->p_idversion;
 
-#if CONFIG_MACF_MACH
-       mac_task_label_update_cred(my_cred, p->task);
-#endif
-       
        host_priv = (sec_token.val[0]) ? HOST_PRIV_NULL : host_priv_self();
 #if CONFIG_MACF
        if (host_priv != HOST_PRIV_NULL && mac_system_check_host_priv(my_cred))
@@ -1999,14 +2060,33 @@ set_security_token(proc_t p)
 #endif
        kauth_cred_unref(&my_cred);
 
+#if DEVELOPMENT || DEBUG
+       /* 
+        * Update the pid an proc name for importance base if any
+        */
+       task_importance_update_owner_info(task);
+#endif
+
        return (host_security_set_task_token(host_security_self(),
-                                          p->task,
+                                          task,
                                           sec_token,
                                           audit_token,
                                           host_priv) != KERN_SUCCESS);
 }
 
 
+int get_audit_token_pid(audit_token_t *audit_token);
+
+int
+get_audit_token_pid(audit_token_t *audit_token)
+{
+       /* keep in-sync with set_security_token (above) */
+       if (audit_token)
+               return (int)audit_token->val[5];
+       return -1;
+}
+
+
 /*
  * Fill in a struct xucred based on a kauth_cred_t.
  */
@@ -2014,177 +2094,11 @@ __private_extern__
 void
 cru2x(kauth_cred_t cr, struct xucred *xcr)
 {
+       posix_cred_t pcr = posix_cred_get(cr);
 
        bzero(xcr, sizeof(*xcr));
        xcr->cr_version = XUCRED_VERSION;
        xcr->cr_uid = kauth_cred_getuid(cr);
-       xcr->cr_ngroups = cr->cr_ngroups;
-       bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups));
-}
-
-#if CONFIG_LCTX
-
-/*
- * Set Login Context ID
- */
-/*
- * MPSAFE - assignment of (visible) process to context protected by ALLLCTX_LOCK,
- *         LCTX by its own locks.
- */
-int
-setlcid(proc_t p0, struct setlcid_args *uap, __unused register_t *retval)
-{
-       proc_t p;
-       struct lctx *l;
-       int error = 0;
-       int refheld = 0;
-
-       AUDIT_ARG(pid, uap->pid);
-       AUDIT_ARG(value, uap->lcid);
-       if (uap->pid == LCID_PROC_SELF) {       /* Create/Join/Leave */
-               p = p0;
-       } else {                                /* Adopt/Orphan */
-               p = proc_find(uap->pid);
-               if (p == NULL)
-                       return (ESRCH);
-               refheld = 1;
-       }
-
-#if CONFIG_MACF
-       error = mac_proc_check_setlcid(p0, p, uap->pid, uap->lcid);
-       if (error)
-               goto out;
-#endif
-
-       switch (uap->lcid) {
-       /* Leave/Orphan */
-       case LCID_REMOVE:
-
-               /* Only root may Leave/Orphan. */
-               if (!is_suser1()) {
-                       error = EPERM;
-                       goto out;
-               }
-
-               /* Process not in login context. */
-               if (p->p_lctx == NULL) {
-                       error = ENOATTR;
-                       goto out;
-               }
-
-               l = NULL;
-
-               break;
-
-       /* Create */
-       case LCID_CREATE:
-
-               /* Create only valid for self! */
-               if (uap->pid != LCID_PROC_SELF) {
-                       error = EPERM;
-                       goto out;
-               }
-
-               /* Already in a login context. */
-               if (p->p_lctx != NULL) {
-                       error = EPERM;
-                       goto out;
-               }
-
-               l = lccreate();
-               if (l == NULL) {
-                       error = ENOMEM;
-                       goto out;
-               }
-
-               LCTX_LOCK(l);
-
-               break;
-
-       /* Join/Adopt */
-       default:
-
-               /* Only root may Join/Adopt. */
-               if (!is_suser1()) {
-                       error = EPERM;
-                       goto out;
-               }
-
-               l = lcfind(uap->lcid);
-               if (l == NULL) {
-                       error = ENOATTR;
-                       goto out;
-               }
-
-               break;
-       }
-
-       ALLLCTX_LOCK;
-       leavelctx(p);
-       enterlctx(p, l, (uap->lcid == LCID_CREATE) ? 1 : 0);
-       ALLLCTX_UNLOCK;
-
-out:
-       if (refheld != 0)
-               proc_rele(p);
-       return (error);
-}
-
-/*
- * Get Login Context ID
- */
-/*
- * MPSAFE - membership of (visible) process in a login context
- *         protected by the all-context lock.
- */
-int
-getlcid(proc_t p0, struct getlcid_args *uap, register_t *retval)
-{
-       proc_t p;
-       int error = 0;
-       int refheld = 0;
-
-       AUDIT_ARG(pid, uap->pid);
-       if (uap->pid == LCID_PROC_SELF) {
-               p = p0;
-       } else {
-               p = proc_find(uap->pid);
-               if (p == NULL)
-                       return (ESRCH);
-               refheld = 1;
-       }
-
-#if CONFIG_MACF
-       error = mac_proc_check_getlcid(p0, p, uap->pid);
-       if (error)
-               goto out;
-#endif
-       ALLLCTX_LOCK;
-       if (p->p_lctx == NULL) {
-               error = ENOATTR;
-               ALLLCTX_UNLOCK;
-               goto out;
-       }
-       *retval = p->p_lctx->lc_id;
-       ALLLCTX_UNLOCK;
- out:
-       if (refheld != 0)
-               proc_rele(p);
-
-       return (error);
-}
-#else  /* LCTX */
-int
-setlcid(proc_t p0, struct setlcid_args *uap, register_t *retval)
-{
-
-       return (ENOSYS);
-}
-
-int
-getlcid(proc_t p0, struct getlcid_args *uap, register_t *retval)
-{
-
-       return (ENOSYS);
+       xcr->cr_ngroups = pcr->cr_ngroups;
+       bcopy(pcr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups));
 }
-#endif /* !LCTX */