X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/ff6e181ae92fc6f1e89841290f461d1f2f9badd9..13fec9890cf095cc781fdf7b8917cb03bf32dd4c:/bsd/kern/kern_prot.c diff --git a/bsd/kern/kern_prot.c b/bsd/kern/kern_prot.c index b4a20fb77..c7721f14d 100644 --- a/bsd/kern/kern_prot.c +++ b/bsd/kern/kern_prot.c @@ -3,20 +3,19 @@ * * @APPLE_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 - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource 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 + * This 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, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * 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 OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -723,6 +722,7 @@ setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __ gid_t newgroups[NGROUPS] = { 0 }; int error; kauth_cred_t my_cred, my_new_cred; + struct uthread *uthread = get_bsdthread_info(current_thread()); if ((error = suser(p->p_ucred, &p->p_acflag))) return (error); @@ -741,39 +741,64 @@ setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __ } } - /* get current credential and take a reference while we muck with it */ - for (;;) { - my_cred = kauth_cred_proc_ref(p); + if ((uthread->uu_flag & UT_SETUID) != 0) { + /* + * If this thread is under an assumed identity, set the + * supplementary grouplist on the thread credential instead + * of the process one. If we were the only reference holder, + * the credential is updated in place, otherwise, our reference + * is dropped and we get back a different cred with a reference + * already held on it. Because this is per-thread, we don't + * need the referencing/locking/retry required for per-process. + * + * Hack: this opts into memberd to avoid needing to use a per + * thread credential initgroups() instead of setgroups() in + * AFP server to address + */ + my_cred = uthread->uu_ucred; + uthread->uu_ucred = kauth_cred_setgroups(my_cred, &newgroups[0], ngrp, my_cred->cr_gmuid); + } else { - /* - * set the credential with new info. If there is no change we get back - * the same credential we passed in. + /* + * get current credential and take a reference while we muck + * with it */ - my_new_cred = kauth_cred_setgroups(p->p_ucred, &newgroups[0], ngrp, gmuid); - if (my_cred != my_new_cred) { - proc_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. + for (;;) { + my_cred = kauth_cred_proc_ref(p); + + /* + * set the credential with new info. If there is no + * change we get back the same credential we passed in. */ - if (p->p_ucred != my_cred) { + my_new_cred = kauth_cred_setgroups(my_cred, &newgroups[0], ngrp, gmuid); + if (my_cred != my_new_cred) { + proc_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); + kauth_cred_rele(my_cred); + kauth_cred_rele(my_new_cred); + /* try again */ + continue; + } + p->p_ucred = my_new_cred; + p->p_flag |= P_SUGID; proc_unlock(p); - kauth_cred_rele(my_cred); - kauth_cred_rele(my_new_cred); - /* try again */ - continue; } - p->p_ucred = my_new_cred; - p->p_flag |= P_SUGID; - proc_unlock(p); + /* drop our extra reference */ + kauth_cred_rele(my_cred); + break; } - /* drop our extra reference */ - kauth_cred_rele(my_cred); - break; - } - AUDIT_ARG(groupset, p->p_ucred->cr_groups, ngrp); - set_security_token(p); + AUDIT_ARG(groupset, p->p_ucred->cr_groups, ngrp); + set_security_token(p); + } return (0); }