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

Divide-by-zero in UVD decode message parser crashes the kernel

Summary

amdgpu_uvd.c:524-526 fs_in_mb = (width/16) * ALIGN(height/16,2) from msg[6]/msg[7] user-controlled. H264 (535-562) and H264-Perf (614-640) compute num_dpb_buffer=8100/fs_in_mb etc. width<16 or height<16 -> fs_in_mb=0 -> div by 0 #DE panic. Post-switch width>pitch check at 681 too late. Trigger: unprivileged DRI render node -> UVD decode IB with msg[6]=0. Affects CIK/VI/Polaris/Vega. Fix: check !width || !height || !fs_in_mb before switch.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1595 Β· 8 files
FileTypeDescriptionSize
README.md readme human-readable summary 1.7 KB ↓ raw
VERDICT.md verdict full source-level analysis + fix-validation result 2.7 KB ↓ raw
fix.diff suggested-fix git-apply-able unified diff fixing the cited bug 888 B view raw
fix_apply.log apply-log patch --dry-run --forward output proving fix.diff applies cleanly on with-src 547 B view raw
env.txt environment uname + guest PCI inventory (no relevant HW) 778 B view raw
build.sh build-script echo pointer to kernel rebuild path 362 B view raw
run.sh run-script echo pointer to VERDICT.md 329 B view raw
fix_build.log fix-build-log tail of combined nativekernel build (rc=0) validating all 30 patches compile 7.2 KB view raw
README.md readme human-readable summary
↓ download raw

PoC DF-1595: amdgpu_uvd divide-by-zero via small width/height

Class: Divide-by-zero (#DE) -> kernel panic Cited site: sys/dev/drm/amd/amdgpu/amdgpu_uvd.c:524-526,535-562,614-640,681

Reproduction status

HW/module gated β€” cannot be live-triggered on the audit QEMU guest.

The audit guest has only virtio + PIIX3 PCI devices (pciconf -lv shows no AMD/Intel GPU, no ath NIC, no AdvanSys SCSI, no mfi/tws/mrsas RAID, etc.), so the cited code path is not reachable at runtime on this guest.

The bug is confirmed at the source level by tracing the cited path:line in sys/dev/drm/amd/amdgpu/amdgpu_uvd.c and confirming the vulnerable code is present in the master DEV kernel tree. The fix.diff in this folder is validated to apply cleanly and compile under -Werror (see VERDICT.md).

Mechanism

amdgpu_uvd_cs_msg_decode: fs_in_mb = (width/16) * ALIGN(height/16,2) from msg[6]/msg[7] user-controlled. H264 (535-562) and H264-Perf (614-640) compute num_dpb_buffer=8100/fs_in_mb etc. width<16 or height<16 -> fs_in_mb=0 -> div by 0 #DE panic. Post-switch width>pitch check at 681 too late.

Realistic impact ceiling (on suitable HW)

unprivileged DoS (kernel panic) via UVD decode IB with msg[6]=0; affects CIK/VI/Polaris/Vega

Fix

Before the switch, reject !width || !height || width<16 || height<16 || !fs_in_mb.

See fix.diff for the git-apply-able patch.

How to validate the fix

scp -F dfbsd-qemu/config fix.diff dfbsd:/root/DF-1595.diff
ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src && patch -p1 --forward < /root/DF-1595.diff'
ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC'
# rc=0 expected; see fix_apply.log + fix_build.log in this folder.
VERDICT.md verdict full source-level analysis + fix-validation result
↓ download raw

VERDICT β€” DF-1595: amdgpu_uvd divide-by-zero via small width/height

Verdict

INCONCLUSIVE (HW/module gated) β€” source-level confirmed, fix validated.

The bug is real and present in master DEV source at sys/dev/drm/amd/amdgpu/amdgpu_uvd.c:524-526,535-562,614-640,681, but the affected driver attaches only to hardware not present in the audit QEMU guest (only virtio+PIIX3 PCI devices, no AMD/Intel GPUs, no ath NICs, no AdvanSys SCSI, no mfi/tws/mrsas RAID, etc.), so it cannot be live-triggered here. The fix.diff applies cleanly and the patched kernel compiles with -Werror (combined build rc=0; see fix_apply.log).

Mechanism (cited path β†’ primitive β†’ effect)

amdgpu_uvd_cs_msg_decode: fs_in_mb = (width/16) * ALIGN(height/16,2) from msg[6]/msg[7] user-controlled. H264 (535-562) and H264-Perf (614-640) compute num_dpb_buffer=8100/fs_in_mb etc. width<16 or height<16 -> fs_in_mb=0 -> div by 0 #DE panic. Post-switch width>pitch check at 681 too late.

Reachability on this guest

No β€” sys/dev/drm/amd/amdgpu/amdgpu_uvd.c:524-526 is in a driver/module that only attaches to hardware absent from the audit guest. The trigger requires the relevant PCI device (or, for VBIOS-driven GPU paths, the actual GPU + a crafted VBIOS loaded by root or via VFIO passthrough).

Phase 6 β€” escalation potential

This is a Divide-by-zero primitive. On real hardware it could be triggered by an unprivileged user (via crafted packets for the NIC findings, via DRM ioctls for the GPU findings, via CAM/pass for the SCSI findings). On this guest there is no live primitive to convert. Per Phase 6 rules this is the "dead/unreachable at runtime on this guest" hard blocker; the primitive is proven at the source/harness level (the cited path:line is real and unfixed in master).

Realistic impact ceiling on suitable HW: unprivileged DoS (kernel panic) via UVD decode IB with msg[6]=0; affects CIK/VI/Polaris/Vega.

Phase 8 β€” fix validation

fix.diff is a minimal, targeted fix at the root cause confirmed above.

  • Applied cleanly with patch -p1 --forward (verified in fix_apply.log).
  • Compiled with -Werror as part of the combined make -j6 nativekernel KERNCONF=X86_64_GENERIC build (kernel build rc=0; see manifest.json).
  • For HW-gated findings the patched code path is not exercisable on this guest, so the fix is validated at the apply + compile level only.

Fix approach: Before the switch, reject !width || !height || width<16 || height<16 || !fs_in_mb.

PoC changes

Source-level confirmation only; no userspace harness written because the bug cannot be exercised on this guest without the relevant HW. The placeholder build.sh/run.sh echo pointers to VERDICT.md and the module/kernel rebuild path.

Confirmed kernel references

Detail

Exploit chain

none β€” HW-gated. Primitive is an unprivileged DoS (kernel panic) via UVD decode IB with msg[6]=0.

Evidence (decisive lines)

Source: sys/dev/drm/amd/amdgpu/amdgpu_uvd.c:524 β€” width_in_mb = width/16; :526 β€” fs_in_mb = width_in_mb * height_in_mb; :539 β€” num_dpb_buffer = 8100 / fs_in_mb (div by zero); :681 β€” width > pitch check too late. Guest has no AMD GPU. fix.diff rejects !width || !height || width<16 || height<16 || !fs_in_mb before the switch.

PoC changes

Created evidence pack from scratch: README.md, VERDICT.md, build.sh, run.sh, env.txt, fix.diff, fix_apply.log, fix_build.log, manifest.json.

Verified recommended fix

Before the switch in amdgpu_uvd_cs_msg_decode, reject !width || !height || width<16 || height<16 || !fs_in_mb. Full diff in findings/poc/DF-1595/fix.diff.

Verdict

INCONCLUSIVE (HW-gated). Bug confirmed at source level: amdgpu_uvd.c:524-526 fs_in_mb = (width/16) * ALIGN(height/16,2) from msg[6]/msg[7] user-controlled. H264 (:535-562) and H264-Perf (:614-640) compute num_dpb_buffer=8100/fs_in_mb etc. width<16 or height<16 -> fs_in_mb=0 -> div by 0 #DE panic. Post-switch width>pitch check at :681 too late. amdgpu UVD only on CIK/VI/Polaris/Vega; audit guest has no AMD GPU.