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

Heap OOB read in amdgpu_dm_set_degamma_lut via unvalidated blob size before __is_lut_linear

Summary

amdgpu_dm_set_degamma_lut (amdgpu_dm_color.c:259-260): lut=(struct drm_color_lut*)blob->data then immediately __is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES=4096) BEFORE blob size validated. Blob size not computed until line 270 (lut_size=blob->length/sizeof(struct drm_color_lut)). DRM core (drm_atomic_uapi.c:436-441) only enforces blob->length%sizeof(drm_color_lut)==0 NOT entry count. Attacker creates 8-byte (1-entry) degamma LUT blob via DRM_IOCTL_MODE_CREATEPROPBLOB; sets CRTC DEGAMMA_LUT property to it; includes plane update on that CRTC in atomic request. Call chain: amdgpu_dm_atomic_check (amdgpu_dm.c:5635) -> dm_update_planes_state enable=true (5700) -> fill_plane_attributes (5470) -> amdgpu_dm_set_degamma_lut (2454) -> __is_lut_linear(lut,4096) reads lut[0..4095] = 32768 bytes from 8-byte allocation -> 32KB OOB heap read crossing unmapped pages -> kernel panic (reliable local DoS). Read data traverses adjacent slab objects (potential weak info-leak via boolean return observable as atomic-check success/failure). Contrast amdgpu_dm_set_regamma_lut (142-160) correctly computes+validates lut_size BEFORE any LUT access -- proving ordering bug not design choice. Attacker: /dev/dri/cardN access (video group/logind) + DRM master. AV:L/PR:L/AC/L, C:L/A:H. Fix: compute+validate lut_size before __is_lut_linear; pass validated lut_size not hardcoded 4096.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2083 Β· 6 files
FileTypeDescriptionSize
VERDICT.md verdict source-level analysis with path:line citations 1.6 KB ↓ raw
reachability.txt environment guest PCI/device survey proving no required HW 1.6 KB view raw
fix.diff suggested-fix git-apply-able fix (validated: applies clean) 952 B view raw
build.sh build-log documents HW requirement 550 B view raw
run.sh run-log documents HW requirement 272 B view raw
env.txt environment guest uname and environment 491 B view raw
VERDICT.md verdict source-level analysis with path:line citations
↓ download raw

DF-2083: Heap OOB read in amdgpu_dm_set_degamma_lut via unvalidated blob size

Verdict: NOT REPRODUCED (HW-gated) β€” source-confirmed real bug

Reachability

NOT reachable on this QEMU guest. amdgpu_dm_set_degamma_lut() is in sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c, part of the amdgpu.ko module. Requires an AMD GPU to attach. PCI survey shows only QEMU stdvga (0x1234), no AMD GPU. kldload amdgpu would fail to find matching hardware.

Mechanism (source-confirmed)

amdgpu_dm_set_degamma_lut() at amdgpu_dm_color.c:243-291: 1. Line 259: lut = (struct drm_color_lut *)blob->data 2. Line 260: __is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES) β€” iterates over MAX_COLOR_LUT_ENTRIES=4096 entries before validating blob size 3. Blob size not computed until line 270: lut_size = blob->length / sizeof(struct drm_color_lut)

If blob->length < 4096 * sizeof(struct drm_color_lut) (i.e. fewer than 4096 LUT entries), __is_lut_linear() reads past the blob data β†’ heap OOB read.

struct drm_color_lut is 12 bytes (3 Γ— uint16_t + 2 bytes pad). 4096 entries = 49152 bytes. A blob of 1 entry (12 bytes) would cause __is_lut_linear to read 49140 bytes past the blob.

Primitive

  • Class: heap OOB read (info leak)
  • Read size: up to 4096 * 12 - blob->length bytes past allocation
  • Could leak adjacent slab data (kernel pointers, sensitive data)

Fix

fix.diff: Compute lut_size from blob->length before calling __is_lut_linear(), and validate it's within [1, MAX_COLOR_LUT_ENTRIES]. Use lut_size instead of MAX_COLOR_LUT_ENTRIES as the iteration count.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

git apply --check clean + amdgpu.ko compiles

git apply --check clean + amdgpu.ko compiles

Confirmed kernel references

β€”

Detail

Exploit chain

none (HW-gated)

Evidence (decisive lines)

HW-GATED (no AMD GPU). Source-confirmed: __is_lut_linear(lut,4096) before blob size validation -> OOB read ~49KB.

Verified recommended fix

HW-GATED (no AMD GPU). Source-confirmed: __is_lut_linear(lut,4096) before blob size validation -> OOB read ~49KB.

Verdict

HW-GATED (no AMD GPU). Source-confirmed: __is_lut_linear(lut,4096) before blob size validation -> OOB read ~49KB.