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

mprsas_prepare_for_tm leaks one union ccb + cam_path per TM reuse/escalation during error recovery

Summary

mprsas_prepare_for_tm allocates a fresh ccb+path and assigns tm->cm_ccb unconditionally; the recovery state machine reuses the same tm - re-abort, LUN-reset escalation, target-reset escalation - leaking the previous ccb+path each time; mprsas_free_tm frees only the last one. A failing device with multiple timed-out commands or repeated abort failures leaks one ccb (several hundred bytes incl. timeout_ch kmalloc) + path per escalation; unbounded under error storms -> memory exhaustion on a storage box. Hardware-gated; fix.diff frees the predecessor.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3803 Β· 7 files
FileTypeDescriptionSize
README.md β€” 170 B ↓ raw
VERDICT.md β€” 2.1 KB ↓ raw
run.sh β€” 111 B view raw
env.txt β€” 855 B view raw
fix.diff β€” 701 B view raw
verdict.json β€” 1.5 KB view raw
manifest.json β€” 430 B view raw

DF-3803 evidence pack

CCB+path leak per TM reuse/escalation in mprsas_prepare_for_tm. Read VERDICT.md. verdict.json: not_reproduced (no SAS3 hardware on guest).

VERDICT.md
↓ download raw

DF-3803 β€” mprsas_prepare_for_tm leaks a CCB + path on every TM reuse/escalation

  • File: sys/dev/raid/mpr/mpr_sas.c
  • Class: unbounded kernel memory leak under error recovery
  • Severity: Low / Confidence: certain (statically provable)
  • Status on guest: not_reproduced β€” no SAS3 HBA (see env.txt)

Defect

mprsas_prepare_for_tm (mpr_sas.c:3787-3813) allocates a fresh CCB and path and assigns them unconditionally:

    ccb = xpt_alloc_ccb();                        /* :3801 */
    if (ccb) {
        if (xpt_create_path(&ccb->ccb_h.path, ...) != CAM_REQ_CMP)
            xpt_free_ccb(&ccb->ccb_h);
        else {
            tm->cm_ccb = ccb;                 /* :3808 β€” overwrites, no free */
            ...
        }
    }

mprsas_free_tm (mpr_sas.c:243-270) frees only the last tm->cm_ccb.

The error-recovery state machine calls prepare_for_tm multiple times on the same tm:

  1. mprsas_send_abort β†’ prepare (mpr_sas.c:1643)
  2. abort completes, more timed-out commands β†’ mprsas_send_abort again (mpr_sas.c:1584 β†’ prepare at 1643) β€” leaks ccb #1
  3. abort fails β†’ LUN reset (mpr_sas.c:1594 β†’ mpr_sas.c:1476) β€” leaks again
  4. LUN reset fails β†’ target reset (mpr_sas.c:1365 β†’ mpr_sas.c:1487) β€” leaks again

Each leak is sizeof(union ccb) (several hundred bytes, includes a kmalloc'd timeout_ch, cam_xpt.c:4933-4935) plus a cam_path. A target with N timed-out commands under a failing device leaks N-1 CCBs; sustained error storms leak without bound. Memory pressure on a storage box is a availability problem, not a corruption problem β†’ Low.

Fix

Free the previous tm->cm_ccb (path + ccb) before overwriting β€” see fix.diff.

Guest verification

No SAS3 controller in the guest β†’ the SIM never runs; static proof only. See env.txt.

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

fix.diff authored; not exercisable on this guest.

findings/poc/DF-3803/fix.diff
↓ fix.diffper-fix-DF-3803

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md, env.txt, fix.diff

PoC changes

n/a β€” hardware-gated

Verified recommended fix

Free the previous tm->cm_ccb path+ccb at the top of mprsas_prepare_for_tm.

Verdict

mprsas_prepare_for_tm (mpr_sas.c:3787-3813) overwrites tm->cm_ccb with a freshly allocated ccb+path on every call; the TM error-recovery state machine calls it repeatedly on the same tm (re-abort at mpr_sas.c:1584->1643, LUN-reset escalation at 1594->1476, target-reset escalation at 1365->1487), leaking one union ccb + cam_path per reuse; mprsas_free_tm frees only the final one. Unbounded leak under device error storms. Not reproduced: no SAS3 HBA on the guest; provable from source.