hpt_attach bus_setup_intr failure kfree()s the newbus-owned IAL_ADAPTER_T softc while it stays linked on gIal_Adapter (use-after-free)
Summary
On IRQ-setup failure the driver frees device_get_softc() memory that newbus owns and never unlinks the adapter from the global gIal_Adapter list (nor undoes init_adapter's interrupt unmask) - later gIal_Adapter walks (ioctls, rescan, worker) and newbus softc reuse dereference freed memory. Attach-time IRQ failure on a present RR1820 (e.g. passthrough VM with exhausted IRQs). Drop-the-kfree fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3923 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.0 KB | β raw | |
| VERDICT.md | β | 1.7 KB | β raw | |
| fix.diff | β | 310 B | view raw | |
| env.txt | β | 1.2 KB | view raw | |
| manifest.json | β | 803 B | view raw | |
| verdict.json | β | 1.8 KB | view raw |
DF-3923 β hpt_attach failure path kfree()s the newbus-owned softc and leaves the freed adapter globally linked
What
sys/dev/raid/hptmv/entry.c:2022-2028 (hpt_attach):
if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, 0,
hpt_intr, pAdapter, &pAdapter->hpt_intr, NULL))
{
hpt_printk(("can't set up interrupt\n"));
kfree(pAdapter, M_DEVBUF); /* <-- frees softc owned by newbus */
return(ENXIO);
}
For a PCI driver the softc (sizeof(IAL_ADAPTER_T), driver_t at entry.c:97-101)
is embedded in the newbus device and returned by device_get_softc(dev)
(entry.c:1992) β it is NOT a driver allocation. init_adapter() (called at
entry.c:2011, succeeding) has already:
- linked pAdapter into the global gIal_Adapter list (entry.c:1280-1287),
- started the MV core (mvSataInitAdapter, entry.c:1349),
- unmasked adapter interrupts (entry.c:1498).
After the kfree: the device still exists with a dangling softc; gIal_Adapter
still points at freed memory. Any later walk of that list β hptproc ioctls
(Kernel_DeviceIoControl, DF-1853 family), RESCAN_DEVICES (ioctl.c:302),
worker-thread SIGSTOP walk (entry.c:2438-2456) β dereferences freed memory.
Newbus itself touches the freed softc on device state changes (probe cycle,
detach, shutdown). Additionally the earlier IRQ-allocation failure path
(entry.c:2016-2020) returns without unlinking the adapter or releasing
mem_res, leaking a half-initialized adapter with interrupts unmasked.
Error-path gated (requires bus_setup_intr/bus_alloc_resource failure on a present RR1820 β e.g. IRQ shortage in a passthrough VM), hardware-gated, but a genuine use-after-free of kernel memory once hit.
Fix
--- a/sys/dev/raid/hptmv/entry.c
+++ b/sys/dev/raid/hptmv/entry.c
@@ -2023,7 +2023,6 @@ hpt_attach(device_t dev)
{
hpt_printk(("can't set up interrupt\n"));
- kfree(pAdapter, M_DEVBUF);
return(ENXIO);
}
plus proper teardown in init_adapter's caller (unlink from gIal_Adapter,
release mem_res/irq) β see fix.diff.
DF-3923 VERDICT
status: not_reproduced (hardware-gated error path) | impact observed: none (potential: UAF of kernel memory) | source certainty: likely
Trace
- entry.c:1992
IAL_ADAPTER_T *pAdapter = device_get_softc(dev);β newbus softc (driver_t size entry.c:100); only kmalloc'd if softc were NULL (entry.c:2000-2004), which never happens for an attached PCI device. - entry.c:2011 init_adapter succeeds β adapter linked into gIal_Adapter (entry.c:1280-1287), MV core initialized, interrupts unmasked (entry.c:1498).
- entry.c:2026
kfree(pAdapter, M_DEVBUF)on bus_setup_intr failure frees memory newbus still owns; gIal_Adapter list retains the dangling pointer (no unlink anywhere on this path). - Consumers of gIal_Adapter: ioctl.c:302 (RESCAN_DEVICES walk), hptproc.c/Kernel_DeviceIoControl, entry.c:2438-2456 (worker SIGSTOP walk), launch_worker_thread (entry.c:2486). Newbus also reuses the softc on the next probe of the same devclass unit.
Why not reproduced
Needs a present RR1820 whose IRQ setup fails at attach β no such hardware on the audit guest (env.txt). Confidence "likely": the double-ownership/free is unambiguous, but reaching it requires a specific attach failure on real hardware.
Fix validation
Not possible without the controller. fix.diff removes the erroneous kfree and adds teardown.
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_testablefix.diff removes the erroneous kfree and releases resources; cannot validate without hardware
fix.diff in this pack; never applied to sys/
Confirmed kernel references
Detail
Exploit chain
IRQ setup failure at attach -> freed softc dangling on gIal_Adapter + newbus device -> later ioctl/rescan/probe UAF (crash-class, privileged contexts)
Evidence (decisive lines)
VERDICT.md ownership trace (entry.c:1992 vs 2026; 1280-1287 link)
PoC changes
n/a (fresh pack)
Verified recommended fix
Drop the kfree of the newbus softc and release the IRQ resource on failure
Verdict
On bus_setup_intr failure hpt_attach kfree()s pAdapter (entry.c:2026) which is the newbus-allocated softc (device_get_softc, entry.c:1992; driver_t size entry.c:100) - not driver memory. init_adapter already linked it into gIal_Adapter (entry.c:1280-1287) and unmasked interrupts (entry.c:1498), so post-failure any gIal_Adapter walk (ioctl.c:302, hptproc, worker entry.c:2438-2456) or newbus softc reuse dereferences freed memory. Requires an attach-time IRQ failure on real RR1820 hardware; not reproducible on the audit guest.
No comments yet.