DF-4180 / fix.diff
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); |