]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_persona.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / kern / kern_persona.c
index e05e8d4249cc4c1d4ee8085a8f307f3d39fcda30..b3470216aefda293a309c0a2843dfb57e2c62e66 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * Copyright (c) 2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <sys/kernel.h>
 #include <sys/kernel_types.h>
 #include <sys/persona.h>
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <sys/kernel.h>
 #include <sys/kernel_types.h>
 #include <sys/persona.h>
+#include <pexpert/pexpert.h>
 
 #if CONFIG_PERSONAS
 
 #if CONFIG_PERSONAS
+#include <machine/atomic.h>
+
 #include <kern/assert.h>
 #include <kern/simple_lock.h>
 #include <kern/task.h>
 #include <kern/zalloc.h>
 #include <kern/assert.h>
 #include <kern/simple_lock.h>
 #include <kern/task.h>
 #include <kern/zalloc.h>
+#include <mach/thread_act.h>
+#include <kern/thread.h>
 
 #include <sys/param.h>
 #include <sys/proc_internal.h>
 
 #include <sys/param.h>
 #include <sys/proc_internal.h>
@@ -52,9 +57,6 @@
 #define FIRST_PERSONA_ID 501
 #define PERSONA_ID_STEP   10
 
 #define FIRST_PERSONA_ID 501
 #define PERSONA_ID_STEP   10
 
-#define PERSONA_SYSTEM_UID    ((uid_t)99)
-#define PERSONA_SYSTEM_LOGIN  "system"
-
 #define PERSONA_ALLOC_TOKEN   (0x7a0000ae)
 #define PERSONA_INIT_TOKEN    (0x7500005e)
 #define PERSONA_MAGIC         (0x0aa55aa0)
 #define PERSONA_ALLOC_TOKEN   (0x7a0000ae)
 #define PERSONA_INIT_TOKEN    (0x7500005e)
 #define PERSONA_MAGIC         (0x0aa55aa0)
 
 static LIST_HEAD(personalist, persona) all_personas;
 static uint32_t g_total_personas;
 
 static LIST_HEAD(personalist, persona) all_personas;
 static uint32_t g_total_personas;
-uint32_t g_max_personas = MAX_PERSONAS;
-
-struct persona *g_system_persona = NULL;
+const uint32_t g_max_personas = MAX_PERSONAS;
+struct persona *system_persona = NULL;
+struct persona *proxy_system_persona = NULL;
+#if !defined(XNU_TARGET_OS_OSX)
+int unique_persona = 1;
+#else
+int unique_persona = 0;
+#endif
 
 static uid_t g_next_persona_id;
 
 
 static uid_t g_next_persona_id;
 
-lck_mtx_t all_personas_lock;
-lck_attr_t *persona_lck_attr;
-lck_grp_t *persona_lck_grp;
-lck_grp_attr_t *persona_lck_grp_attr;
+LCK_GRP_DECLARE(persona_lck_grp, "personas");
+LCK_MTX_DECLARE(all_personas_lock, &persona_lck_grp);
 
 os_refgrp_decl(static, persona_refgrp, "persona", NULL);
 
 
 os_refgrp_decl(static, persona_refgrp, "persona", NULL);
 
-static zone_t persona_zone;
+static ZONE_DECLARE(persona_zone, "personas", sizeof(struct persona), ZC_ZFREE_CLEARMEM);
 
 kauth_cred_t g_default_persona_cred;
 
 kauth_cred_t g_default_persona_cred;
+extern struct auditinfo_addr * const audit_default_aia_p;
 
 #define lock_personas()    lck_mtx_lock(&all_personas_lock)
 #define unlock_personas()  lck_mtx_unlock(&all_personas_lock)
 
 
 #define lock_personas()    lck_mtx_lock(&all_personas_lock)
 #define unlock_personas()  lck_mtx_unlock(&all_personas_lock)
 
-
 extern void mach_kauth_cred_uthread_update(void);
 
 extern void mach_kauth_cred_uthread_update(void);
 
-void personas_bootstrap(void)
+extern kern_return_t bank_get_bank_ledger_thread_group_and_persona(void *voucher,
+    void *bankledger, void **banktg, uint32_t *persona_id);
+void
+ipc_voucher_release(void *voucher);
+
+void
+personas_bootstrap(void)
 {
        struct posix_cred pcred;
 {
        struct posix_cred pcred;
+       int unique_persona_bootarg;
 
        persona_dbg("Initializing persona subsystem");
        LIST_INIT(&all_personas);
 
        persona_dbg("Initializing persona subsystem");
        LIST_INIT(&all_personas);
@@ -97,19 +109,6 @@ void personas_bootstrap(void)
 
        g_next_persona_id = FIRST_PERSONA_ID;
 
 
        g_next_persona_id = FIRST_PERSONA_ID;
 
-       persona_lck_grp_attr = lck_grp_attr_alloc_init();
-       lck_grp_attr_setstat(persona_lck_grp_attr);
-
-       persona_lck_grp = lck_grp_alloc_init("personas", persona_lck_grp_attr);
-       persona_lck_attr = lck_attr_alloc_init();
-
-       lck_mtx_init(&all_personas_lock, persona_lck_grp, persona_lck_attr);
-
-       persona_zone = zinit(sizeof(struct persona),
-                            MAX_PERSONAS * sizeof(struct persona),
-                            MAX_PERSONAS, "personas");
-       assert(persona_zone != NULL);
-
        /*
         * setup the default credentials that a persona temporarily
         * inherits (to work around kauth APIs)
        /*
         * setup the default credentials that a persona temporarily
         * inherits (to work around kauth APIs)
@@ -123,60 +122,62 @@ void personas_bootstrap(void)
        pcred.cr_gmuid = KAUTH_UID_NONE;
 
        g_default_persona_cred = posix_cred_create(&pcred);
        pcred.cr_gmuid = KAUTH_UID_NONE;
 
        g_default_persona_cred = posix_cred_create(&pcred);
-       if (!g_default_persona_cred)
+       if (!g_default_persona_cred) {
                panic("couldn't create default persona credentials!");
                panic("couldn't create default persona credentials!");
-
-       g_system_persona = persona_alloc(PERSONA_SYSTEM_UID,
-                                        PERSONA_SYSTEM_LOGIN,
-                                        PERSONA_SYSTEM, NULL);
-       int err = persona_init_begin(g_system_persona);
-       assert(err == 0);
-
-       persona_init_end(g_system_persona, err);
-
-       assert(g_system_persona != NULL);
+       }
+#if CONFIG_AUDIT
+       /* posix_cred_create() sets this value to NULL */
+       g_default_persona_cred->cr_audit.as_aia_p = audit_default_aia_p;
+#endif
+       if (PE_parse_boot_argn("unique_persona", &unique_persona_bootarg, sizeof(unique_persona_bootarg))) {
+               unique_persona = !!unique_persona_bootarg;
+       }
 }
 
 }
 
-struct persona *persona_alloc(uid_t id, const char *login, int type, int *error)
+struct persona *
+persona_alloc(uid_t id, const char *login, persona_type_t type, char *path, int *error)
 {
        struct persona *persona;
        int err = 0;
 
        if (!login) {
                pna_err("Must provide a login name for a new persona!");
 {
        struct persona *persona;
        int err = 0;
 
        if (!login) {
                pna_err("Must provide a login name for a new persona!");
-               if (error)
+               if (error) {
                        *error = EINVAL;
                        *error = EINVAL;
+               }
                return NULL;
        }
 
        if (type <= PERSONA_INVALID || type > PERSONA_TYPE_MAX) {
                pna_err("Invalid type: %d", type);
                return NULL;
        }
 
        if (type <= PERSONA_INVALID || type > PERSONA_TYPE_MAX) {
                pna_err("Invalid type: %d", type);
-               if (error)
+               if (error) {
                        *error = EINVAL;
                        *error = EINVAL;
+               }
                return NULL;
        }
 
        persona = (struct persona *)zalloc(persona_zone);
        if (!persona) {
                return NULL;
        }
 
        persona = (struct persona *)zalloc(persona_zone);
        if (!persona) {
-               if (error)
+               if (error) {
                        *error = ENOMEM;
                        *error = ENOMEM;
+               }
                return NULL;
        }
 
        bzero(persona, sizeof(*persona));
 
                return NULL;
        }
 
        bzero(persona, sizeof(*persona));
 
-       if (hw_atomic_add(&g_total_personas, 1) > MAX_PERSONAS) {
+       if (os_atomic_inc(&g_total_personas, relaxed) > MAX_PERSONAS) {
                /* too many personas! */
                pna_err("too many active personas!");
                err = EBUSY;
                goto out_error;
        }
 
                /* too many personas! */
                pna_err("too many active personas!");
                err = EBUSY;
                goto out_error;
        }
 
-       strncpy(persona->pna_login, login, sizeof(persona->pna_login)-1);
+       strncpy(persona->pna_login, login, sizeof(persona->pna_login) - 1);
        persona_dbg("Starting persona allocation for: '%s'", persona->pna_login);
 
        LIST_INIT(&persona->pna_members);
        persona_dbg("Starting persona allocation for: '%s'", persona->pna_login);
 
        LIST_INIT(&persona->pna_members);
-       lck_mtx_init(&persona->pna_lock, persona_lck_grp, persona_lck_attr);
+       lck_mtx_init(&persona->pna_lock, &persona_lck_grp, LCK_ATTR_NULL);
        os_ref_init(&persona->pna_refcount, &persona_refgrp);
 
        /*
        os_ref_init(&persona->pna_refcount, &persona_refgrp);
 
        /*
@@ -194,6 +195,7 @@ struct persona *persona_alloc(uid_t id, const char *login, int type, int *error)
        persona->pna_type = type;
        persona->pna_id = id;
        persona->pna_valid = PERSONA_ALLOC_TOKEN;
        persona->pna_type = type;
        persona->pna_id = id;
        persona->pna_valid = PERSONA_ALLOC_TOKEN;
+       persona->pna_path = path;
 
        /*
         * NOTE: this persona has not been fully initialized. A subsequent
 
        /*
         * NOTE: this persona has not been fully initialized. A subsequent
@@ -206,7 +208,7 @@ struct persona *persona_alloc(uid_t id, const char *login, int type, int *error)
        return persona;
 
 out_error:
        return persona;
 
 out_error:
-       (void)hw_atomic_add(&g_total_personas, -1);
+       os_atomic_dec(&g_total_personas, relaxed);
        zfree(persona_zone, persona);
        if (error) {
                *error = err;
        zfree(persona_zone, persona);
        if (error) {
                *error = err;
@@ -224,13 +226,14 @@ out_error:
  * structure as valid
  *
  * Conditions:
  * structure as valid
  *
  * Conditions:
- *     persona has been allocated via persona_alloc()
- *     nothing locked
+ *      persona has been allocated via persona_alloc()
+ *      nothing locked
  *
  * Returns:
  *
  * Returns:
- *     global persona list is locked (even on error)
+ *      global persona list is locked (even on error)
  */
  */
-int persona_init_begin(struct persona *persona)
+int
+persona_init_begin(struct persona *persona)
 {
        struct persona *tmp;
        int err = 0;
 {
        struct persona *tmp;
        int err = 0;
@@ -246,8 +249,9 @@ int persona_init_begin(struct persona *persona)
 
        lock_personas();
 try_again:
 
        lock_personas();
 try_again:
-       if (id == PERSONA_ID_NONE)
+       if (id == PERSONA_ID_NONE) {
                persona->pna_id = g_next_persona_id;
                persona->pna_id = g_next_persona_id;
+       }
 
        persona_dbg("Beginning Initialization of %d:%d (%s)...", id, persona->pna_id, persona->pna_login);
 
 
        persona_dbg("Beginning Initialization of %d:%d (%s)...", id, persona->pna_id, persona->pna_login);
 
@@ -275,17 +279,19 @@ try_again:
                }
                persona_unlock(tmp);
        }
                }
                persona_unlock(tmp);
        }
-       if (err)
+       if (err) {
                goto out;
                goto out;
+       }
 
        /* ensure the cred has proper UID/GID defaults */
        kauth_cred_ref(persona->pna_cred);
        tmp_cred = kauth_cred_setuidgid(persona->pna_cred,
 
        /* ensure the cred has proper UID/GID defaults */
        kauth_cred_ref(persona->pna_cred);
        tmp_cred = kauth_cred_setuidgid(persona->pna_cred,
-                                       persona->pna_id,
-                                       persona->pna_id);
+           persona->pna_id,
+           persona->pna_id);
        kauth_cred_unref(&persona->pna_cred);
        kauth_cred_unref(&persona->pna_cred);
-       if (tmp_cred != persona->pna_cred)
+       if (tmp_cred != persona->pna_cred) {
                persona->pna_cred = tmp_cred;
                persona->pna_cred = tmp_cred;
+       }
 
        if (!persona->pna_cred) {
                err = EACCES;
 
        if (!persona->pna_cred) {
                err = EACCES;
@@ -298,10 +304,11 @@ try_again:
        kauth_cred_ref(persona->pna_cred);
        /* opt _out_ of memberd as a default */
        tmp_cred = kauth_cred_setgroups(persona->pna_cred,
        kauth_cred_ref(persona->pna_cred);
        /* opt _out_ of memberd as a default */
        tmp_cred = kauth_cred_setgroups(persona->pna_cred,
-                                       &new_group, 1, KAUTH_UID_NONE);
+           &new_group, 1, KAUTH_UID_NONE);
        kauth_cred_unref(&persona->pna_cred);
        kauth_cred_unref(&persona->pna_cred);
-       if (tmp_cred != persona->pna_cred)
+       if (tmp_cred != persona->pna_cred) {
                persona->pna_cred = tmp_cred;
                persona->pna_cred = tmp_cred;
+       }
 
        if (!persona->pna_cred) {
                err = EACCES;
 
        if (!persona->pna_cred) {
                err = EACCES;
@@ -309,8 +316,9 @@ try_again:
        }
 
        /* if the kernel supplied the persona ID, increment for next time */
        }
 
        /* if the kernel supplied the persona ID, increment for next time */
-       if (id == PERSONA_ID_NONE)
+       if (id == PERSONA_ID_NONE) {
                g_next_persona_id += PERSONA_ID_STEP;
                g_next_persona_id += PERSONA_ID_STEP;
+       }
 
        persona->pna_valid = PERSONA_INIT_TOKEN;
 
 
        persona->pna_valid = PERSONA_INIT_TOKEN;
 
@@ -340,13 +348,14 @@ out:
  * only mark the persona valid if the input parameter 'error' is 0.
  *
  * Conditions:
  * only mark the persona valid if the input parameter 'error' is 0.
  *
  * Conditions:
- *     persona is initialized via persona_init_begin()
- *     global persona list is locked via lock_personas()
+ *      persona is initialized via persona_init_begin()
+ *      global persona list is locked via lock_personas()
  *
  * Returns:
  *
  * Returns:
- *     global persona list is unlocked
+ *      global persona list is unlocked
  */
  */
-void persona_init_end(struct persona *persona, int error)
+void
+persona_init_end(struct persona *persona, int error)
 {
        if (persona == NULL) {
                return;
 {
        if (persona == NULL) {
                return;
@@ -363,9 +372,9 @@ void persona_init_end(struct persona *persona, int error)
        if (error != 0 || persona->pna_valid == PERSONA_ALLOC_TOKEN) {
                persona_dbg("ERROR:%d after initialization of %d (%s)", error, persona->pna_id, persona->pna_login);
                /* remove this persona from the global count */
        if (error != 0 || persona->pna_valid == PERSONA_ALLOC_TOKEN) {
                persona_dbg("ERROR:%d after initialization of %d (%s)", error, persona->pna_id, persona->pna_login);
                /* remove this persona from the global count */
-               (void)hw_atomic_add(&g_total_personas, -1);
+               os_atomic_dec(&g_total_personas, relaxed);
        } else if (error == 0 &&
        } else if (error == 0 &&
-                  persona->pna_valid == PERSONA_INIT_TOKEN) {
+           persona->pna_valid == PERSONA_INIT_TOKEN) {
                persona->pna_valid = PERSONA_MAGIC;
                LIST_INSERT_HEAD(&all_personas, persona, pna_list);
                persona_dbg("Initialization of %d (%s) Complete.", persona->pna_id, persona->pna_login);
                persona->pna_valid = PERSONA_MAGIC;
                LIST_INSERT_HEAD(&all_personas, persona, pna_list);
                persona_dbg("Initialization of %d (%s) Complete.", persona->pna_id, persona->pna_login);
@@ -374,17 +383,90 @@ void persona_init_end(struct persona *persona, int error)
        unlock_personas();
 }
 
        unlock_personas();
 }
 
-static struct persona *persona_get_locked(struct persona *persona)
+/**
+ * persona_verify_and_set_uniqueness
+ *
+ * This function checks the persona, if the one being spawned is of type
+ * PERSONA_SYSTEM or PERSONA_SYSTEM_PROXY, is unique.
+ *
+ * Conditions:
+ *      global persona list is locked on entry and return.
+ *
+ * Returns:
+ *      EEXIST: if persona is system/system-proxy and is not unique.
+ *      0: Otherwise.
+ */
+int
+persona_verify_and_set_uniqueness(struct persona *persona)
+{
+       if (persona == NULL) {
+               return EINVAL;
+       }
+
+       if (!unique_persona) {
+               return 0;
+       }
+
+       if (persona->pna_type == PERSONA_SYSTEM) {
+               if (system_persona != NULL) {
+                       return EEXIST;
+               }
+               system_persona = persona;
+               return 0;
+       }
+
+       if (persona->pna_type == PERSONA_SYSTEM_PROXY) {
+               if (proxy_system_persona != NULL) {
+                       return EEXIST;
+               }
+               proxy_system_persona = persona;
+               return 0;
+       }
+       return 0;
+}
+
+/**
+ * persona_is_unique
+ *
+ * This function checks if the persona spawned is unique.
+ *
+ * Returns:
+ *      TRUE: if unique.
+ *      FALSE: otherwise.
+ */
+boolean_t
+persona_is_unique(struct persona *persona)
+{
+       if (persona == NULL) {
+               return FALSE;
+       }
+
+       if (!unique_persona) {
+               return FALSE;
+       }
+
+       if (persona->pna_type == PERSONA_SYSTEM ||
+           persona->pna_type == PERSONA_SYSTEM_PROXY) {
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static struct persona *
+persona_get_locked(struct persona *persona)
 {
        os_ref_retain_locked(&persona->pna_refcount);
        return persona;
 }
 
 {
        os_ref_retain_locked(&persona->pna_refcount);
        return persona;
 }
 
-struct persona *persona_get(struct persona *persona)
+struct persona *
+persona_get(struct persona *persona)
 {
        struct persona *ret;
 {
        struct persona *ret;
-       if (!persona)
+       if (!persona) {
                return NULL;
                return NULL;
+       }
        persona_lock(persona);
        ret = persona_get_locked(persona);
        persona_unlock(persona);
        persona_lock(persona);
        ret = persona_get_locked(persona);
        persona_unlock(persona);
@@ -392,12 +474,14 @@ struct persona *persona_get(struct persona *persona)
        return ret;
 }
 
        return ret;
 }
 
-void persona_put(struct persona *persona)
+void
+persona_put(struct persona *persona)
 {
        int destroy = 0;
 
 {
        int destroy = 0;
 
-       if (!persona)
+       if (!persona) {
                return;
                return;
+       }
 
        persona_lock(persona);
        if (os_ref_release_locked(&persona->pna_refcount) == 0) {
 
        persona_lock(persona);
        if (os_ref_release_locked(&persona->pna_refcount) == 0) {
@@ -405,24 +489,30 @@ void persona_put(struct persona *persona)
        }
        persona_unlock(persona);
 
        }
        persona_unlock(persona);
 
-       if (!destroy)
+       if (!destroy) {
                return;
                return;
+       }
 
        persona_dbg("Destroying persona %s", persona_desc(persona, 0));
 
        /* release our credential reference */
 
        persona_dbg("Destroying persona %s", persona_desc(persona, 0));
 
        /* release our credential reference */
-       if (persona->pna_cred)
+       if (persona->pna_cred) {
                kauth_cred_unref(&persona->pna_cred);
                kauth_cred_unref(&persona->pna_cred);
+       }
 
        /* remove it from the global list and decrement the count */
        lock_personas();
        persona_lock(persona);
        if (persona_valid(persona)) {
                LIST_REMOVE(persona, pna_list);
 
        /* remove it from the global list and decrement the count */
        lock_personas();
        persona_lock(persona);
        if (persona_valid(persona)) {
                LIST_REMOVE(persona, pna_list);
-               if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX)
+               if (os_atomic_dec_orig(&g_total_personas, relaxed) == 0) {
                        panic("persona count underflow!\n");
                        panic("persona count underflow!\n");
+               }
                persona_mkinvalid(persona);
        }
                persona_mkinvalid(persona);
        }
+       if (persona->pna_path != NULL) {
+               zfree(ZV_NAMEI, persona->pna_path);
+       }
        persona_unlock(persona);
        unlock_personas();
 
        persona_unlock(persona);
        unlock_personas();
 
@@ -431,14 +521,17 @@ void persona_put(struct persona *persona)
        zfree(persona_zone, persona);
 }
 
        zfree(persona_zone, persona);
 }
 
-uid_t persona_get_id(struct persona *persona)
+uid_t
+persona_get_id(struct persona *persona)
 {
 {
-       if (persona)
+       if (persona) {
                return persona->pna_id;
                return persona->pna_id;
+       }
        return PERSONA_ID_NONE;
 }
 
        return PERSONA_ID_NONE;
 }
 
-struct persona *persona_lookup(uid_t id)
+struct persona *
+persona_lookup(uid_t id)
 {
        struct persona *persona, *tmp;
 
 {
        struct persona *persona, *tmp;
 
@@ -463,7 +556,8 @@ struct persona *persona_lookup(uid_t id)
        return persona;
 }
 
        return persona;
 }
 
-struct persona *persona_lookup_and_invalidate(uid_t id)
+struct persona *
+persona_lookup_and_invalidate(uid_t id)
 {
        struct persona *persona, *entry, *tmp;
 
 {
        struct persona *persona, *entry, *tmp;
 
@@ -473,12 +567,13 @@ struct persona *persona_lookup_and_invalidate(uid_t id)
        LIST_FOREACH_SAFE(entry, &all_personas, pna_list, tmp) {
                persona_lock(entry);
                if (entry->pna_id == id) {
        LIST_FOREACH_SAFE(entry, &all_personas, pna_list, tmp) {
                persona_lock(entry);
                if (entry->pna_id == id) {
-                       if (persona_valid(entry)) {
+                       if (persona_valid(entry) && !persona_is_unique(entry)) {
                                persona = persona_get_locked(entry);
                                assert(persona != NULL);
                                LIST_REMOVE(persona, pna_list);
                                persona = persona_get_locked(entry);
                                assert(persona != NULL);
                                LIST_REMOVE(persona, pna_list);
-                               if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX)
+                               if (os_atomic_dec_orig(&g_total_personas, relaxed) == 0) {
                                        panic("persona ref count underflow!\n");
                                        panic("persona ref count underflow!\n");
+                               }
                                persona_mkinvalid(persona);
                        }
                        persona_unlock(entry);
                                persona_mkinvalid(persona);
                        }
                        persona_unlock(entry);
@@ -491,59 +586,91 @@ struct persona *persona_lookup_and_invalidate(uid_t id)
        return persona;
 }
 
        return persona;
 }
 
-int persona_find(const char *login, uid_t uid,
-                struct persona **persona, size_t *plen)
+int
+persona_find_by_type(persona_type_t persona_type, struct persona **persona, size_t *plen)
+{
+       return persona_find_all(NULL, PERSONA_ID_NONE, persona_type, persona, plen);
+}
+
+int
+persona_find(const char *login, uid_t uid,
+    struct persona **persona, size_t *plen)
+{
+       return persona_find_all(login, uid, PERSONA_INVALID, persona, plen);
+}
+
+int
+persona_find_all(const char *login, uid_t uid, persona_type_t persona_type,
+    struct persona **persona, size_t *plen)
 {
        struct persona *tmp;
        int match = 0;
        size_t found = 0;
 
 {
        struct persona *tmp;
        int match = 0;
        size_t found = 0;
 
-       if (login)
+       if (login) {
                match++;
                match++;
-       if (uid != PERSONA_ID_NONE)
+       }
+       if (uid != PERSONA_ID_NONE) {
+               match++;
+       }
+       if ((persona_type > PERSONA_INVALID) && (persona_type <= PERSONA_TYPE_MAX)) {
                match++;
                match++;
+       } else if (persona_type != PERSONA_INVALID) {
+               return EINVAL;
+       }
 
 
-       if (match == 0)
+       if (match == 0) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_dbg("Searching with %d parameters (l:\"%s\", u:%d)",
 
        persona_dbg("Searching with %d parameters (l:\"%s\", u:%d)",
-                   match, login, uid);
+           match, login, uid);
 
        lock_personas();
        LIST_FOREACH(tmp, &all_personas, pna_list) {
                int m = 0;
                persona_lock(tmp);
 
        lock_personas();
        LIST_FOREACH(tmp, &all_personas, pna_list) {
                int m = 0;
                persona_lock(tmp);
-               if (login && strncmp(tmp->pna_login, login, sizeof(tmp->pna_login)) == 0)
+               if (login && strncmp(tmp->pna_login, login, sizeof(tmp->pna_login)) == 0) {
                        m++;
                        m++;
-               if (uid != PERSONA_ID_NONE && uid == tmp->pna_id)
+               }
+               if (uid != PERSONA_ID_NONE && uid == tmp->pna_id) {
                        m++;
                        m++;
+               }
+               if (persona_type != PERSONA_INVALID && persona_type == tmp->pna_type) {
+                       m++;
+               }
                if (m == match) {
                if (m == match) {
-                       if (persona && *plen > found)
+                       if (persona && *plen > found) {
                                persona[found] = persona_get_locked(tmp);
                                persona[found] = persona_get_locked(tmp);
+                       }
                        found++;
                }
 #ifdef PERSONA_DEBUG
                        found++;
                }
 #ifdef PERSONA_DEBUG
-               if (m > 0)
+               if (m > 0) {
                        persona_dbg("ID:%d Matched %d/%d, found:%d, *plen:%d",
                        persona_dbg("ID:%d Matched %d/%d, found:%d, *plen:%d",
-                                   tmp->pna_id, m, match, (int)found, (int)*plen);
+                           tmp->pna_id, m, match, (int)found, (int)*plen);
+               }
 #endif
                persona_unlock(tmp);
        }
        unlock_personas();
 
        *plen = found;
 #endif
                persona_unlock(tmp);
        }
        unlock_personas();
 
        *plen = found;
-       if (!found)
+       if (!found) {
                return ESRCH;
                return ESRCH;
+       }
        return 0;
 }
 
        return 0;
 }
 
-struct persona *persona_proc_get(pid_t pid)
+struct persona *
+persona_proc_get(pid_t pid)
 {
        struct persona *persona;
        proc_t p = proc_find(pid);
 
 {
        struct persona *persona;
        proc_t p = proc_find(pid);
 
-       if (!p)
+       if (!p) {
                return NULL;
                return NULL;
+       }
 
        proc_lock(p);
        persona = persona_get(p->p_persona);
 
        proc_lock(p);
        persona = persona_get(p->p_persona);
@@ -554,44 +681,65 @@ struct persona *persona_proc_get(pid_t pid)
        return persona;
 }
 
        return persona;
 }
 
-struct persona *current_persona_get(void)
+struct persona *
+current_persona_get(void)
 {
 {
-       proc_t p = current_proc();
-       struct persona *persona;
-
-       proc_lock(p);
-       persona = persona_get(p->p_persona);
-       proc_unlock(p);
+       struct persona *persona = NULL;
+       uid_t current_persona_id = PERSONA_ID_NONE;
+       ipc_voucher_t voucher;
 
 
+       thread_get_mach_voucher(current_thread(), 0, &voucher);
+       /* returns a voucher ref */
+       if (voucher != IPC_VOUCHER_NULL) {
+               /*
+                * If the voucher doesn't contain a bank attribute, it uses
+                * the default bank task value to determine the persona id
+                * which is the same as the proc's persona id
+                */
+               bank_get_bank_ledger_thread_group_and_persona(voucher, NULL,
+                   NULL, &current_persona_id);
+               ipc_voucher_release(voucher);
+               persona = persona_lookup(current_persona_id);
+       } else {
+               /* Fallback - get the proc's persona */
+               proc_t p = current_proc();
+               proc_lock(p);
+               persona = persona_get(p->p_persona);
+               proc_unlock(p);
+       }
        return persona;
 }
 
 /**
  * inherit a persona from parent to child
  */
        return persona;
 }
 
 /**
  * inherit a persona from parent to child
  */
-int persona_proc_inherit(proc_t child, proc_t parent)
+int
+persona_proc_inherit(proc_t child, proc_t parent)
 {
        if (child->p_persona != NULL) {
                persona_dbg("proc_inherit: child already in persona: %s",
 {
        if (child->p_persona != NULL) {
                persona_dbg("proc_inherit: child already in persona: %s",
-                           persona_desc(child->p_persona, 0));
+                   persona_desc(child->p_persona, 0));
                return -1;
        }
 
        /* no persona to inherit */
                return -1;
        }
 
        /* no persona to inherit */
-       if (parent->p_persona == NULL)
+       if (parent->p_persona == NULL) {
                return 0;
                return 0;
+       }
 
        return persona_proc_adopt(child, parent->p_persona, parent->p_ucred);
 }
 
 
        return persona_proc_adopt(child, parent->p_persona, parent->p_ucred);
 }
 
-int persona_proc_adopt_id(proc_t p, uid_t id, kauth_cred_t auth_override)
+int
+persona_proc_adopt_id(proc_t p, uid_t id, kauth_cred_t auth_override)
 {
        int ret;
        struct persona *persona;
 
        persona = persona_lookup(id);
 {
        int ret;
        struct persona *persona;
 
        persona = persona_lookup(id);
-       if (!persona)
+       if (!persona) {
                return ESRCH;
                return ESRCH;
+       }
 
        ret = persona_proc_adopt(p, persona, auth_override);
 
 
        ret = persona_proc_adopt(p, persona, auth_override);
 
@@ -611,9 +759,10 @@ typedef enum e_persona_reset_op {
  * internal cleanup routine for proc_set_cred_internal
  *
  */
  * internal cleanup routine for proc_set_cred_internal
  *
  */
-static struct persona *proc_reset_persona_internal(proc_t p, persona_reset_op_t op,
-                                                  struct persona *old_persona,
-                                                  struct persona *new_persona)
+static struct persona *
+proc_reset_persona_internal(proc_t p, persona_reset_op_t op,
+    struct persona *old_persona,
+    struct persona *new_persona)
 {
 #if (DEVELOPMENT || DEBUG)
        persona_lock_assert_held(new_persona);
 {
 #if (DEVELOPMENT || DEBUG)
        persona_lock_assert_held(new_persona);
@@ -622,7 +771,7 @@ static struct persona *proc_reset_persona_internal(proc_t p, persona_reset_op_t
        switch (op) {
        case PROC_REMOVE_PERSONA:
                old_persona = p->p_persona;
        switch (op) {
        case PROC_REMOVE_PERSONA:
                old_persona = p->p_persona;
-               /* fall through */
+               OS_FALLTHROUGH;
        case PROC_RESET_OLD_PERSONA:
                break;
        default:
        case PROC_RESET_OLD_PERSONA:
                break;
        default:
@@ -633,6 +782,7 @@ static struct persona *proc_reset_persona_internal(proc_t p, persona_reset_op_t
        /* unlock the new persona (locked on entry) */
        persona_unlock(new_persona);
        /* lock the old persona and the process */
        /* unlock the new persona (locked on entry) */
        persona_unlock(new_persona);
        /* lock the old persona and the process */
+       assert(old_persona != NULL);
        persona_lock(old_persona);
        proc_lock(p);
 
        persona_lock(old_persona);
        proc_lock(p);
 
@@ -661,25 +811,28 @@ static struct persona *proc_reset_persona_internal(proc_t p, persona_reset_op_t
  * previous persona the process had adopted. The caller is
  * responsible to release the reference.
  */
  * previous persona the process had adopted. The caller is
  * responsible to release the reference.
  */
-static struct persona *proc_set_cred_internal(proc_t p, struct persona *persona,
-                                             kauth_cred_t auth_override, int *rlim_error)
+static struct persona *
+proc_set_cred_internal(proc_t p, struct persona *persona,
+    kauth_cred_t auth_override, int *rlim_error)
 {
        struct persona *old_persona = NULL;
        kauth_cred_t my_cred, my_new_cred;
        uid_t old_uid, new_uid;
 {
        struct persona *old_persona = NULL;
        kauth_cred_t my_cred, my_new_cred;
        uid_t old_uid, new_uid;
-       int count;
+       size_t count;
+       rlim_t nproc = proc_limitgetcur(p, RLIMIT_NPROC, TRUE);
 
        /*
         * This operation must be done under the proc trans lock
         * by the thread which took the trans lock!
         */
        assert(((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) &&
 
        /*
         * This operation must be done under the proc trans lock
         * by the thread which took the trans lock!
         */
        assert(((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) &&
-              p->p_transholder == current_thread());
+           p->p_transholder == current_thread());
        assert(persona != NULL);
 
        /* no work to do if we "re-adopt" the same persona */
        assert(persona != NULL);
 
        /* no work to do if we "re-adopt" the same persona */
-       if (p->p_persona == persona)
+       if (p->p_persona == persona) {
                return NULL;
                return NULL;
+       }
 
        /*
         * If p is in a persona, then we need to remove 'p' from the list of
 
        /*
         * If p is in a persona, then we need to remove 'p' from the list of
@@ -688,16 +841,18 @@ static struct persona *proc_set_cred_internal(proc_t p, struct persona *persona,
         */
        if (p->p_persona) {
                old_persona = proc_reset_persona_internal(p, PROC_REMOVE_PERSONA,
         */
        if (p->p_persona) {
                old_persona = proc_reset_persona_internal(p, PROC_REMOVE_PERSONA,
-                                                         NULL, persona);
+                   NULL, persona);
        }
 
        }
 
-       if (auth_override)
+       if (auth_override) {
                my_new_cred = auth_override;
                my_new_cred = auth_override;
-       else
+       } else {
                my_new_cred = persona->pna_cred;
                my_new_cred = persona->pna_cred;
+       }
 
 
-       if (!my_new_cred)
+       if (!my_new_cred) {
                panic("NULL credentials (persona:%p)", persona);
                panic("NULL credentials (persona:%p)", persona);
+       }
 
        *rlim_error = 0;
 
 
        *rlim_error = 0;
 
@@ -711,12 +866,14 @@ static struct persona *proc_set_cred_internal(proc_t p, struct persona *persona,
         * the process or changing its credentials.
         */
        if (new_uid != 0 &&
         * the process or changing its credentials.
         */
        if (new_uid != 0 &&
-           (rlim_t)chgproccnt(new_uid, 0) > p->p_rlimit[RLIMIT_NPROC].rlim_cur) {
+           (rlim_t)chgproccnt(new_uid, 0) > nproc) {
                pna_err("PID:%d hit proc rlimit in new persona(%d): %s",
                pna_err("PID:%d hit proc rlimit in new persona(%d): %s",
-                       p->p_pid, new_uid, persona_desc(persona, 1));
+                   p->p_pid, new_uid, persona_desc(persona, 1));
                *rlim_error = EACCES;
                *rlim_error = EACCES;
-               (void)proc_reset_persona_internal(p, PROC_RESET_OLD_PERSONA,
-                                                 old_persona, persona);
+               if (old_persona) {
+                       (void)proc_reset_persona_internal(p, PROC_RESET_OLD_PERSONA,
+                           old_persona, persona);
+               }
                kauth_cred_unref(&my_new_cred);
                return NULL;
        }
                kauth_cred_unref(&my_new_cred);
                return NULL;
        }
@@ -727,9 +884,9 @@ static struct persona *proc_set_cred_internal(proc_t p, struct persona *persona,
 set_proc_cred:
        my_cred = kauth_cred_proc_ref(p);
        persona_dbg("proc_adopt PID:%d, %s -> %s",
 set_proc_cred:
        my_cred = kauth_cred_proc_ref(p);
        persona_dbg("proc_adopt PID:%d, %s -> %s",
-                   p->p_pid,
-                   persona_desc(old_persona, 1),
-                   persona_desc(persona, 1));
+           p->p_pid,
+           persona_desc(old_persona, 1),
+           persona_desc(persona, 1));
 
        old_uid = kauth_cred_getruid(my_cred);
 
 
        old_uid = kauth_cred_getruid(my_cred);
 
@@ -770,13 +927,14 @@ set_proc_cred:
         * Update the proc count.
         * If the UIDs are the same, then there is no work to do.
         */
         * Update the proc count.
         * If the UIDs are the same, then there is no work to do.
         */
-       if (old_persona)
+       if (old_persona) {
                old_uid = old_persona->pna_id;
                old_uid = old_persona->pna_id;
+       }
 
        if (new_uid != old_uid) {
                count = chgproccnt(old_uid, -1);
 
        if (new_uid != old_uid) {
                count = chgproccnt(old_uid, -1);
-               persona_dbg("Decrement %s:%d proc_count to: %d",
-                           old_persona ? "Persona" : "UID", old_uid, count);
+               persona_dbg("Decrement %s:%d proc_count to: %lu",
+                   old_persona ? "Persona" : "UID", old_uid, count);
 
                /*
                 * Increment the proc count on the UID associated with
 
                /*
                 * Increment the proc count on the UID associated with
@@ -784,8 +942,8 @@ set_proc_cred:
                 * as in fork1()
                 */
                count = chgproccnt(new_uid, 1);
                 * as in fork1()
                 */
                count = chgproccnt(new_uid, 1);
-               persona_dbg("Increment Persona:%d (UID:%d) proc_count to: %d",
-                           new_uid, kauth_cred_getuid(my_new_cred), count);
+               persona_dbg("Increment Persona:%d (UID:%d) proc_count to: %lu",
+                   new_uid, kauth_cred_getuid(my_new_cred), count);
        }
 
        OSBitOrAtomic(P_ADOPTPERSONA, &p->p_flag);
        }
 
        OSBitOrAtomic(P_ADOPTPERSONA, &p->p_flag);
@@ -800,17 +958,18 @@ set_proc_cred:
        return old_persona;
 }
 
        return old_persona;
 }
 
-int persona_proc_adopt(proc_t p, struct persona *persona, kauth_cred_t auth_override)
+int
+persona_proc_adopt(proc_t p, struct persona *persona, kauth_cred_t auth_override)
 {
        int error;
        struct persona *old_persona;
 {
        int error;
        struct persona *old_persona;
-       struct session * sessp;
 
 
-       if (!persona)
+       if (!persona) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_dbg("%d adopting Persona %d (%s)", proc_pid(p),
 
        persona_dbg("%d adopting Persona %d (%s)", proc_pid(p),
-                   persona->pna_id, persona_desc(persona, 0));
+           persona->pna_id, persona_desc(persona, 0));
 
        persona_lock(persona);
        if (!persona->pna_cred || !persona_valid(persona)) {
 
        persona_lock(persona);
        if (!persona->pna_cred || !persona_valid(persona)) {
@@ -832,20 +991,26 @@ int persona_proc_adopt(proc_t p, struct persona *persona, kauth_cred_t auth_over
        if (persona->pna_pgid) {
                uid_t uid = kauth_cred_getuid(persona->pna_cred);
                persona_dbg(" PID:%d, pgid:%d%s",
        if (persona->pna_pgid) {
                uid_t uid = kauth_cred_getuid(persona->pna_cred);
                persona_dbg(" PID:%d, pgid:%d%s",
-                           p->p_pid, persona->pna_pgid,
-                           persona->pna_pgid == uid ? ", new_session" : ".");
+                   p->p_pid, persona->pna_pgid,
+                   persona->pna_pgid == uid ? ", new_session" : ".");
                enterpgrp(p, persona->pna_pgid, persona->pna_pgid == uid);
        }
 
                enterpgrp(p, persona->pna_pgid, persona->pna_pgid == uid);
        }
 
+       /* Only Multiuser Mode needs to update the session login name to the persona name */
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+       volatile uint32_t *multiuser_flag_address = (volatile uint32_t *)(uintptr_t)(_COMM_PAGE_MULTIUSER_CONFIG);
+       uint32_t multiuser_flags = *multiuser_flag_address;
        /* set the login name of the session */
        /* set the login name of the session */
-       sessp = proc_session(p);
-       if (sessp != SESSION_NULL) {
-               session_lock(sessp);
-               bcopy(persona->pna_login, sessp->s_login, MAXLOGNAME);
-               session_unlock(sessp);
-               session_rele(sessp);
+       if (multiuser_flags) {
+               struct session * sessp = proc_session(p);
+               if (sessp != SESSION_NULL) {
+                       session_lock(sessp);
+                       bcopy(persona->pna_login, sessp->s_login, MAXLOGNAME);
+                       session_unlock(sessp);
+                       session_rele(sessp);
+               }
        }
        }
-
+#endif
        persona_unlock(persona);
 
        set_security_token(p);
        persona_unlock(persona);
 
        set_security_token(p);
@@ -853,14 +1018,16 @@ int persona_proc_adopt(proc_t p, struct persona *persona, kauth_cred_t auth_over
        /*
         * Drop the reference to the old persona.
         */
        /*
         * Drop the reference to the old persona.
         */
-       if (old_persona)
+       if (old_persona) {
                persona_put(old_persona);
                persona_put(old_persona);
+       }
 
        persona_dbg("%s", error == 0 ? "SUCCESS" : "FAILED");
        return error;
 }
 
 
        persona_dbg("%s", error == 0 ? "SUCCESS" : "FAILED");
        return error;
 }
 
-int persona_proc_drop(proc_t p)
+int
+persona_proc_drop(proc_t p)
 {
        struct persona *persona = NULL;
 
 {
        struct persona *persona = NULL;
 
@@ -911,12 +1078,14 @@ try_again:
        return 0;
 }
 
        return 0;
 }
 
-int persona_get_type(struct persona *persona)
+int
+persona_get_type(struct persona *persona)
 {
        int type;
 
 {
        int type;
 
-       if (!persona)
+       if (!persona) {
                return PERSONA_INVALID;
                return PERSONA_INVALID;
+       }
 
        persona_lock(persona);
        if (!persona_valid(persona)) {
 
        persona_lock(persona);
        if (!persona_valid(persona)) {
@@ -929,12 +1098,14 @@ int persona_get_type(struct persona *persona)
        return type;
 }
 
        return type;
 }
 
-int persona_set_cred(struct persona *persona, kauth_cred_t cred)
+int
+persona_set_cred(struct persona *persona, kauth_cred_t cred)
 {
        int ret = 0;
        kauth_cred_t my_cred;
 {
        int ret = 0;
        kauth_cred_t my_cred;
-       if (!persona || !cred)
+       if (!persona || !cred) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
@@ -951,14 +1122,15 @@ int persona_set_cred(struct persona *persona, kauth_cred_t cred)
 
        /* ensure that the UID matches the persona ID */
        my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
 
        /* ensure that the UID matches the persona ID */
        my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
-                                      persona->pna_id, persona->pna_id,
-                                      KAUTH_UID_NONE);
+           persona->pna_id, persona->pna_id,
+           KAUTH_UID_NONE);
 
        /* TODO: clear the saved GID?! */
 
        /* replace the persona's cred with the new one */
 
        /* TODO: clear the saved GID?! */
 
        /* replace the persona's cred with the new one */
-       if (persona->pna_cred)
+       if (persona->pna_cred) {
                kauth_cred_unref(&persona->pna_cred);
                kauth_cred_unref(&persona->pna_cred);
+       }
        persona->pna_cred = my_cred;
 
 out_unlock:
        persona->pna_cred = my_cred;
 
 out_unlock:
@@ -966,12 +1138,14 @@ out_unlock:
        return ret;
 }
 
        return ret;
 }
 
-int persona_set_cred_from_proc(struct persona *persona, proc_t proc)
+int
+persona_set_cred_from_proc(struct persona *persona, proc_t proc)
 {
        int ret = 0;
        kauth_cred_t parent_cred, my_cred;
 {
        int ret = 0;
        kauth_cred_t parent_cred, my_cred;
-       if (!persona || !proc)
+       if (!persona || !proc) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
@@ -992,12 +1166,13 @@ int persona_set_cred_from_proc(struct persona *persona, proc_t proc)
 
        /* ensure that the UID matches the persona ID */
        my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
 
        /* ensure that the UID matches the persona ID */
        my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
-                                      persona->pna_id, persona->pna_id,
-                                      KAUTH_UID_NONE);
+           persona->pna_id, persona->pna_id,
+           KAUTH_UID_NONE);
 
        /* replace the persona's cred with the new one */
 
        /* replace the persona's cred with the new one */
-       if (persona->pna_cred)
+       if (persona->pna_cred) {
                kauth_cred_unref(&persona->pna_cred);
                kauth_cred_unref(&persona->pna_cred);
+       }
        persona->pna_cred = my_cred;
 
        kauth_cred_unref(&parent_cred);
        persona->pna_cred = my_cred;
 
        kauth_cred_unref(&parent_cred);
@@ -1007,16 +1182,19 @@ out_unlock:
        return ret;
 }
 
        return ret;
 }
 
-kauth_cred_t persona_get_cred(struct persona *persona)
+kauth_cred_t
+persona_get_cred(struct persona *persona)
 {
        kauth_cred_t cred = NULL;
 
 {
        kauth_cred_t cred = NULL;
 
-       if (!persona)
+       if (!persona) {
                return NULL;
                return NULL;
+       }
 
        persona_lock(persona);
 
        persona_lock(persona);
-       if (!persona_valid(persona))
+       if (!persona_valid(persona)) {
                goto out_unlock;
                goto out_unlock;
+       }
 
        if (persona->pna_cred) {
                kauth_cred_ref(persona->pna_cred);
 
        if (persona->pna_cred) {
                kauth_cred_ref(persona->pna_cred);
@@ -1029,12 +1207,14 @@ out_unlock:
        return cred;
 }
 
        return cred;
 }
 
-uid_t persona_get_uid(struct persona *persona)
+uid_t
+persona_get_uid(struct persona *persona)
 {
        uid_t uid = UID_MAX;
 
 {
        uid_t uid = UID_MAX;
 
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return UID_MAX;
                return UID_MAX;
+       }
 
        persona_lock(persona);
        if (persona_valid(persona)) {
 
        persona_lock(persona);
        if (persona_valid(persona)) {
@@ -1046,13 +1226,15 @@ uid_t persona_get_uid(struct persona *persona)
        return uid;
 }
 
        return uid;
 }
 
-int persona_set_gid(struct persona *persona, gid_t gid)
+int
+persona_set_gid(struct persona *persona, gid_t gid)
 {
        int ret = 0;
        kauth_cred_t my_cred, new_cred;
 
 {
        int ret = 0;
        kauth_cred_t my_cred, new_cred;
 
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
@@ -1067,8 +1249,9 @@ int persona_set_gid(struct persona *persona, gid_t gid)
        my_cred = persona->pna_cred;
        kauth_cred_ref(my_cred);
        new_cred = kauth_cred_setresgid(my_cred, gid, gid, gid);
        my_cred = persona->pna_cred;
        kauth_cred_ref(my_cred);
        new_cred = kauth_cred_setresgid(my_cred, gid, gid, gid);
-       if (new_cred != my_cred)
+       if (new_cred != my_cred) {
                persona->pna_cred = new_cred;
                persona->pna_cred = new_cred;
+       }
        kauth_cred_unref(&my_cred);
 
 out_unlock:
        kauth_cred_unref(&my_cred);
 
 out_unlock:
@@ -1076,30 +1259,36 @@ out_unlock:
        return ret;
 }
 
        return ret;
 }
 
-gid_t persona_get_gid(struct persona *persona)
+gid_t
+persona_get_gid(struct persona *persona)
 {
        gid_t gid = GID_MAX;
 
 {
        gid_t gid = GID_MAX;
 
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return GID_MAX;
                return GID_MAX;
+       }
 
        persona_lock(persona);
 
        persona_lock(persona);
-       if (persona_valid(persona))
+       if (persona_valid(persona)) {
                gid = kauth_cred_getgid(persona->pna_cred);
                gid = kauth_cred_getgid(persona->pna_cred);
+       }
        persona_unlock(persona);
 
        return gid;
 }
 
        persona_unlock(persona);
 
        return gid;
 }
 
-int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid)
+int
+persona_set_groups(struct persona *persona, gid_t *groups, size_t ngroups, uid_t gmuid)
 {
        int ret = 0;
        kauth_cred_t my_cred, new_cred;
 
 {
        int ret = 0;
        kauth_cred_t my_cred, new_cred;
 
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return EINVAL;
                return EINVAL;
-       if (ngroups > NGROUPS_MAX)
+       }
+       if (ngroups > NGROUPS_MAX) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
 
        persona_lock(persona);
        if (!persona_initialized(persona)) {
@@ -1113,9 +1302,10 @@ int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups,
 
        my_cred = persona->pna_cred;
        kauth_cred_ref(my_cred);
 
        my_cred = persona->pna_cred;
        kauth_cred_ref(my_cred);
-       new_cred = kauth_cred_setgroups(my_cred, groups, (int)ngroups, gmuid);
-       if (new_cred != my_cred)
+       new_cred = kauth_cred_setgroups(my_cred, groups, ngroups, gmuid);
+       if (new_cred != my_cred) {
                persona->pna_cred = new_cred;
                persona->pna_cred = new_cred;
+       }
        kauth_cred_unref(&my_cred);
 
 out_unlock:
        kauth_cred_unref(&my_cred);
 
 out_unlock:
@@ -1123,19 +1313,21 @@ out_unlock:
        return ret;
 }
 
        return ret;
 }
 
-int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz)
+int
+persona_get_groups(struct persona *persona, size_t *ngroups, gid_t *groups, size_t groups_sz)
 {
        int ret = EINVAL;
 {
        int ret = EINVAL;
-       if (!persona || !persona->pna_cred || !groups || !ngroups || groups_sz > NGROUPS)
+       if (!persona || !persona->pna_cred || !groups || !ngroups || groups_sz > NGROUPS) {
                return EINVAL;
                return EINVAL;
+       }
 
        *ngroups = groups_sz;
 
        persona_lock(persona);
        if (persona_valid(persona)) {
 
        *ngroups = groups_sz;
 
        persona_lock(persona);
        if (persona_valid(persona)) {
-               int kauth_ngroups = (int)groups_sz;
+               size_t kauth_ngroups = groups_sz;
                kauth_cred_getgroups(persona->pna_cred, groups, &kauth_ngroups);
                kauth_cred_getgroups(persona->pna_cred, groups, &kauth_ngroups);
-               *ngroups = (unsigned)kauth_ngroups;
+               *ngroups = (uint32_t)kauth_ngroups;
                ret = 0;
        }
        persona_unlock(persona);
                ret = 0;
        }
        persona_unlock(persona);
@@ -1143,16 +1335,19 @@ int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups
        return ret;
 }
 
        return ret;
 }
 
-uid_t persona_get_gmuid(struct persona *persona)
+uid_t
+persona_get_gmuid(struct persona *persona)
 {
        uid_t gmuid = KAUTH_UID_NONE;
 
 {
        uid_t gmuid = KAUTH_UID_NONE;
 
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return gmuid;
                return gmuid;
+       }
 
        persona_lock(persona);
 
        persona_lock(persona);
-       if (!persona_valid(persona))
+       if (!persona_valid(persona)) {
                goto out_unlock;
                goto out_unlock;
+       }
 
        posix_cred_t pcred = posix_cred_get(persona->pna_cred);
        gmuid = pcred->cr_gmuid;
 
        posix_cred_t pcred = posix_cred_get(persona->pna_cred);
        gmuid = pcred->cr_gmuid;
@@ -1162,23 +1357,24 @@ out_unlock:
        return gmuid;
 }
 
        return gmuid;
 }
 
-int persona_get_login(struct persona *persona, char login[MAXLOGNAME+1])
+int
+persona_get_login(struct persona *persona, char login[MAXLOGNAME + 1])
 {
        int ret = EINVAL;
 {
        int ret = EINVAL;
-       if (!persona || !persona->pna_cred)
+       if (!persona || !persona->pna_cred) {
                return EINVAL;
                return EINVAL;
+       }
 
        persona_lock(persona);
 
        persona_lock(persona);
-       if (!persona_valid(persona))
+       if (!persona_valid(persona)) {
                goto out_unlock;
                goto out_unlock;
+       }
 
        strlcpy(login, persona->pna_login, MAXLOGNAME);
        ret = 0;
 
 out_unlock:
        persona_unlock(persona);
 
        strlcpy(login, persona->pna_login, MAXLOGNAME);
        ret = 0;
 
 out_unlock:
        persona_unlock(persona);
-       login[MAXLOGNAME] = 0;
-
        return ret;
 }
 
        return ret;
 }
 
@@ -1188,45 +1384,71 @@ out_unlock:
  * symbol exports for kext compatibility
  */
 
  * symbol exports for kext compatibility
  */
 
-uid_t persona_get_id(__unused struct persona *persona)
+struct persona *system_persona = NULL;
+struct persona *proxy_system_persona = NULL;
+int unique_persona = 0;
+
+uid_t
+persona_get_id(__unused struct persona *persona)
 {
        return PERSONA_ID_NONE;
 }
 
 {
        return PERSONA_ID_NONE;
 }
 
-int persona_get_type(__unused struct persona *persona)
+int
+persona_get_type(__unused struct persona *persona)
 {
        return PERSONA_INVALID;
 }
 
 {
        return PERSONA_INVALID;
 }
 
-kauth_cred_t persona_get_cred(__unused struct persona *persona)
+kauth_cred_t
+persona_get_cred(__unused struct persona *persona)
 {
        return NULL;
 }
 
 {
        return NULL;
 }
 
-struct persona *persona_lookup(__unused uid_t id)
+struct persona *
+persona_lookup(__unused uid_t id)
 {
        return NULL;
 }
 
 {
        return NULL;
 }
 
-int persona_find(__unused const char *login,
-                __unused uid_t uid,
-                __unused struct persona **persona,
-                __unused size_t *plen)
+int
+persona_find(__unused const char *login,
+    __unused uid_t uid,
+    __unused struct persona **persona,
+    __unused size_t *plen)
+{
+       return ENOTSUP;
+}
+
+int
+persona_find_by_type(__unused int persona_type,
+    __unused struct persona **persona,
+    __unused size_t *plen)
 {
        return ENOTSUP;
 }
 
 {
        return ENOTSUP;
 }
 
-struct persona *current_persona_get(void)
+struct persona *
+persona_proc_get(__unused pid_t pid)
+{
+       return NULL;
+}
+
+struct persona *
+current_persona_get(void)
 {
        return NULL;
 }
 
 {
        return NULL;
 }
 
-struct persona *persona_get(struct persona *persona)
+struct persona *
+persona_get(struct persona *persona)
 {
        return persona;
 }
 
 {
        return persona;
 }
 
-void persona_put(__unused struct persona *persona)
+void
+persona_put(__unused struct persona *persona)
 {
        return;
 }
 {
        return;
 }