DragonFlyBSD Kernel Audit
DF-2788 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 7dd812c2..57963f32 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -884,8 +884,20 @@ _callout_cancel_or_stop(struct callout *cc, uint32_t flags, int sync)
 	/*
 	 * If the operation is still in-progress then re-acquire the spin-lock
 	 * and block if necessary.  Also initiate the lock cancel.
+	 *
+	 * If the request was already processed (typically by our own
+	 * _callout_update_spinlocked() call above, which dequeued the
+	 * callout and set CALLOUT_PREVENTED on this _callout), report
+	 * whether this stop/cancel was responsible for preventing a
+	 * callback.  CALLOUT_PREVENTED was cleared at the top of this
+	 * function, so it cannot be stale here.
 	 */
-	if (sync == 0 || (c->flags & (CALLOUT_INPROG | CALLOUT_SET)) == 0) {
+	if ((c->flags & (CALLOUT_INPROG | CALLOUT_SET)) == 0) {
+		int res = ((c->flags & CALLOUT_PREVENTED) != 0);
+		exis_drop_gd(gd);
+		return res;
+	}
+	if (sync == 0) {
 		exis_drop_gd(gd);
 		return 0;
 	}