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

md_get_mbuf() ignores md_get_mem() failure (silent short copy / INVARIANTS panic) and md_done() leaves md_cur/md_pos dangling

Field Value
ID DF-2907
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
CWE CWE-252 / CWE-459
File sys/kern/libmchain/subr_mchain.c
Lines 511-521 (esp. :518), 323-330
Area libmchain (legacy smb consumer)
Confidence likely
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket legacy
Reported pending
Known CVE none
CVE match novel

Summary

md_get_mbuf (:511-521) ignores the return of md_get_mem(mdp, NULL, size, MB_MZERO) at :518, so if size exceeds the remaining chain the caller still gets success with a short mbuf (on INVARIANTS kernels m_copym panics first via KASSERT). Separately, md_done (:323-330) clears only md_top, leaving md_cur/md_pos pointing at freed mbufs β€” a dangling-state hazard; in-tree dereference is currently prevented because smb_iod_waitrq only returns error==0 after a fresh record was attached, and every md_done caller re-inits before parsing, but any future caller that parses after a terminal md_done gets a UAF read with an attacker-groomable u_int count underflow in md_get_mem (:478-486). Latent/hardening. Fix: check md_get_mem's return in md_get_mbuf; clear md_cur/md_pos in md_done (already included in DF-2905's fix.diff).

Timeline

  • 2026-09-02 Discovered during pass-2 audit of subr_mchain.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2907 Β· 11 files
FileTypeDescriptionSize
README.md β€” 706 B ↓ raw
VERDICT.md β€” 1.9 KB ↓ raw
build.sh β€” 72 B view raw
dfv_boom.c β€” 3.9 KB view raw
env.txt β€” 401 B view raw
fix.diff β€” 1.7 KB view raw
fix_run.log β€” 264 B view raw
manifest.json β€” 708 B view raw
run.log β€” 468 B view raw
run.sh β€” 120 B view raw
verdict.json β€” 2.3 KB view raw

DF-2907 PoC evidence pack

What

md_get_mbuf ignores md_get_mem failure; md_done leaves md_cur/md_pos dangling.

Build

make (KMOD dfv_boom with KERNBUILDDIR)

Run

kldload smbfs; kldload dfv_boom.ko; sysctl -w dfvboom.m2907=1

Expected

safe form: md_done leaves md_cur/md_pos dangling + stale m_len read; panic form: panic: m_copym: length > size of mbuf chain

Guest: DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:04 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 All logs are full untrimmed captures unless noted. fix.diff is the git-apply-able verified fix (authored after verification; never applied to the audit tree).

VERDICT.md
↓ download raw

DF-2907 - verification verdict

Status: reproduced | reproduced: 1 | impact: panic | confidence: certain

Both halves reproduced on the stock INVARIANTS kernel. (1) Oversize fetch: md_get_mbuf(mdp, 128) against a 64-byte chain panics with panic: m_copym: length > size of mbuf chain - the ignored md_get_mem return at subr_mchain.c:518 lets the call proceed into m_copym with an unsatisfiable length (backtrace: m_copym <- md_get_mbuf <- sysctl trigger); on non-INVARIANTS kernels m_copym breaks with a short copy and the caller gets silent success with a short mbuf - the production form of the claim. (2) md_done leaves md_cur=0xfffff801174d2600 and md_pos dangling over the freed chain (md_top cleared only), and a stale read through md_cur->m_len after md_done returned 64 - the UAF read executed. Fix (check md_get_mem; clear md_cur/md_pos) A/B validated on the fix-all kernel.

Evidence pointers

df2907p_panic.txt: panic m_copym length > size of mbuf chain via md_get_mbuf; run.log: md_done dangling pointers + stale read 64

Kernel references

PoC changes vs the filing sketch

drove the library from a kld harness (needs smbfs.ko loaded for mchain symbols)

Fix

recommendation: check md_get_mem return; clear md_cur/md_pos in md_done

fix status: fixed

see fix_baseline_reproduced fields; A/B on fix-all kernel returned EBADRPC instead of panic

Guest: DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:04 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

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

A/B on fix kernel #2: oversize md_get_mbuf(128) returns 72 (EBADRPC), no panic, guest alive. IMPORTANT: the first fix revision (check md_get_mem AFTER m_copym) did NOT survive A/B - the INVARIANTS KASSERT fires inside m_copym before any post-check; the validated fix pre-computes the remaining chain bytes and rejects before m_copym.

↓ fix.diffper-fix-DF-2907

Confirmed kernel references

Detail

Evidence (decisive lines)

df2907p_panic.txt: panic m_copym length > size of mbuf chain via md_get_mbuf; run.log: md_done dangling pointers + stale read 64

PoC changes

drove the library from a kld harness (needs smbfs.ko loaded for mchain symbols)

Verified recommended fix

check md_get_mem return; clear md_cur/md_pos in md_done

Verdict

Both halves reproduced on the stock INVARIANTS kernel. (1) Oversize fetch: md_get_mbuf(mdp, 128) against a 64-byte chain panics with panic: m_copym: length > size of mbuf chain - the ignored md_get_mem return at subr_mchain.c:518 lets the call proceed into m_copym with an unsatisfiable length (backtrace: m_copym <- md_get_mbuf <- sysctl trigger); on non-INVARIANTS kernels m_copym breaks with a short copy and the caller gets silent success with a short mbuf - the production form of the claim. (2) md_done leaves md_cur=0xfffff801174d2600 and md_pos dangling over the freed chain (md_top cleared only), and a stale read through md_cur->m_len after md_done returned 64 - the UAF read executed. Fix (check md_get_mem; clear md_cur/md_pos) A/B validated on the fix-all kernel.