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

XPT_RESET_DEV on the RAID physical-disk bus resets the WRONG device: phydisk id passed unmapped as a bus-0 TMF TargetID (hits the RAID volume sharing the number)

Summary

The raid_passthru mapping gate excludes XPT_RESET_DEV from mpt_map_physdisk(), so the raw phydisk-bus id (bus 1) reaches mpt_bus_reset, which sends the TMF on channel 0 where the same number denotes a RAID volume - 'reset this hidden disk' becomes 'TARGET_RESET of an unrelated volume', disrupting all its in-flight I/O. mpt_start() maps correctly for I/O, proving the omission. MPT RAID host: camcontrol reset of a physdisk pass node resets a whole volume - availability/data-integrity impact for that volume's in-flight commands.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3677 Β· 6 files
FileTypeDescriptionSize
README.md β€” 648 B ↓ raw
VERDICT.md β€” 3.1 KB ↓ raw
fix.diff β€” 685 B view raw
env.txt β€” 281 B view raw
verdict.json β€” 1.8 KB view raw
manifest.json β€” 619 B view raw

DF-3677 β€” XPT_RESET_DEV on the RAID physical-disk bus resets the WRONG device (unmapped phydisk id sent as bus-0 TargetID)

Severity: Low (wrong-device TMF reset: in-flight volume I/O disrupted). The raid_passthru mapping gate at mpt_cam.c:3292-3302 excludes XPT_RESET_DEV, so tgt stays the raw phydisk-bus id when mpt_bus_reset() sends the TMF on channel 0 (mpt_cam.c:3350 -> 2279-2287) β€” hitting the RAID volume with the same numeric id. mpt_start() maps for I/O (2104-2112); the reset path forgot. Trigger: camcontrol reset on the phydisk pass node. Requires MPT RAID hardware (absent on guest β€” env.txt). See VERDICT.md + fix.diff.

VERDICT.md
↓ download raw

DF-3677 β€” VERDICT

status: inconclusive (logic bug, source-certain; no MPT RAID hardware on guest)

Root cause

mpt_action() maps the RAID-physical-disk target id to a real bus-0 TargetID for every function except three:

/* sys/dev/disk/mpt/mpt_cam.c:3292-3302 */
    if (raid_passthru &&
        ccb->ccb_h.func_code != XPT_PATH_INQ &&
        ccb->ccb_h.func_code != XPT_RESET_BUS &&
        ccb->ccb_h.func_code != XPT_RESET_DEV) {          /* <-- RESET_DEV excluded */
        if (mpt_map_physdisk(mpt, ccb, &tgt) != 0) { ... CAM_DEV_NOT_THERE ... }
    }

and mpt_start() performs the mapping itself for I/O (mpt_cam.c:2104-2112), but the XPT_RESET_DEV case does not:

/* sys/dev/disk/mpt/mpt_cam.c:3342-3359 */
    case XPT_RESET_DEV:
        ...
        (void) mpt_bus_reset(mpt, tgt, lun, FALSE);       /* tgt = raw path id */

tgt is the phydisk-bus id (0..MaxPhysDisks-1, exported on bus 1, mpt_cam.c:3634-3638), but mpt_bus_reset() issues the TMF on channel 0 (mpt_scsi_send_tmf(..., 0 /* channel */, tgt, ...) via mpt_cam.c:2279-2287), where the same numeric id denotes a RAID volume. The result of XPT_RESET_DEV on a physical disk is a TARGET_RESET of the unrelated volume that happens to share the number β€” resetting every I/O in flight to that volume β€” or a reset sent to a nonexistent target. mpt_map_physdisk() exists precisely to translate (mpt_raid.c:806-819: *tgt = mpt_disk->config_page.PhysDiskID).

Impact: wrong-device reset (availability/data-integrity for the volume's in-flight I/O: unit attentions, failed writes reported to fs layers). Severity Low: requires a RAID-capable MPT controller, a userland reset of a hidden physdisk (camcontrol reset on the phydisk pass node), and the volume id space to overlap.

Fix

--- a/sys/dev/disk/mpt/mpt_cam.c
+++ b/sys/dev/disk/mpt/mpt_cam.c
@@ -3291,7 +3291,7 @@
    if (raid_passthru &&
        ccb->ccb_h.func_code != XPT_PATH_INQ &&
        ccb->ccb_h.func_code != XPT_RESET_BUS &&
-       ccb->ccb_h.func_code != XPT_RESET_DEV) {
+       ccb->ccb_h.func_code != XPT_RESET_DEV) {    /* keep: mapped below */
        if (mpt_map_physdisk(mpt, ccb, &tgt) != 0) {
            ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
            mpt_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
@@ -3342,6 +3342,14 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
        } else {
            xpt_print(ccb->ccb_h.path, "reset device\n");
        }
+       if (raid_passthru && mpt_map_physdisk(mpt, ccb, &tgt) != 0) {
+           ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+           mpt_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
+           xpt_done(ccb);
+           return;
+       }
        (void) mpt_bus_reset(mpt, tgt, lun, FALSE);

Guest verdict

inconclusive β€” no MPT RAID controller on the QEMU guest; the mapping mismatch is proven by reading the three code sites against each other.

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

Mapping fix authored (fix.diff); not exercisable without MPT RAID hardware.

fix.diff; env.txt
↓ fix.diffper-fix-DF-3677

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (three-site comparison with path:line); fix.diff (map in the RESET_DEV case); env.txt

PoC changes

n/a

Verified recommended fix

Call mpt_map_physdisk() for XPT_RESET_DEV on the phydisk sim before issuing the TMF

Verdict

Source-certain logic bug: the raid_passthru gate in mpt_action (mpt_cam.c:3292-3302) excludes XPT_RESET_DEV from mpt_map_physdisk(), so the raw phydisk-bus target id is passed to mpt_bus_reset (3350) which issues the TMF on channel 0 (2279-2287) β€” resetting the RAID volume that shares the numeric id instead of the intended physical disk. I/O commands map correctly (mpt_start 2104-2112), proving the omission. Impact on hardware: wrong-device TARGET_RESET, disrupting in-flight volume I/O (availability/data-integrity); requires an MPT RAID controller, absent on this guest.