⬢ DragonFlyBSD Kernel Audit
DF-2762 / fix.diff
← back to finding ↓ download raw
--- 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();