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

mprsas_check_eedp error path calls xpt_free_path(NULL) instead of freeing local_path: deterministic NULL-deref panic under memory pressure during EEDP probe

Summary

On read-capacity buffer allocation failure, mprsas_check_eedp frees ccb->ccb_h.path which is NULL (the path was never assigned - local_path is a separate object that leaks). xpt_free_path(NULL) -> xpt_release_path derefs path->device. kmalloc(M_NOWAIT) failure during discovery of a protected LUN under memory pressure -> guaranteed kernel panic (plus local_path leak). Hardware-gated; one-line wrong-pointer fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3804 Β· 7 files
FileTypeDescriptionSize
README.md β€” 246 B ↓ raw
VERDICT.md β€” 2.2 KB ↓ raw
run.sh β€” 111 B view raw
env.txt β€” 855 B view raw
fix.diff β€” 683 B view raw
verdict.json β€” 1.6 KB view raw
manifest.json β€” 395 B view raw

DF-3804 evidence pack

mprsas_check_eedp frees ccb->ccb_h.path (NULL) instead of local_path on the read-capacity allocation-failure path β†’ NULL-deref panic. Read VERDICT.md. verdict.json: not_reproduced (no SAS3 hardware on guest).

VERDICT.md
↓ download raw

DF-3804 β€” mprsas_check_eedp error path frees a NULL path β†’ guaranteed panic on OOM

  • File: sys/dev/raid/mpr/mpr_sas.c
  • Class: NULL-deref panic on allocation-failure path + path leak
  • Severity: Low / Confidence: certain (statically provable)
  • Status on guest: not_reproduced β€” no SAS3 HBA (see env.txt)

Defect

mprsas_check_eedp (mpr_sas.c:3594-3714) allocates a local CCB at mpr_sas.c:3636 (zeroed: xpt_alloc_ccb uses M_INTWAIT|M_ZERO, sys/bus/cam/cam_xpt.c:4929-4938, so ccb->ccb_h.path == NULL) and creates a separate local_path at mpr_sas.c:3643.

On failure of the M_NOWAIT read-capacity buffer allocation (mpr_sas.c:3684-3692), the error path frees the wrong path:

    rcap_buf = kmalloc(sizeof(struct scsi_read_capacity_eedp), M_MPR,
        M_NOWAIT | M_ZERO);
    if (rcap_buf == NULL) {
        ...
        xpt_free_path(ccb->ccb_h.path);   /* :3689 β€” NULL! */
        xpt_free_ccb(&ccb->ccb_h);
        return;
    }

xpt_free_path(NULL) β†’ xpt_release_path(NULL) β†’ CAM_DEBUG(path,...) / path->device deref (sys/bus/cam/cam_xpt.c:4044-4067) β†’ NULL-deref panic. (With CAMDEBUG enabled, xpt_path_comp(cam_dpath, NULL) faults first at cam_xpt.c:4080+.)

Additionally local_path itself leaks in this path (and note the neighboring success path correctly uses xpt_free_path(local_path)-style handling via the completion callback mprsas_read_cap_done, mpr_sas.c:3781).

Trigger: kmalloc(M_NOWAIT) failure during EEDP probe of a newly-found protected LUN β€” i.e., under real memory pressure during device discovery. OOM-gated β†’ Low severity, but the panic is deterministic once the allocation fails.

Fix

Free local_path (the actual allocation), not the never-assigned ccb->ccb_h.path. See fix.diff.

Guest verification

No SAS3 HBA β†’ mprsas_check_eedp unreachable at runtime. 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 corrects the freed pointer; not exercisable on this guest.

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

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md, env.txt, fix.diff

PoC changes

n/a β€” hardware-gated

Verified recommended fix

Free local_path instead of the NULL ccb->ccb_h.path in the rcap_buf allocation-failure branch.

Verdict

mprsas_check_eedp's read-capacity allocation-failure path (mpr_sas.c:3684-3692) calls xpt_free_path(ccb->ccb_h.path) where ccb->ccb_h.path is NULL (xpt_alloc_ccb zeroes the ccb and no path was assigned yet); xpt_free_path(NULL) -> xpt_release_path(NULL) derefs path->device (sys/bus/cam/cam_xpt.c:4047) -> deterministic kernel panic under memory pressure during EEDP probing, plus local_path (created at mpr_sas.c:3643) leaks. Not reproduced on guest: no SAS3 HBA, function unreachable at runtime; provable from source.