* Copyright (c) 2015 Apple Inc. All rights reserved.
*
* @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
* 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.
- *
+ *
* 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.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#include <sys/kernel.h>
#include <sys/proc_info.h>
#include <sys/resourcevar.h>
-#define pna_info(fmt, ...) \
- printf("%s: " fmt "\n", __func__, ## __VA_ARGS__)
-
+#include <os/log.h>
#define pna_err(fmt, ...) \
- printf("ERROR[%s]: " fmt "\n", __func__, ## __VA_ARGS__)
+ os_log_error(OS_LOG_DEFAULT, "ERROR: " fmt, ## __VA_ARGS__)
#define MAX_PERSONAS 512
#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_initialized(p) ((p)->pna_valid == PERSONA_MAGIC || (p)->pna_valid == PERSONA_INIT_TOKEN)
#define persona_valid(p) ((p)->pna_valid == PERSONA_MAGIC)
#define persona_mkinvalid(p) ((p)->pna_valid = ~(PERSONA_MAGIC))
lck_grp_t *persona_lck_grp;
lck_grp_attr_t *persona_lck_grp_attr;
+os_refgrp_decl(static, persona_refgrp, "persona", NULL);
+
static zone_t persona_zone;
kauth_cred_t g_default_persona_cred;
extern void mach_kauth_cred_uthread_update(void);
-void personas_bootstrap(void)
+void
+personas_bootstrap(void)
{
struct posix_cred pcred;
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");
+ MAX_PERSONAS * sizeof(struct persona),
+ MAX_PERSONAS, "personas");
assert(persona_zone != NULL);
/*
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!");
+ }
g_system_persona = persona_alloc(PERSONA_SYSTEM_UID,
- PERSONA_SYSTEM_LOGIN,
- PERSONA_SYSTEM, NULL);
+ 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);
}
-struct persona *persona_alloc(uid_t id, const char *login, int type, int *error)
+struct persona *
+persona_alloc(uid_t id, const char *login, int type, int *error)
{
- struct persona *persona, *tmp;
+ struct persona *persona;
int err = 0;
- kauth_cred_t tmp_cred;
- gid_t new_group;
if (!login) {
pna_err("Must provide a login name for a new persona!");
- if (error)
+ if (error) {
*error = EINVAL;
+ }
return NULL;
}
if (type <= PERSONA_INVALID || type > PERSONA_TYPE_MAX) {
pna_err("Invalid type: %d", type);
- if (error)
+ if (error) {
*error = EINVAL;
+ }
return NULL;
}
persona = (struct persona *)zalloc(persona_zone);
if (!persona) {
- if (error)
+ if (error) {
*error = ENOMEM;
+ }
return NULL;
}
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);
lck_mtx_init(&persona->pna_lock, persona_lck_grp, persona_lck_attr);
- persona->pna_refcount = 1;
+ os_ref_init(&persona->pna_refcount, &persona_refgrp);
/*
* Setup initial (temporary) kauth_cred structure
goto out_error;
}
+ persona->pna_type = type;
+ persona->pna_id = id;
+ persona->pna_valid = PERSONA_ALLOC_TOKEN;
+
+ /*
+ * NOTE: this persona has not been fully initialized. A subsequent
+ * call to persona_init_begin() followed by persona_init_end() will make
+ * the persona visible to the rest of the system.
+ */
+ if (error) {
+ *error = 0;
+ }
+ return persona;
+
+out_error:
+ (void)hw_atomic_add(&g_total_personas, -1);
+ zfree(persona_zone, persona);
+ if (error) {
+ *error = err;
+ }
+ return NULL;
+}
+
+/**
+ * persona_init_begin
+ *
+ * This function begins initialization of a persona. It first acquires the
+ * global persona list lock via lock_personas(), then selects an appropriate
+ * persona ID and sets up the persona's credentials. This function *must* be
+ * followed by a call to persona_init_end() which will mark the persona
+ * structure as valid
+ *
+ * Conditions:
+ * persona has been allocated via persona_alloc()
+ * nothing locked
+ *
+ * Returns:
+ * global persona list is locked (even on error)
+ */
+int
+persona_init_begin(struct persona *persona)
+{
+ struct persona *tmp;
+ int err = 0;
+ kauth_cred_t tmp_cred;
+ gid_t new_group;
+ uid_t id;
+
+ if (!persona || (persona->pna_valid != PERSONA_ALLOC_TOKEN)) {
+ return EINVAL;
+ }
+
+ id = persona->pna_id;
+
lock_personas();
try_again:
- if (id != PERSONA_ID_NONE)
- persona->pna_id = id;
- else
+ if (id == PERSONA_ID_NONE) {
persona->pna_id = g_next_persona_id;
+ }
- persona_dbg("Adding %d (%s) to global list...", persona->pna_id, persona->pna_login);
+ persona_dbg("Beginning Initialization of %d:%d (%s)...", id, persona->pna_id, persona->pna_login);
err = 0;
LIST_FOREACH(tmp, &all_personas, pna_list) {
- if (id == PERSONA_ID_NONE && tmp->pna_id == id) {
+ persona_lock(tmp);
+ if (id == PERSONA_ID_NONE && tmp->pna_id == persona->pna_id) {
+ persona_unlock(tmp);
/*
* someone else manually claimed this ID, and we're
* trying to allocate an ID for the caller: try again
g_next_persona_id += PERSONA_ID_STEP;
goto try_again;
}
- if (strncmp(tmp->pna_login, login, sizeof(tmp->pna_login)) == 0
- || tmp->pna_id == id) {
+ if (strncmp(tmp->pna_login, persona->pna_login, sizeof(tmp->pna_login)) == 0 ||
+ tmp->pna_id == persona->pna_id) {
+ persona_unlock(tmp);
/*
* Disallow use of identical login names and re-use
* of previously allocated persona IDs
err = EEXIST;
break;
}
+ persona_unlock(tmp);
+ }
+ if (err) {
+ goto out;
}
- if (err)
- goto out_unlock;
/* 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);
- if (tmp_cred != persona->pna_cred)
+ if (tmp_cred != persona->pna_cred) {
persona->pna_cred = tmp_cred;
+ }
if (!persona->pna_cred) {
err = EACCES;
- goto out_unlock;
+ goto out;
}
/* it should be a member of exactly 1 group (equal to its UID) */
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);
- if (tmp_cred != persona->pna_cred)
+ if (tmp_cred != persona->pna_cred) {
persona->pna_cred = tmp_cred;
+ }
if (!persona->pna_cred) {
err = EACCES;
- goto out_unlock;
+ goto out;
}
- persona->pna_type = type;
-
- /* insert the, now valid, persona into the global list! */
- persona->pna_valid = PERSONA_MAGIC;
- LIST_INSERT_HEAD(&all_personas, persona, pna_list);
-
/* 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;
+ }
-out_unlock:
- unlock_personas();
+ persona->pna_valid = PERSONA_INIT_TOKEN;
- if (err) {
- switch (err) {
- case EEXIST:
- persona_dbg("Login '%s' (%d) already exists",
- login, persona->pna_id);
- break;
- case EACCES:
- persona_dbg("kauth_error for persona:%d", persona->pna_id);
- break;
- default:
- persona_dbg("Unknown error:%d", err);
- }
- goto out_error;
+out:
+ if (err != 0) {
+ persona_dbg("ERROR:%d while initializing %d:%d (%s)...", err, id, persona->pna_id, persona->pna_login);
+ /*
+ * mark the persona with an error so that persona_init_end()
+ * will *not* add it to the global list.
+ */
+ persona->pna_id = PERSONA_ID_NONE;
}
- return persona;
-
-out_error:
- (void)hw_atomic_add(&g_total_personas, -1);
- zfree(persona_zone, persona);
- if (error)
- *error = err;
- return NULL;
+ /*
+ * leave the global persona list locked: it will be
+ * unlocked in a call to persona_init_end()
+ */
+ return err;
}
-int persona_invalidate(struct persona *persona)
+/**
+ * persona_init_end
+ *
+ * This function finalizes the persona initialization by marking it valid and
+ * adding it to the global list of personas. After unlocking the global list,
+ * the persona will be visible to the reset of the system. The function will
+ * 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()
+ *
+ * Returns:
+ * global persona list is unlocked
+ */
+void
+persona_init_end(struct persona *persona, int error)
{
- int error = 0;
- if (!persona)
- return EINVAL;
-
- lock_personas();
- persona_lock(persona);
-
- if (!persona_valid(persona))
- panic("Double-invalidation of persona %p", persona);
+ if (persona == NULL) {
+ return;
+ }
- LIST_REMOVE(persona, pna_list);
- if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX)
- panic("persona ref count underflow!\n");
- persona_mkinvalid(persona);
+ /*
+ * If the pna_valid member is set to the INIT_TOKEN value, then it has
+ * successfully gone through persona_init_begin(), and we can mark it
+ * valid and make it visible to the rest of the system. However, if
+ * there was an error either during initialization or otherwise, we
+ * need to decrement the global count of personas because this one
+ * will be disposed-of by the callers invocation of persona_put().
+ */
+ 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);
+ } else if (error == 0 &&
+ 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_unlock(persona);
unlock_personas();
-
- return error;
}
-static struct persona *persona_get_locked(struct persona *persona)
+static struct persona *
+persona_get_locked(struct persona *persona)
{
- if (persona->pna_refcount) {
- persona->pna_refcount++;
- return persona;
- }
- return NULL;
+ 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;
- if (!persona)
+ if (!persona) {
return NULL;
+ }
persona_lock(persona);
ret = persona_get_locked(persona);
persona_unlock(persona);
return ret;
}
-void persona_put(struct persona *persona)
+void
+persona_put(struct persona *persona)
{
int destroy = 0;
- if (!persona)
+ if (!persona) {
return;
+ }
persona_lock(persona);
- if (persona->pna_refcount >= 0) {
- if (--(persona->pna_refcount) == 0)
- destroy = 1;
+ if (os_ref_release_locked(&persona->pna_refcount) == 0) {
+ destroy = 1;
}
persona_unlock(persona);
- if (!destroy)
+ if (!destroy) {
return;
+ }
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);
+ }
/* 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 (hw_atomic_add(&g_total_personas, -1) == UINT_MAX) {
panic("persona count underflow!\n");
+ }
persona_mkinvalid(persona);
}
+ persona_unlock(persona);
unlock_personas();
assert(LIST_EMPTY(&persona->pna_members));
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_ID_NONE;
}
-struct persona *persona_lookup(uid_t id)
+struct persona *
+persona_lookup(uid_t id)
{
struct persona *persona, *tmp;
return persona;
}
-int persona_find(const char *login, uid_t uid,
- struct persona **persona, size_t *plen)
+struct persona *
+persona_lookup_and_invalidate(uid_t id)
+{
+ struct persona *persona, *entry, *tmp;
+
+ persona = NULL;
+
+ lock_personas();
+ LIST_FOREACH_SAFE(entry, &all_personas, pna_list, tmp) {
+ persona_lock(entry);
+ if (entry->pna_id == id) {
+ if (persona_valid(entry)) {
+ persona = persona_get_locked(entry);
+ assert(persona != NULL);
+ LIST_REMOVE(persona, pna_list);
+ if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX) {
+ panic("persona ref count underflow!\n");
+ }
+ persona_mkinvalid(persona);
+ }
+ persona_unlock(entry);
+ break;
+ }
+ persona_unlock(entry);
+ }
+ unlock_personas();
+
+ return persona;
+}
+
+int
+persona_find(const char *login, uid_t uid,
+ struct persona **persona, size_t *plen)
{
struct persona *tmp;
int match = 0;
size_t found = 0;
- if (login)
+ if (login) {
match++;
- if (uid != PERSONA_ID_NONE)
+ }
+ if (uid != PERSONA_ID_NONE) {
match++;
+ }
- if (match == 0)
+ if (match == 0) {
return EINVAL;
+ }
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);
- 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++;
- if (uid != PERSONA_ID_NONE && uid == tmp->pna_id)
+ }
+ if (uid != PERSONA_ID_NONE && uid == tmp->pna_id) {
m++;
+ }
if (m == match) {
- if (persona && *plen > found)
+ if (persona && *plen > found) {
persona[found] = persona_get_locked(tmp);
+ }
found++;
}
#ifdef PERSONA_DEBUG
- if (m > 0)
+ if (m > 0) {
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;
- if (!found)
+ if (!found) {
return ESRCH;
+ }
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);
- if (!p)
+ if (!p) {
return NULL;
+ }
proc_lock(p);
persona = persona_get(p->p_persona);
return persona;
}
-struct persona *current_persona_get(void)
+struct persona *
+current_persona_get(void)
{
proc_t p = current_proc();
struct persona *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",
- persona_desc(child->p_persona, 0));
+ persona_desc(child->p_persona, 0));
return -1;
}
/* no persona to inherit */
- if (parent->p_persona == NULL)
+ if (parent->p_persona == NULL) {
return 0;
+ }
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);
- if (!persona)
+ if (!persona) {
return ESRCH;
+ }
ret = persona_proc_adopt(p, persona, auth_override);
* 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);
switch (op) {
case PROC_REMOVE_PERSONA:
old_persona = p->p_persona;
- /* fall through */
+ /* fall through */
case PROC_RESET_OLD_PERSONA:
break;
default:
* 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;
* 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 */
- if (p->p_persona == persona)
+ if (p->p_persona == persona) {
return NULL;
+ }
/*
* If p is in a persona, then we need to remove 'p' from the list of
*/
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;
- else
+ } else {
my_new_cred = persona->pna_cred;
+ }
- if (!my_new_cred)
+ if (!my_new_cred) {
panic("NULL credentials (persona:%p)", persona);
+ }
*rlim_error = 0;
if (new_uid != 0 &&
(rlim_t)chgproccnt(new_uid, 0) > p->p_rlimit[RLIMIT_NPROC].rlim_cur) {
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;
(void)proc_reset_persona_internal(p, PROC_RESET_OLD_PERSONA,
- old_persona, persona);
+ old_persona, persona);
kauth_cred_unref(&my_new_cred);
return NULL;
}
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);
* 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;
+ }
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);
+ old_persona ? "Persona" : "UID", old_uid, count);
/*
* Increment the proc count on the UID associated with
*/
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);
+ new_uid, kauth_cred_getuid(my_new_cred), count);
}
OSBitOrAtomic(P_ADOPTPERSONA, &p->p_flag);
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;
struct session * sessp;
- if (!persona)
+ if (!persona) {
return EINVAL;
+ }
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)) {
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);
}
/*
* Drop the reference to the old persona.
*/
- if (old_persona)
+ if (old_persona) {
persona_put(old_persona);
+ }
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;
return 0;
}
-int persona_get_type(struct persona *persona)
+int
+persona_get_type(struct persona *persona)
{
int type;
- if (!persona)
+ if (!persona) {
return PERSONA_INVALID;
+ }
persona_lock(persona);
if (!persona_valid(persona)) {
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;
- if (!persona || !cred)
+ if (!persona || !cred) {
return EINVAL;
+ }
persona_lock(persona);
- if (!persona_valid(persona)) {
+ if (!persona_initialized(persona)) {
ret = EINVAL;
goto out_unlock;
}
/* 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 */
- if (persona->pna_cred)
+ if (persona->pna_cred) {
kauth_cred_unref(&persona->pna_cred);
+ }
persona->pna_cred = my_cred;
out_unlock:
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;
- if (!persona || !proc)
+ if (!persona || !proc) {
return EINVAL;
+ }
persona_lock(persona);
- if (!persona_valid(persona)) {
+ if (!persona_initialized(persona)) {
ret = EINVAL;
goto out_unlock;
}
/* 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 */
- if (persona->pna_cred)
+ if (persona->pna_cred) {
kauth_cred_unref(&persona->pna_cred);
+ }
persona->pna_cred = my_cred;
kauth_cred_unref(&parent_cred);
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;
- if (!persona)
+ if (!persona) {
return NULL;
+ }
persona_lock(persona);
- if (!persona_valid(persona))
+ if (!persona_valid(persona)) {
goto out_unlock;
+ }
if (persona->pna_cred) {
kauth_cred_ref(persona->pna_cred);
return cred;
}
-uid_t persona_get_uid(struct persona *persona)
+uid_t
+persona_get_uid(struct persona *persona)
{
uid_t uid = UID_MAX;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return UID_MAX;
+ }
persona_lock(persona);
if (persona_valid(persona)) {
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;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return EINVAL;
+ }
persona_lock(persona);
- if (!persona_valid(persona)) {
+ if (!persona_initialized(persona)) {
ret = EINVAL;
goto out_unlock;
}
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;
+ }
kauth_cred_unref(&my_cred);
out_unlock:
return ret;
}
-gid_t persona_get_gid(struct persona *persona)
+gid_t
+persona_get_gid(struct persona *persona)
{
gid_t gid = GID_MAX;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return GID_MAX;
+ }
persona_lock(persona);
- if (persona_valid(persona))
+ if (persona_valid(persona)) {
gid = kauth_cred_getgid(persona->pna_cred);
+ }
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, unsigned ngroups, uid_t gmuid)
{
int ret = 0;
kauth_cred_t my_cred, new_cred;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return EINVAL;
- if (ngroups > NGROUPS_MAX)
+ }
+ if (ngroups > NGROUPS_MAX) {
return EINVAL;
+ }
persona_lock(persona);
- if (!persona_valid(persona)) {
+ if (!persona_initialized(persona)) {
ret = EINVAL;
goto out_unlock;
}
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)
+ if (new_cred != my_cred) {
persona->pna_cred = new_cred;
+ }
kauth_cred_unref(&my_cred);
out_unlock:
return ret;
}
-int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz)
+int
+persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz)
{
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;
+ }
*ngroups = groups_sz;
return ret;
}
-uid_t persona_get_gmuid(struct persona *persona)
+uid_t
+persona_get_gmuid(struct persona *persona)
{
uid_t gmuid = KAUTH_UID_NONE;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return gmuid;
+ }
persona_lock(persona);
- if (!persona_valid(persona))
+ if (!persona_valid(persona)) {
goto out_unlock;
+ }
posix_cred_t pcred = posix_cred_get(persona->pna_cred);
gmuid = pcred->cr_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;
- if (!persona || !persona->pna_cred)
+ if (!persona || !persona->pna_cred) {
return EINVAL;
+ }
persona_lock(persona);
- if (!persona_valid(persona))
+ if (!persona_valid(persona)) {
goto out_unlock;
+ }
strlcpy(login, persona->pna_login, MAXLOGNAME);
ret = 0;
* symbol exports for kext compatibility
*/
-uid_t persona_get_id(__unused struct persona *persona)
+uid_t
+persona_get_id(__unused struct persona *persona)
{
return PERSONA_ID_NONE;
}
-int persona_get_type(__unused struct persona *persona)
+int
+persona_get_type(__unused struct persona *persona)
{
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;
}
-struct persona *persona_lookup(__unused uid_t id)
+struct persona *
+persona_lookup(__unused uid_t id)
{
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;
}
-struct persona *current_persona_get(void)
+struct persona *
+current_persona_get(void)
{
return NULL;
}
-struct persona *persona_get(struct persona *persona)
+struct persona *
+persona_get(struct persona *persona)
{
return persona;
}
-void persona_put(__unused struct persona *persona)
+void
+persona_put(__unused struct persona *persona)
{
return;
}