⬢ DragonFlyBSD Kernel Audit
DF-5183 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/linux_wait.c
+++ b/sys/dev/drm/linux_wait.c
@@ -104,13 +104,21 @@ int
 wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
 		    unsigned long timeout)
 {
 	int rv, awakened = 0, timeout_expired = 0;
 	long start_time;
+	int slpflags;
+	int timo;
+
+	/* Translate Linux state constants to tsleep(9) flags: TASK_*
+	 * values (0/1/2) are not PCATCH. */
+	slpflags = (mode & TASK_INTERRUPTIBLE) ? PCATCH : 0;
+
+	/* tsleep(9) takes an int timeout; clamp "infinite" to 0 (= no
+	 * timeout) instead of letting (unsigned long)LONG_MAX truncate
+	 * to -1, which _callout_setup_quick() clamps to a 1-tick callout. */
+	timo = (timeout >= INT_MAX || timeout == MAX_SCHEDULE_TIMEOUT) ? 0
+	    : (int)timeout;
 
 	if (!test_bit(bit, word))
 		return 0;
 
 	start_time = ticks;
 	set_current_state(mode);
 
 	do {
-		rv = tsleep(word, mode, "lwobt", timeout);
+		rv = tsleep(word, slpflags, "lwobt", timo);
 		if (rv == 0)
 			awakened = 1;
 		if (time_after_eq(start_time, timeout))