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

Kernel heap info leak via unbounded copyout of oversized outbuffer

  • File: sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c
  • Lines: 1289, 1290, 1293, 1301, 1302, 1303, 1304, 1305
  • Severity: Low
  • CVSS: CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U:C:L/I:N/A:N
  • CWE: CWE-200 Exposure of Sensitive Information
  • Confidence: likely

Summary

hpt_ioctl kmallocs nOutBufferSize bytes (M_DEVBUF, no M_ZERO) for the outbuffer and then, on success, copyout()s the full nOutBufferSize to user space β€” not the count of bytes ldm actually wrote (which the OSM never learns).

A caller passing nOutBufferSize larger than the ioctl's required output size receives the unused tail of the kmalloc'd buffer, which contains stale M_DEVBUF heap contents (kernel pointers, file names, attacker-uncontrolled but sensitive data).

Root cause

  • Line 1290: ioctl_args.lpOutBuffer = kmalloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK); β€” no M_ZERO flag, so the buffer starts out containing whatever was last freed into the M_DEVBUF slab.
  • The closed-source ldm_ioctl writes only as many bytes as each dwIoControlCode requires (typically sizeof(CONTROLLER_INFO), sizeof(LOGICAL_DEVICE_INFO_V3), etc.).
  • Lines 1302-1305: if (piop->nOutBufferSize) { if (copyout(ioctl_args.lpOutBuffer, (void*)piop->lpOutBuffer, piop->nOutBufferSize)) goto invalid; } copies the entire user-supplied size back, exposing the unwritten tail.

Threat

Caller is root (file mode 0600), but the leak crosses the kernel/user boundary for data the caller could not otherwise see β€” useful for KASLR bypass and for revealing recently-freed kernel object pointers when chained with heap-grooming primitives.

Each call leaks (nOutBufferSize - actual_size) bytes of heap.

Zero the outbuffer on allocation, or copy out only the bytes ldm reports via lpBytesReturned (falling back to nOutBufferSize only when lpBytesReturned is unset).

--- a/sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c
+++ b/sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c
@@ -1289,7 +1289,8 @@ static int hpt_ioctl(struct dev_ioctl_args *ap)
        if (ioctl_args.nOutBufferSize) {
-           ioctl_args.lpOutBuffer = kmalloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK);
+           ioctl_args.lpOutBuffer = kmalloc(ioctl_args.nOutBufferSize,
+                           M_DEVBUF, M_WAITOK | M_ZERO);
            if (!ioctl_args.lpOutBuffer)
                goto invalid;
        }

And additionally cap the copyout to *lpBytesReturned when it is smaller than nOutBufferSize.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1565 Β· 4 files
FileTypeDescriptionSize
fix.diff suggested-fix git-apply-able fix for the cited bug 484 B view raw
VERDICT.md verdict source-confirmation analysis 1.0 KB ↓ raw
build.sh build-script N/A (source-only) 65 B view raw
run.sh run-script N/A (source-only) 89 B view raw
VERDICT.md verdict source-confirmation analysis
↓ download raw

DF-1565 VERDICT

Verdict: REPRODUCED (source-confirmed)

Impact: Low (driver-level NULL deref / OOB / leak / DoS β€” hardware-gated)

Mechanism: hpt27xx_osm_bsd.c:1290 ioctl_args.lpOutBuffer = kmalloc(nOutBufferSize, M_DEVBUF, M_WAITOK) NO M_ZERO. ldm_ioctl writes only the ioctl-required bytes (sizeof(CONTROLLER_INFO) etc). 1302-1305 copyout(l

Citation: sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c:1289-1305

Fix: Applied fix.diff β€” compiles in batch kernel build (rc=0, -Werror).

Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.

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

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.diff compiled in batch kernel build rc=0 -Werror

fix.diff compiled in batch kernel build rc=0 -Werror
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none (Low severity)

Evidence (decisive lines)

Source-confirmed: kmalloc without M_ZERO + full-size copyout leaks heap (hpt27xx_osm_bsd.c:1290,1303)

Verified recommended fix

Source-confirmed: kmalloc without M_ZERO + full-size copyout leaks heap (hpt27xx_osm_bsd.c:1290,1303)

Verdict

Source-confirmed: kmalloc without M_ZERO + full-size copyout leaks heap (hpt27xx_osm_bsd.c:1290,1303)