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

mpt_cam detach/error-path memory leaks: els_cmd_ptrs and tgt_cmd_ptrs never freed; sas_portinfo freed without its phy_info array

Summary

mpt_cam_detach() never frees mpt->els_cmd_ptrs or mpt->tgt_cmd_ptrs - no kfree exists anywhere in the driver for either - and frees mpt->sas_portinfo without the separately allocated phy_info array; the SAS config error path leaks phy_info identically. Repeatable heap leak on mpt.ko load/unload cycles; latent while mpt is built into the kernel.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3678 Β· 6 files
FileTypeDescriptionSize
README.md β€” 409 B ↓ raw
VERDICT.md β€” 2.8 KB ↓ raw
fix.diff β€” 977 B view raw
env.txt β€” 281 B view raw
verdict.json β€” 1.7 KB view raw
manifest.json β€” 552 B view raw

DF-3678 β€” mpt_cam detach/error-path leaks: els_cmd_ptrs, tgt_cmd_ptrs, sas phy_info

Severity: Info. mpt_cam_detach (1169-1217) never frees els_cmd_ptrs (alloc 4208) or tgt_cmd_ptrs (alloc 4255), and frees sas_portinfo without its phy_info array (alloc 633; same on the SAS error path 763-767). Repeatable with mpt.ko load/unload. Fix in fix.diff. Guest has no MPT HBA (env.txt) β€” source-verified only.

VERDICT.md
↓ download raw

DF-3678 β€” VERDICT

status: inconclusive (memory leaks at detach; source-certain; no MPT hardware on guest)

Root cause β€” three allocations are never freed anywhere in the driver

  1. mpt->els_cmd_ptrs β€” kmalloc(MPT_MAX_ELS * sizeof(request_t *)) at mpt_cam.c:4208-4209 (mpt_add_els_buffers).
  2. mpt->tgt_cmd_ptrs β€” kmalloc(max * sizeof(request_t *)) at mpt_cam.c:4255-4256 (mpt_add_target_commands). mpt_cam_detach() (mpt_cam.c:1169-1217) deregisters handlers, frees the TMF request and sas_portinfo, the SIMs and paths β€” but never these two arrays (grep across mpt*.c: no kfree of either).
  3. sas_portinfo->phy_info β€” kmalloc(num_phys * sizeof(*phy_info)) at mpt_cam.c:633-634 (mptsas_sas_io_unit_pg0). mpt_cam_detach frees only the portinfo shell (mpt_cam.c:1198-1201), leaking the phy_info array; the error path at mpt_cam.c:763-767 (mpt_read_config_info_sas) has the same leak when mptsas_sas_io_unit_pg0() succeeded in allocating phy_info but a later error aborts the loop (mpt_cam.c:769-791 breaks out and the partially built portinfo is still installed at :792 β€” that one is retained, not leaked; the truly leaked case is mptsas_sas_io_unit_pg0 failing after the phy_info allocation, e.g. mpt_read_extcfg_page error at :625-630, where the caller kfree's portinfo only).

Impact: kernel heap memory leak on every mpt detach (module unload / driver re-attach cycle) and on SAS config-read error paths. With MPT_CAM built into the kernel and never detached this is latent; with mpt.ko load/unload cycles it is a repeatable leak (DoS-by-leak only after many cycles). Severity Info.

Fix

--- a/sys/dev/disk/mpt/mpt_cam.c
+++ b/sys/dev/disk/mpt/mpt_cam.c
@@ -1198,6 +1198,14 @@ mpt_cam_detach(struct mpt_softc *mpt)
    if (mpt->sas_portinfo != NULL) {
+       if (mpt->sas_portinfo->phy_info != NULL) {
+           kfree(mpt->sas_portinfo->phy_info, M_DEVBUF);
+       }
        kfree(mpt->sas_portinfo, M_DEVBUF);
        mpt->sas_portinfo = NULL;
    }
+   if (mpt->tgt_cmd_ptrs != NULL) {
+       kfree(mpt->tgt_cmd_ptrs, M_DEVBUF);
+       mpt->tgt_cmd_ptrs = NULL;
+       mpt->tgt_cmds_allocated = 0;
+   }
+   if (mpt->els_cmd_ptrs != NULL) {
+       kfree(mpt->els_cmd_ptrs, M_DEVBUF);
+       mpt->els_cmd_ptrs = NULL;
+       mpt->els_cmds_allocated = 0;
+   }

plus the matching phy_info free on the error path of mpt_read_config_info_sas().

Guest verdict

inconclusive β€” no MPT hardware; leaks proven by exhaustive grep (no free sites) plus the allocation sites cited above.

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

Free-path diff authored (fix.diff); not exercisable without hardware.

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

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (alloc/free site audit); fix.diff; env.txt

PoC changes

n/a

Verified recommended fix

Free els_cmd_ptrs/tgt_cmd_ptrs in mpt_cam_detach and phy_info alongside sas_portinfo (detach + SAS error path)

Verdict

Source-certain leaks: mpt_cam_detach() (mpt_cam.c:1169-1217) never frees mpt->els_cmd_ptrs (kmalloc at 4208-4209) or mpt->tgt_cmd_ptrs (kmalloc at 4255-4256) β€” exhaustive grep over sys/dev/disk/mpt shows no kfree for either β€” and frees mpt->sas_portinfo (1198-1201) without its separately allocated phy_info array (kmalloc at 633-634); the SAS error path at 763-767 leaks phy_info the same way when mptsas_sas_io_unit_pg0 fails after its allocation. Repeatable heap leak on mpt.ko load/unload cycles (Info severity; latent while built-in). Not executable on this guest (no MPT hardware).