⬢ DragonFlyBSD Kernel Audit
DF-2868 / fix.diff
← back to finding ↓ download raw
--- sys/kern/kern_ktrace.c	2026-06-29 12:51:19.000000000 +0000
+++ /tmp/opencode/v26/fixtree/sys/kern/kern_ktrace.c	2026-10-24 16:33:07.877714441 +0000
@@ -668,20 +668,34 @@
 ktrcanset(struct thread *calltd, struct proc *targetp)
 {
 	struct ucred *caller = calltd->td_ucred;
-	struct ucred *target = targetp->p_ucred;
+	struct ucred *target;
+	int rv;
 
-	if (!PRISON_CHECK(caller, target))
+	/*
+	 * DF-2868: p_ucred is only stable under p_token; hold a
+	 * reference while checking instead of racing cratom_proc.
+	 */
+	lwkt_gettoken_shared(&targetp->p_token);
+	target = targetp->p_ucred;
+	if (target)
+		target = crhold(target);
+	lwkt_reltoken(&targetp->p_token);
+	if (target == NULL)
 		return (0);
-	if ((caller->cr_uid == target->cr_ruid &&
-	     target->cr_ruid == target->cr_svuid &&
-	     caller->cr_rgid == target->cr_rgid &&	/* XXX */
-	     target->cr_rgid == target->cr_svgid &&
-	     (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
-	     (targetp->p_flags & P_SUGID) == 0) ||
-	     caller->cr_uid == 0)
-		return (1);
 
-	return (0);
+	rv = 0;
+	if (PRISON_CHECK(caller, target) &&
+	    ((caller->cr_uid == target->cr_ruid &&
+	      target->cr_ruid == target->cr_svuid &&
+	      caller->cr_rgid == target->cr_rgid &&	/* XXX */
+	      target->cr_rgid == target->cr_svgid &&
+	      (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
+	      (targetp->p_flags & P_SUGID) == 0) ||
+	      caller->cr_uid == 0))
+		rv = 1;
+	crfree(target);
+
+	return (rv);
 }
 
 #endif /* KTRACE */