--- a/sys/dev/raid/tws/tws_cam.c +++ b/sys/dev/raid/tws/tws_cam.c @@ -1158,11 +1158,23 @@ tws_intr_resp(struct tws_softc *sc) while ( tws_get_response(sc, &req_id, &mfa) ) { sc->stats.reqs_out++; if ( req_id == TWS_INVALID_REQID ) { TWS_TRACE_DEBUG(sc, "invalid req_id", mfa, req_id); sc->stats.reqs_errored++; tws_err_complete(sc, mfa); continue; } + /* + * The response queue is firmware-fed: validate both the index + * (req_id is a raw 16-bit field) and that the request is actually + * in flight with a completer before dereferencing cb. + */ + if (req_id >= (u_int16_t)tws_queue_depth || + sc->reqs[req_id].cb == NULL || + sc->reqs[req_id].state == TWS_REQ_STATE_FREE) { + TWS_TRACE(sc, "bogus response req_id", mfa, req_id); + sc->stats.reqs_errored++; + continue; + } sc->reqs[req_id].cb(&sc->reqs[req_id]); } }