DragonFlyBSD Kernel Audit
DF-0103 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -363,10 +363,16 @@
 		lwkt_gettoken(&pg->pg_token);
 		LIST_FOREACH(p, &pg->pg_members, p_pglist) {
 			PHOLD(p);
-			if (descend)
+			if (descend) {
 				ret |= ktrsetchildren(td, p, ops, facs, tracenode);
-			else
+			} else {
+				/* hold target token around p_tracenode mutation
+				 * (ktrops is otherwise unlocked vs concurrent
+				 * ktrace on the same pid -> double-free) */
+				lwkt_gettoken(&p->p_token);
 				ret |= ktrops(td, p, ops, facs, tracenode);
+				lwkt_reltoken(&p->p_token);
+			}
 			PRELE(p);
 		}
 		lwkt_reltoken(&pg->pg_token);
@@ -380,10 +386,14 @@
 			error = ESRCH;
 			goto done;
 		}
-		if (descend)
+		if (descend) {
 			ret |= ktrsetchildren(td, p, ops, facs, tracenode);
-		else
+		} else {
+			/* hold target token around p_tracenode mutation */
+			lwkt_gettoken(&p->p_token);
 			ret |= ktrops(td, p, ops, facs, tracenode);
+			lwkt_reltoken(&p->p_token);
+		}
 		PRELE(p);
 	}
 	if (!ret)