mpt_raid_attach error paths: MPT_UNLOCK of a never-acquired lock (deterministic lockmgr panic) plus csa CCB leak
Summary
If mpt_spawn_raid_thread fails, goto cleanup reaches MPT_UNLOCK although MPT_LOCK is only taken later - lockmgr panics 'LK_RELEASE: no lock held'. On the other error path the csa CCB is never freed. Attach-time kthread ENOMEM with an MPT HBA present: recoverable ENOMEM becomes a kernel panic. Return-directly + free-ccb fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4212 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.2 KB | β raw | |
| VERDICT.md | β | 1.5 KB | β raw | |
| env.txt | β | 992 B | view raw | |
| fix.diff | β | 675 B | view raw | |
| manifest.json | β | 647 B | view raw | |
| verdict.json | β | 1.9 KB | view raw |
DF-4212 β mpt_raid_attach error paths: MPT_UNLOCK on a lock it never took (guaranteed panic) + CCB leak
- File:
sys/dev/disk/mpt/mpt_raid.c - Lines: 283β287, 288, 311, 314β317
- Class: error-path lock protocol violation (CWE-667) β kernel panic; memory leak (CWE-401)
- Hardware gate: LSI MPT Fusion RAID controller, attach-time error (kthread_create ENOMEM)
Bug 1 β unlock without lock (panic)
mpt_raid_attach():
error = mpt_spawn_raid_thread(mpt); /* 283 */
if (error != 0) {
mpt_prt(mpt, "Unable to spawn RAID thread!\n");
goto cleanup; /* 286: MPT_LOCK NOT held */
}
csa = &xpt_alloc_ccb()->csa; /* 288 */
MPT_LOCK(mpt); /* 290 */
...
cleanup: /* 314 */
MPT_UNLOCK(mpt); /* 315: LK_RELEASE */
mpt_raid_detach(mpt);
return (error);
If mpt_spawn_raid_thread() fails (kthread_create ENOMEM,
mpt_raid.c:645), control reaches cleanup without ever executing
MPT_LOCK (taken only at line 290). MPT_UNLOCK is
lockmgr(&mpt->mpt_lock, LK_RELEASE) (sys/dev/disk/mpt/mpt.h:763-764), and
DragonFly's lockmgr panics on releasing an unheld lock:
panic("lockmgr: LK_RELEASE: no lock held") (sys/kern/kern_lock.c:761-768).
So the error path converts a recoverable ENOMEM into a guaranteed kernel
panic during device attach (boot or kldload under memory pressure).
Bug 2 β CCB leak on the other error path
If mpt_register_handler fails (line 292β297), the csa CCB allocated at
line 288 is never freed β cleanup only calls mpt_raid_detach(), which
allocates and frees its own CCB (mpt_raid.c:333, 349). One
xpt_alloc_ccb() leaks per failed attach.
Verification status
untested β hardware-gated (no MPT HBA on the guest, see env.txt; also
requires kthread_create failure). Source-certain: the lock-state arithmetic
is two lines apart and kern_lock.c:768 makes the panic deterministic.
Fix
fix.diff: return directly on spawn failure (nothing to unwind); free csa
before calling mpt_raid_detach on the handler-registration failure.
VERDICT β DF-4212
status: untested (hardware-gated) Β· impact: panic (attach-time, OOM-gated) Β· confidence: certain (source)
Not reproducible on the audit guest: no MPT Fusion HBA (env.txt), and the
trigger additionally needs kthread_create() to fail during attach.
Source proof:
- MPT_LOCK is taken at mpt_raid.c:290, after the spawn-failure goto
cleanup at 283β287; cleanup (314β317) executes MPT_UNLOCK
unconditionally.
- MPT_LOCK/MPT_UNLOCK are plain lockmgr EXCLUSIVE/RELEASE
(sys/dev/disk/mpt/mpt.h:763-764), non-recursive, and DragonFly lockmgr
hard-panics on LK_RELEASE with no lock held
(sys/kern/kern_lock.c:761-768: panic("lockmgr: LK_RELEASE: no lock held")).
- CCB leak: csa allocated at mpt_raid.c:288 is freed only at line 311 on
the success path; the goto cleanup at 296 skips it, and
mpt_raid_detach frees only its own CCB (mpt_raid.c:333/349).
Deterministic panic, but the precondition (attach-time kthread ENOMEM on a
machine with the RAID HBA) makes it Low severity. Fix is trivial and
low-risk; not runtime-validated (no hardware) β fix_status: not_testable.
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_testablediff authored and git-apply-verified against the read-only sys/ tree; runtime fix validation impossible without the triggering hardware on the QEMU guest
findings/poc/DF-4212/fix.diff (git apply --check passed)
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-4212/VERDICT.md, findings/poc/DF-4212/env.txt (guest pciconf: no triggering hardware), findings/poc/DF-4212/fix.diff
PoC changes
no runnable PoC: hardware-gated path absent from the audit guest (env.txt)
Verified recommended fix
return early on spawn failure (nothing to unwind); free csa on the register-failure path
Verdict
mpt_raid_attach takes MPT_LOCK only after mpt_spawn_raid_thread succeeds (mpt_raid.c:290), but the spawn-failure goto cleanup (283-287) reaches MPT_UNLOCK (315) on a lock never acquired -> DragonFly lockmgr panic 'LK_RELEASE: no lock held' (kern_lock.c:768). The other error path (handler registration failure, 292-297) leaks the csa CCB allocated at 288. Both are attach-time error-path defects; hardware-gated (no MPT HBA on guest).
No comments yet.