DF-2762 / fix.diff
--- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -662,6 +662,7 @@ { struct proc *p = curproc; struct ucred *cr; + gid_t newgroups[NGROUPS]; u_int ngrp; int error; @@ -679,6 +680,19 @@ * XXX A little bit lazy here. We could test if anything has * changed before cratom() and setting P_SUGID. */ + /* + * Copy the new group set in BEFORE publishing it: cratom_proc() + * makes the new credential visible to other threads immediately, + * so mutating cr_groups afterwards exposes a mixed credential, + * and a failing copyin would leave a partially-mutated (but + * published) credential behind. + */ + if (ngrp >= 1) { + error = copyin(uap->gidset, newgroups, + ngrp * sizeof(gid_t)); + if (error) + goto done; + } cr = cratom_proc(p); if (ngrp < 1) { /* @@ -689,10 +703,7 @@ */ cr->cr_ngroups = 1; } else { - error = copyin(uap->gidset, cr->cr_groups, - ngrp * sizeof(gid_t)); - if (error) - goto done; + memcpy(cr->cr_groups, newgroups, ngrp * sizeof(gid_t)); cr->cr_ngroups = ngrp; } setsugid(); |