DragonFlyBSD Kernel Audit
DF-2917 / fix.diff
← back to finding ↓ download raw
DF-2917 fix: _sleepq_wait_begin() computed the sleep domain
(PDOMAIN_FBSD0 + td_sqqueue * PDOMAIN_FBSDINC) into a local variable and
then never used it - tsleep() was called with tflags alone (PINTERLOCKED
carries no domain bits).  Because sleepq_add() had interlocked the thread
with tsleep_interlock(wchan, PDOMAIN_FBSD0+...), kern_synch.c's interlock
validation (td->td_wdomain != (flags & PDOMAIN_MASK)) always mismatched
and every sleepq_wait()/wait_sig()/timedwait()/timedwait_sig() returned
immediately via the goto resume fast path without ever descheduling.

OR the domain into the tsleep flags, exactly like the established umtx
pattern (kern_umtx.c:227: tsleep(waddr, PCATCH | PINTERLOCKED |
PDOMAIN_UMTX, ...)).

--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -328,12 +328,14 @@
 	if (timo) {
 		timo -= sbticks;
 		if (timo > 0) {
-			ret = tsleep(td->td_wchan, tflags, td->td_wmesg, timo);
+			ret = tsleep(td->td_wchan, tflags | domain,
+				     td->td_wmesg, timo);
 		} else {
 			ret = EWOULDBLOCK;
 		}
 	} else {
-		ret = tsleep(td->td_wchan, tflags, td->td_wmesg, 0);
+		ret = tsleep(td->td_wchan, tflags | domain,
+			     td->td_wmesg, 0);
 	}
 
 	return ret;