{
  "finding_id": "DF-4238",
  "status": "not_reproduced",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Parsing primitive proven by a guest-run harness; the kernel path is hardware-gated (no AMD GPU on the audit guest - pciconf shows zero 0x1002 devices, env.txt). sdma_v3_0_init_microcode() validates each SDMA firmware image only via amdgpu_ucode_validate() (amdgpu_ucode.c:251-260, single equality fw->datasize == hdr->size_bytes) and then reads beyond the common header: hdr->header.ucode_version at sdma_v3_0.c:316 (offset +16), hdr->ucode_feature_version at :317 (offset +32; sdma_firmware_header_v1_0 is 48 bytes), and header->ucode_size_bytes at :324-326 (offset +24) folded into adev->firmware.fw_size which later sizes the firmware BO memcpyd at amdgpu_ucode.c:347-351 (DF-1947 sink; VI load type is AMDGPU_FW_LOAD_SMU per amdgpu_ucode.c:291-300). A 4-byte blob declaring size_bytes=4 passes validation; harness (fwcheck.c, guard-page stand-in for the exact-size request_firmware allocation) shows validate returns 0 and the very first sub-header read faults with SIGSEGV exit 139 - the exact access order of the kernel function. Root-installed firmware gate, same threat model/severity as family findings DF-1451 (sdma_v4_0), DF-1553 (cik_sdma), DF-1598 (sdma_v2_4).",
  "exploit_chain": "root replaces /boot amdgpufw_<asic>_sdma[_1] with a 4-byte file whose first u32 is 4 -> amdgpu_ucode_validate passes -> sdma_v3_0.c:316/:317/:326 read 16/24/32 bytes past the allocation -> heap OOB read: garbage fw_version/feature_version (dmesg leak, burst_nop misconfig) and attacker-influenced OOB-read value inflates fw_size feeding the DF-1947 unbounded memcpy of ucode_size_bytes from fw->data+ucode_array_offset_bytes.",
  "evidence": "run.log: amdgpu_ucode_validate(4-byte blob) = 0 (0 == accepted) then RUN_EXIT=139 (SIGSEGV) at the +16 read; VERDICT.md has the full line-cited trace; fix.diff applies cleanly to the unmodified sys file (patch --dry-run verified).",
  "kernel_refs": [
    "sys/dev/drm/amd/amdgpu/sdma_v3_0.c:309-317",
    "sys/dev/drm/amd/amdgpu/sdma_v3_0.c:321-326",
    "sys/dev/drm/amd/amdgpu/amdgpu_ucode.c:251-260",
    "sys/dev/drm/amd/amdgpu/amdgpu_ucode.c:347-351",
    "sys/dev/drm/amd/amdgpu/amdgpu_ucode.h:120-126"
  ],
  "poc_changes": "No seed PoC; fwcheck.c is a guard-page harness (no ASan needed on the DragonFly guest) replicating the validate-then-read sequence with struct layouts mirrored from amdgpu_ucode.h.",
  "attempts": 2,
  "guest_uname": "DragonFly 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",
  "runtime_sec": 1,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o fwcheck fwcheck.c",
  "run_cmd": "./fwcheck; echo $?  (139 = SIGSEGV)",
  "code_hash": "a6b75b1559f8c807a21a987d3ecca843807d03aa11c92b0f353194229d541b24",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "not_testable (no AMD hardware on the guest); fix.diff rejects datasize < sizeof(struct sdma_firmware_header_v1_0) before the sub-header reads - the v3 twin of the DF-1598 fix. Full header cross-validation belongs in amdgpu_ucode_validate (DF-1946); memcpy sink hardening is DF-1947.",
  "fix_evidence": "fix.diff (patch --dry-run clean against unmodified sys/dev/drm/amd/amdgpu/sdma_v3_0.c); harness output demonstrates the accepted-then-rejected sequence the guard implements.",
  "notes": "Hardware-gated kernel path, primitive guest-proven. Per-file twin of DF-1451/DF-1553/DF-1598; shared-root findings DF-1946/DF-1947 remain the umbrella. sdma_v3_0.c otherwise audited clean: emit accounting (emit_frame_size 6+3+6+VI_FLUSH_GPU_TLB_NUM_WREG*3+6+30 vs actual writes 6/3/6/12/max-10; vm_flush over-reserved), interrupt dispatcher switch-cases ring_id to fixed instances, instance walks bounded by SDMA_MAX_INSTANCE=2, suspend/resume symmetric, doorbell indices constants.",
  "recommended_fix": "In sdma_v3_0_init_microcode, reject firmware with fw->datasize < sizeof(struct sdma_firmware_header_v1_0) (and ideally ucode_array_offset_bytes+ucode_size_bytes > datasize) before reading any sub-header field."
}