xHCI: clear event TRB before state.finish() to prevent re-entrancy race

CRITICAL F1.1 from NETWORKING-AND-DRIVERS-CODE-ASSESSMENT-2026-07-27.md
§3.3: xHCI acknowledge() called state.finish() BEFORE releasing the
event TRB. A re-entrant waker.wake() from the future could re-enter the
reactor and re-match the same event TRB against a different state that
happens to overlap in address range, causing wrong-state-match.

Fix: call trb.reserved(false) BEFORE every state.finish() call site in
acknowledge() and acknowledge_failed_transfer_trbs(). This ensures
the event TRB is no longer in the live state set when the future
re-wakes, so a re-entrant wake cannot re-match this TRB.

Touches 4 call sites in irq_reactor.rs:
- StateKind::CommandCompletion match arm
- StateKind::Transfer match arm (transfer match)
- StateKind::Transfer 'dead ring' branch
- StateKind::Other match arm
- acknowledge_failed_transfer_trbs function
This commit is contained in:
Red Bear OS
2026-07-27 16:08:04 +09:00
parent 3a3af8253e
commit 51ae15674a
@@ -459,6 +459,9 @@ impl<const N: usize> IrqReactor<N> {
};
// TODO: Validate the command TRB.
// Release the event TRB before waking the future so a
// re-entrant waker.wake() cannot re-match this TRB.
trb.reserved(false);
state.finish(Some(NextEventTrb {
src_trb: Some(command_trb.clone()),
event_trb: trb.clone(),
@@ -489,6 +492,7 @@ impl<const N: usize> IrqReactor<N> {
let src_trb = self.hci.get_transfer_trb(phys_ptr, ring_id);
// Give the source transfer TRB together with the event TRB, to the future.
let state = self.states.remove(index);
trb.reserved(false);
state.finish(Some(NextEventTrb {
src_trb: src_trb,
event_trb: trb.clone(),
@@ -518,6 +522,7 @@ impl<const N: usize> IrqReactor<N> {
if self.hci.with_ring(ring_id, |_ring| ()).is_none() {
log::debug!("State {} is a dead transfer", index);
let state = self.states.remove(index);
trb.reserved(false);
state.finish(Some(NextEventTrb {
src_trb: None,
//TODO: don't send this TRB as it may not be related
@@ -529,6 +534,7 @@ impl<const N: usize> IrqReactor<N> {
StateKind::Other(trb_type) if trb_type as u8 == trb.trb_type() => {
let state = self.states.remove(index);
trb.reserved(false);
state.finish(None);
return;
}
@@ -557,6 +563,7 @@ impl<const N: usize> IrqReactor<N> {
continue;
}
let state = self.states.remove(index);
trb.reserved(false);
state.finish(Some(NextEventTrb {
event_trb: trb.clone(),
src_trb: None,