X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/593a1d5fd87cdf5b46dd5fcb84467b432cea0f91..e8c3f78193f1895ea514044358b93b1add9322f3:/bsd/kern/kern_prot.c?ds=inline diff --git a/bsd/kern/kern_prot.c b/bsd/kern/kern_prot.c index 46ab8bf1b..36beb2737 100644 --- a/bsd/kern/kern_prot.c +++ b/bsd/kern/kern_prot.c @@ -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@ * @@ -24,9 +24,11 @@ * 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. @@ -64,18 +66,19 @@ * 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. + * */ /* @@ -92,18 +95,12 @@ #include #include #include +#include -#include - -#if CONFIG_LCTX -#include -#endif +#include #if CONFIG_MACF #include -#if CONFIG_MACF_MACH -#include -#endif #endif #include @@ -116,8 +113,6 @@ #include -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 */