⬢ DragonFlyBSD Kernel Audit
DF-4415 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/misc/kbd/atkbdc.c b/sys/dev/misc/kbd/atkbdc.c
--- a/sys/dev/misc/kbd/atkbdc.c
+++ b/sys/dev/misc/kbd/atkbdc.c
@@ -856,9 +856,11 @@ empty_kbd_buffer(KBDC p, int wait)
 #endif
 	int delta = 2;
+	int waited = 0;
 
 	for (t = wait; t > 0;) {
 		if ((f = read_status(p)) & KBDS_ANY_BUFFER_FULL) {
 			DELAY(KBDD_DELAYTIME);
 			b = read_data(p);
@@ -879,7 +881,13 @@ empty_kbd_buffer(KBDC p, int wait)
 		} else {
 			t -= delta;
 		}
+		/*
+		 * A flooding controller resets `t' forever; cap total time
+		 * like empty_both_buffers() does for the Intel blades.
+		 */
+		waited += (delta * 1000);
+		if (waited >= (delta * 1000000))
+			return;
 		DELAY(delta * 1000);
 	}
@@ -895,9 +903,11 @@ empty_aux_buffer(KBDC p, int wait)
 #endif
 	int delta = 2;
+	int waited = 0;
 
 	for (t = wait; t > 0;) {
 		if ((f = read_status(p)) & KBDS_ANY_BUFFER_FULL) {
 			DELAY(KBDD_DELAYTIME);
 			b = read_data(p);
@@ -918,7 +928,13 @@ empty_aux_buffer(KBDC p, int wait)
 		} else {
 			t -= delta;
 		}
+		waited += (delta * 1000);
+		if (waited >= (delta * 1000000))
+			return;
 		DELAY(delta * 1000);
 	}
@@ -796,7 +812,11 @@ read_kbd_data_no_wait(KBDC p)
 	f = read_status(p) & KBDS_BUFFER_FULL;
 	while (f == KBDS_AUX_BUFFER_FULL) {
 		DELAY(KBDD_DELAYTIME);
 		b = read_data(p);
 		addq(&p->aux, b);
 		f = read_status(p) & KBDS_BUFFER_FULL;
+		if (++drain > KBDQ_BUFSIZE) {	/* bounded drain */
+			f = 0;
+			break;
+		}
 	}
@@ -835,7 +855,11 @@ read_aux_data_no_wait(KBDC p)
 	f = read_status(p) & KBDS_BUFFER_FULL;
 	while (f == KBDS_KBD_BUFFER_FULL) {
 		DELAY(KBDD_DELAYTIME);
 		b = read_data(p);
 		addq(&p->kbd, b);
 		f = read_status(p) & KBDS_BUFFER_FULL;
+		if (++drain > KBDQ_BUFSIZE) {	/* bounded drain */
+			f = 0;
+			break;
+		}
 	}