⬢ DragonFlyBSD Kernel Audit
DF-4180 / fix.diff
← back to finding ↓ download raw
fix for DF-4180: twe_done trusts the controller-supplied 8-bit response_id
(0..255) to index sc->twe_lookup[TWE_Q_LENGTH] with TWE_Q_LENGTH == 255
(TWE_INIT_MESSAGE_CREDITS == 0xff), so a response_id of 255 reads one
pointer past the array (the first 8 bytes of sc->twe_drive[0]) and then
dereferences it as a struct twe_request * (read of tr_status plus a write
of TWE_CMD_COMPLETE).  Drop ids outside the valid range instead.
--- a/sys/dev/raid/twe/twe.c
+++ b/sys/dev/raid/twe/twe.c
@@ -1196,6 +1196,11 @@
 	if (!(status_reg & TWE_STATUS_RESPONSE_QUEUE_EMPTY)) {
 	    found = 1;
 	    rq.value = TWE_RESPONSE_QUEUE(sc);
+	    if (rq.u.response_id >= TWE_Q_LENGTH) {
+		twe_printf(sc, "invalid response id %d, dropping\n",
+			   rq.u.response_id);
+		continue;
+	    }
 	    tr = sc->twe_lookup[rq.u.response_id];	/* find command */
 #ifdef TWE_DEBUG
 	    cmd = TWE_FIND_COMMAND(tr);