β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4562

mpssas_add_device/mpssas_volume_add re-initialize a target slot without checking the asynchronous removal is still in flight (INREMOVAL flag cleared under an outstanding TM; TAILQ_INIT over possibly-linked command lists)

Summary

prepare_remove only starts an async removal; add_device unconditionally clears flags and re-inits the command lists on the same slot - a re-add event inside the removal window clears INREMOVAL under an outstanding TM and orphans linked commands; the completion's TAILQ_REMOVE then writes through stale tqe_prev pointers. Not covered by DF-3895/3898; filed speculative per pass-2 lifetime discipline (needs real HBA event timing). Bail-EBUSY guard sketch.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4562 Β· 4 files
FileTypeDescriptionSize
README.md β€” 2.6 KB ↓ raw
fix.diff β€” 1.3 KB view raw
VERDICT.md β€” 1.8 KB ↓ raw
verdict.json β€” 2.5 KB view raw

DF-4562 β€” mpssas_add_device re-initializes a target that may still be in

removal / have in-flight commands (speculative list-corruption race)

File: `sys/dev/raid/mps/mps_sas_lsi.c:580-682 (sink :653-670), interaction with :212-219/:328-346/:394-395 Severity: Low (speculative), Status:** untested β€” needs an mps HBA to create the event interleaving; filed as a labeled speculation per pass-2 discipline (lifetimes/error-path interactions), adjacent to the already-filed DF-3895/DF-3898 removal-path defects.

The hypothesis

All fw events are processed serialized on ev_tq under mps_lock (mps_sas_lsi.c:564-577), but mpssas_prepare_remove() only starts an asynchronous removal: it sets MPSSAS_TARGET_INREMOVAL, sends a TM TARGET_RESET, and the removal finishes later in completion callbacks (mps_sas.c:407-466). If a TARG_ADDED / PD_DELETED event for the same (or a colliding-ID) device is processed before that removal completes, mpssas_add_device() unconditionally overwrites the target slot (mps_sas_lsi.c:653-670):

  • targ->flags = 0 clears MPSSAS_TARGET_INREMOVAL while the TM is still outstanding (targ->tm still points at it);
  • TAILQ_INIT(&targ->commands) / TAILQ_INIT(&targ->timedout_commands) orphan any still-linked commands β€” their tqe_prev still point into the (now reset) head or into each other, so the completion path's TAILQ_REMOVE writes through stale pointers into the new list head (list corruption; lost/leaked commands);
  • the failure branch at :212-219 itself calls mpssas_prepare_remove() on a just-failed add of the same handle, interleaving two removals on one slot.

mpssas_volume_add() (:847-853) has the same shape (no INREMOVAL / non-empty-list check before TAILQ_INIT).

Why speculative

Triggering requires a specific firmware-event interleaving (removal not yet completed when the re-add for the same target ID is processed) that cannot be produced on the QEMU guest (no mps controller). The list mechanics above are how TAILQ behaves, but the existence of the interleaving window in the field is unproven; pass-1 findings DF-3895 / DF-3898 cover neighboring removal-lifetime defects, so this is recorded as the remaining uncovered edge rather than a demonstrated primitive.

Suggested hardening (defensive; also collapses this window)

In mpssas_add_device / mpssas_volume_add, before overwriting the slot: bail out (EBUSY) if targ->handle != 0 && (targ->flags & MPSSAS_TARGET_INREMOVAL || !TAILQ_EMPTY(&targ->commands) || !TAILQ_EMPTY(&targ->timedout_commands) || targ->tm != NULL) β€” see fix.diff sketch.

VERDICT.md
↓ download raw

DF-4562 VERDICT β€” untested (speculative), Low, target-slot re-init race

Bottom line

Speculative, labeled as such. mpssas_add_device() (sys/dev/raid/mps/mps_sas_lsi.c:653-670) and mpssas_volume_add() (:847-853) overwrite/TAILQ_INIT a target slot without checking MPSSAS_TARGET_INREMOVAL / outstanding commands / targ->tm. Removal is asynchronous (TM TARGET_RESET started in mpssas_prepare_remove, mps_sas.c:449-466); a re-add event processed before the removal completes would clear the flag under an outstanding TM and re-init lists that may still be linked, corrupting the new list through stale tqe_prev pointers on the completion path.

Why not verified

The interleaving requires a real mps HBA delivering a re-add event inside the removal window; the QEMU guest has no such hardware, and unlike DF-4559/DF-4560 there is no deterministic arithmetic to replicate β€” the claim is about event timing, not address math. Honest status: untested. Filed (speculative) because pass-2 exists exactly for lifetime/error-path interactions, and the neighboring removal defects DF-3895/DF-3898 do not cover this sink.

Impact if real

List corruption / lost commands on the storage path of one adapter β€” availability-grade (DoS), possibly worse if the orphaned command blocks are later double-completed. Not demonstrated.

Guard in add paths (see README): refuse to re-init a slot that is INREMOVAL, has non-empty command lists, or an outstanding tm.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_applicable (speculative finding, no reproducer)

README.md hardening sketch.
↓ fix.diffper-fix-DF-4562

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md and README.md contain the full path:line trace of the interleaving hypothesis; no runtime artifacts (no hardware).

PoC changes

No PoC possible on the available guest; filed as a labeled speculative pass-2 lifetime finding.

Verified recommended fix

Guard target-slot re-initialization in mpssas_add_device/mpssas_volume_add against in-flight removal (INREMOVAL flag, non-empty command lists, outstanding tm).

Verdict

SPECULATIVE, untested (needs a real mps HBA to produce the event interleaving; the QEMU guest has none, and unlike DF-4559/DF-4560 there is no deterministic arithmetic to replicate β€” the claim is about event TIMING). mpssas_add_device (mps_sas_lsi.c:653-670) and mpssas_volume_add (:847-853) overwrite/TAILQ_INIT a target slot without checking MPSSAS_TARGET_INREMOVAL, outstanding commands, or targ->tm, while mpssas_prepare_remove's removal is asynchronous (TM TARGET_RESET completes later, mps_sas.c:449-466). A re-add event processed inside the removal window would clear INREMOVAL under an outstanding TM and re-init possibly-still-linked lists; completion-path TAILQ_REMOVE would then write through stale tqe_prev pointers into the re-initialized head. Adjacent to (not covered by) DF-3895/DF-3898. If real: list corruption / lost commands β€” availability-grade.