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

Infinite recursion in mpt_configure_ioc due to tn++ post-increment bypasses retry limit -> stack overflow

Summary

mpt_configure_ioc at mpt.c:2630: guard if(tn==MPT_MAX_TRYS=3) return -1. Three recursive calls at :2645/:2652/:2795 use mpt_configure_ioc(mpt,tn++,1). C post-increment evaluates to pre-increment value -> always passes tn=0 -> guard never fires. Malicious/buggy HBA that fails init -> unbounded recursion -> kernel stack overflow panic at boot/hotplug. Fix: change tn++ to tn+1.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1278 Β· 8 files
FileTypeDescriptionSize
trigger_analysis.c trigger-source documentation marker β€” no runtime trigger possible without MPT HBA 941 B view raw
fix.diff suggested-fix tn++ -> tn+1 at three recursive call sites in mpt_configure_ioc 909 B view raw
build.sh build-script syntax-checks the marker 432 B view raw
run.sh run-script documents INCONCLUSIVE status 647 B view raw
combined_build.log build-log full X86_64_GENERIC rebuild log with this fix applied (combined with DF-1279/1280/1285/1287); rc=0 5.6 MB ↓ download
env.txt environment uname, pciconf -l, kldstat -v 1015 B view raw
README.md readme human-readable summary 2.2 KB ↓ raw
VERDICT.md verdict detailed source-level analysis 2.8 KB ↓ raw
README.md readme human-readable summary
↓ download raw

DF-1278 β€” Infinite recursion in mpt_configure_ioc (tn++ post-increment)

Finding

mpt_configure_ioc at sys/dev/disk/mpt/mpt.c:2623 retries failed init via three recursive self-calls at lines 2645, 2652, and 2795. All three pass tn++ as the recursive argument. C post-increment evaluates to the current value of tn and only increments the local afterward, so the recursion always forwards tn == 0. The retry-limit guard at line 2630 (if (tn == MPT_MAX_TRYS /* == 3 */) return (-1);) therefore never fires. A buggy or malicious LSI MPT/Fusion HBA that fails any of mpt_reset, mpt_get_iocfacts, or mpt_get_portfacts causes unbounded recursion that overflows the kernel stack at attach / hot-plug time.

Fix

Replace tn++ with tn + 1 at all three recursive call sites. The tn local then correctly advances by one each retry, the guard at line 2630 fires after 3 attempts, and the function returns -1 instead of recursing forever.

Verification on this guest

  • The mpt driver is statically compiled into X86_64_GENERIC (device mpt in sys/config/X86_64_GENERIC:93) and shows up in kldstat -v (pci/mpt, mpt_core, …).
  • The QEMU guest has no LSI MPT/Fusion PCI device (pciconf -l lists only i440FX/PIIX/ACPI/virtio-net/virtio-blk/std-VGA). The driver's mpt_pci_probe never matches, so mpt_attach -> mpt_configure_ioc is never called. The bug is therefore not runtime-triggerable on this guest.
  • Source-level confirmation by reading the cited lines:
  • mpt.c:2630 β€” the guard if (tn == MPT_MAX_TRYS) return (-1);.
  • mpt.c:2645 β€” return (mpt_configure_ioc(mpt, tn++, 1)); on failed reset.
  • mpt.c:2652 β€” same on failed mpt_get_iocfacts.
  • mpt.c:2795 β€” same on failed mpt_get_portfacts.
  • Fix verified to compile by applying this fix.diff together with the four other driver fixes (DF-1279/1280/1285/1287) and rebuilding X86_64_GENERIC β€” make -j6 nativekernel succeeded.

Realistic impact ceiling

Hardware-attacker (PCIe/Thunderbolt/external chassis) DoS: kernel stack overflow panic. CVSS vector reflects AV:P. Not exploitable from an unprivileged user without first presenting a malicious HBA.

VERDICT.md verdict detailed source-level analysis
↓ download raw

VERDICT β€” DF-1278

Status

INCONCLUSIVE (source-confirmed; not runtime-triggerable on this guest).

Mechanism (source-confirmed)

mpt_configure_ioc at sys/dev/disk/mpt/mpt.c:2623 is the per-controller init routine. It retries failed init steps via three recursive self-calls:

Site Triggered when
mpt.c:2645 mpt_reset() fails
mpt.c:2652 mpt_get_iocfacts() fails
mpt.c:2795 mpt_get_portfacts() fails on any port

All three pass tn++ (C post-increment) as the argument. Post-increment yields the current value of tn and only updates the local afterward, so the recursion always forwards tn == 0. The retry-limit guard at mpt.c:2630 (if (tn == MPT_MAX_TRYS) return (-1);, with MPT_MAX_TRYS == 3 per mpt.c:111) therefore never fires.

A buggy or malicious LSI MPT/Fusion HBA that fails any of those three sub-calls will recurse unbounded and overflow the kernel stack.

Fix

Replace tn++ with tn + 1 at all three sites. The tn local then correctly advances by one per retry, the guard fires after 3 attempts, and the function returns -1.

Verification on this guest

  • mpt is statically compiled into X86_64_GENERIC (sys/config/X86_64_GENERIC:93 β€” device mpt).
  • kldstat -v confirms: mpt_core, mpt_cam, pci/mpt, mpt_raid, mpt_user.
  • pciconf -l lists only i440FX/PIIX3/PIIX4/virtio-net/virtio-blk/std-VGA. No LSI MPT/Fusion PCI device is present, so mpt_pci_probe never matches, mpt_attach is never called, and mpt_configure_ioc never executes.
  • The bug is therefore not runtime-triggerable on this guest.
  • Fix validation: applied this fix.diff together with the four other driver fixes (DF-1279/1280/1285/1287) to a clean with-src snapshot, rebuilt X86_64_GENERIC with make -j6 nativekernel, build exited rc=0. Full build log: combined_build.log.

Exploit chain

None. The primitive is kernel-stack-overflow panic via unbounded recursion, reachable only at HBA attach time. No userspace trigger exists on this guest.

Realistic impact ceiling

Hardware-attacker DoS (PCIe / Thunderbolt / external chassis presenting a malicious or faulty MPT/Fusion HBA). CVSS: AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.

PoC changes

The PoC folder was empty; added trigger_analysis.c (documentation marker), build.sh, run.sh, README.md, this VERDICT.md, fix.diff, manifest.json, and the combined combined_build.log.

Matches the finding proposal: change tn++ to tn + 1 at mpt.c:2645, mpt.c:2652, and mpt.c:2795. See fix.diff.

Fix status

not_testable β€” the bug requires absent hardware. The fix.diff was verified to apply (patch -p1 --forward) and compile cleanly into a rebuild of X86_64_GENERIC together with four other fixes (combined build rc=0).

Fix verification

not_testable

compile validated

nativekernel rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. mpt_configure_ioc tn++ post-increment -> infinite recursion. mpt in GENERIC, no MPT HW.