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

Hostile SCSI target panics the kernel via MESSAGE REJECT of the driver's own MSG_ABORT/MSG_NOOP: amdsentmsg panic("Inconsistent msg buffer")

Summary

After an unexpected reselection amd_Reselect queues msgout=[MSG_ABORT] and amd_MsgOutPhase1 substitutes [MSG_NOOP] when msgout_len==0; if the target replies MESSAGE REJECT (any target may legally reject optional messages), amdsentmsg walks msgout_buf and hits the terminal panic() because MSG_ABORT/MSG_NOOP are not in its recognized byte set. Verified by compiling a verbatim copy of amdsentmsg on the guest and driving it with both real driver states - both select the panic branch. Deterministic kernel DoS from interrupt context; driver ships in GENERIC. Bail-out fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4042 Β· 12 files
FileTypeDescriptionSize
amd_walks.c β€” 10.2 KB view raw
build.sh β€” 65 B view raw
run.sh β€” 89 B view raw
build.log β€” 184 B view raw
run.log β€” 2.0 KB view raw
env.txt β€” 832 B view raw
fix.diff β€” 289 B view raw
fix_build.log β€” 1.2 KB view raw
README.md β€” 1.1 KB ↓ raw
VERDICT.md β€” 2.8 KB ↓ raw
manifest.json β€” 917 B view raw
verdict.json β€” 3.9 KB view raw

DF-4042 β€” Hostile SCSI target panics the kernel via MESSAGE REJECT of the driver's own MSG_ABORT/MSG_NOOP: amdsentmsg panic("Inconsistent msg buffer")

File: sys/dev/disk/amd/amd.c Severity: Medium | Class: CWE-670 Always-Incorrect Control Flow Implementation (kernel panic on hostile input) Status: hardware-gated β€” source-certain; runtime reproduction impossible on the audit guest (no Polaris GPU / no AMD53C974 HBA β€” see env.txt). Verdict: inconclusive, confidence certain.

Build & run (on the DragonFly guest)

./build.sh     # compiles the demonstrator (uses the guest's kernel headers)
./run.sh       # reproduces the exact index arithmetic / branch selection

Expected: the DF-4042 section of run.log shows the OOB offsets / panic-branch selection / fault. Full guest details in env.txt.

Fix validation

fix.diff applied (with all DF-4036..DF-4044 patches together) to a clean guest /usr/src copy; make nativekernel KERNCONF=X86_64_GENERIC completed with 0 errors under -Werror (see fix_build.log β€” amd.o recompiled). Sources restored to pristine afterwards (md5-verified).

VERDICT.md
↓ download raw

DF-4042 VERDICT β€” Hostile SCSI target panics the kernel via MESSAGE REJECT of the driver's own MSG_ABORT/MSG_NOOP: amdsentmsg panic("Inconsistent msg buffer")

Bottom line

Source-certain kernel panic from device-fed message flow: after an unexpected reselection amd_Reselect queues msgout=[MSG_ABORT] (amd.c:1839-1840) and amd_MsgOutPhase1 substitutes [MSG_NOOP] when msgout_len==0 (amd.c:1745-1748); if the target then replies MESSAGE REJECT (any target may legally reject any optional message), amdparsemsg (amd.c:1246) -> amdhandlemsgreject (amd.c:1467) -> amdsentmsg walks msgout_buf and hits the terminal else panic("amdsentmsg: Inconsistent msg buffer") at amd.c:1435 because MSG_ABORT(0x06)/MSG_NOOP(0x08) are not in its recognized set (identify/REJECT/2-byte tag/EXT only). Verified by compiling the verbatim amdsentmsg copy on the guest and driving it with the two real driver states β€” both select the panic branch (run.log DF-4042). amd(4) is in the GENERIC kernel (X86_64_GENERIC:88); trigger requires a hostile/compromised SCSI target (or emulation), so runtime reproduction on this guest (no AMD53C974 HBA) is impossible -> inconclusive at runtime, source certain.

Exploit chain

hostile target: reselect an idle ID (driver queues ABORT) -> send MESSAGE REJECT byte in MSG IN -> amdhandlemsgreject -> amdsentmsg walk -> panic at amd.c:1435 (kernel DoS from interrupt context)

Why not reproduced on the guest

The audit guest has no AMD53c974-compatible SCSI HBA (env.txt); amd(4) is compiled into the GENERIC kernel but never attaches, so the hostile-target message flows cannot be exercised at runtime. The exact walks were compiled from the driver source (verbatim amdsentmsg copy / exact branch ladder / exact store) and driven with the real driver states (run.log); the fix is compile-validated (fix_build.log).

Negative results recorded alongside (pass-2 depth)

Kills proven in run.log: msgin_buf[6] per-byte walk max index 4 (bounded); SRB_array[msgin_buf[1]] 0..255 fits SRB_array[256] exactly; msgout shift bcopy fits msgout_buf[6]; amdtimeout/callout family is #if 0 dead code (no timeout-vs-intr race); EEPROM word walks fit eepromBuf[128] exactly; XPT_RESET_BUS ACBFlag race can only strand CCBs (hang, logged, not filed).

Fix

Replace the panic() with a bail-out break (treat as not found) β€” the buffer is driver-own, never worth dying over (fix.diff). Applied and compile-validated on the guest (fix_build.log); sys/ tree never modified by the audit.

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 no→ patch + rebuild →patched clean

fixed (compile-validated): all nine patches applied together to the clean guest /usr/src copy (polaris10_smumgr.c md5 6f39bb32..->19a2b278.., amd.c f577a330..->54ce1518..), make -j4 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with 0 compile errors under -Werror; the patched polaris10_smumgr.o (amdgpu module) and amd.o (GENERIC kernel) both recompiled. Runtime re-test impossible on this guest (device absent). Sources restored to pristine and md5-verified after validation.

findings/poc/DF-4042/fix.diff; findings/poc/DF-4042/fix_build.log (build banner + compile lines + 0 errors)
↓ fix.diffDragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (nativekernel X86_64_GENERIC rebuilt with all DF-4036..DF-4044 patches; 0 errors under -Werror; see fix_build.log)

Confirmed kernel references

Detail

Exploit chain

hostile target: reselect an idle ID (driver queues ABORT) -> send MESSAGE REJECT byte in MSG IN -> amdhandlemsgreject -> amdsentmsg walk -> panic at amd.c:1435 (kernel DoS from interrupt context)

Evidence (decisive lines)

run.log section DF-4042 (verbatim-copy walk trace: 0x06 and 0x08 both hit the panic branch; contrast EXT/SDTR case clean); VERDICT.md; fix_build.log; env.txt

PoC changes

Pass-2 reviewer authored demonstrator compiling the kernel's own headers (smu74.h/smu74_discrete.h packed, or a verbatim copy of the driver's amdsentmsg/parsemsg arms) so struct geometry and branch selection are the kernel's; fix.diff generated against the pristine file and compile-validated via full nativekernel rebuild on the guest (shared build with DF-4036..DF-4044, fix_build.log).

Verified recommended fix

Replace the panic() with a bail-out break (treat as not found) β€” the buffer is driver-own, never worth dying over (fix.diff)

Verdict

Source-certain kernel panic from device-fed message flow: after an unexpected reselection amd_Reselect queues msgout=[MSG_ABORT] (amd.c:1839-1840) and amd_MsgOutPhase1 substitutes [MSG_NOOP] when msgout_len==0 (amd.c:1745-1748); if the target then replies MESSAGE REJECT (any target may legally reject any optional message), amdparsemsg (amd.c:1246) -> amdhandlemsgreject (amd.c:1467) -> amdsentmsg walks msgout_buf and hits the terminal else panic("amdsentmsg: Inconsistent msg buffer") at amd.c:1435 because MSG_ABORT(0x06)/MSG_NOOP(0x08) are not in its recognized set (identify/REJECT/2-byte tag/EXT only). Verified by compiling the verbatim amdsentmsg copy on the guest and driving it with the two real driver states β€” both select the panic branch (run.log DF-4042). amd(4) is in the GENERIC kernel (X86_64_GENERIC:88); trigger requires a hostile/compromised SCSI target (or emulation), so runtime reproduction on this guest (no AMD53C974 HBA) is impossible -> inconclusive at runtime, source certain.