cz_init_cp_jump_table: NULL mec2_fw dereference on Carrizo when the MEC2 firmware request fails
Summary
MEC2 request_firmware failure is swallowed (err=0, mec2_fw=NULL) but on Carrizo cz_init_cp_jump_table sets max_me=5 and the me==4 slot dereferences adev->gfx.mec2_fw->data plus header fields - NULL-page read -> kernel panic during rlc_init/sw_init whenever amdgpufw_carrizo_mec2 is missing/unreadable. Stoney unaffected (max_me stays 4). Distinct from DF-1134 (jt bounds in the same function): this is the NULL reachability of the 5th slot itself. Carrizo machine with a broken install or root-deleted MEC2 module: boot/probe-time panic. Availability-only, privileged precondition.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3599 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.sh | β | 89 B | view raw | |
| run.log | β | 1.7 KB | view raw | |
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| fix.diff | β | 307 B | view raw | |
| manifest.json | β | 801 B | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-3599 β cz_init_cp_jump_table NULL dereference when Carrizo MEC2 firmware is absent
What
gfx_v8_0_init_microcode() treats a failed MEC2 firmware request as
non-fatal on every non-Topaz/non-Stoney asic:
gfx_v8_0.c:1156-1173
err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
...
} else {
err = 0;
adev->gfx.mec2_fw = NULL; /* :1172 β load continues OK */
}
but on Carrizo the RLC init path unconditionally walks a 5th jump-table slot that dereferences that pointer:
gfx_v8_0.c:1309-1310
if (adev->asic_type == CHIP_CARRIZO)
max_me = 5;
...
gfx_v8_0.c:1347-1349
} else if (me == 4) {
const struct gfx_firmware_header_v1_0 *hdr =
(const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data; /* NULL->data */
struct firmware.data sits at a small offset, so with mec2_fw == NULL
this reads from the unmapped NULL page and the subsequent
le32_to_cpu(hdr->header.ucode_array_offset_bytes) at :1352 and the copy
loop at :1357-1359 fault β kernel panic during gfx_v8_0_rlc_init()
(:1418, reached from gfx_v8_0_sw_init :2091) β driver probe failure /
boot-time panic on a CZ system whose amdgpufw_carrizo_mec2 module is
missing or unreadable.
Stoney is unaffected (its max_me stays 4 and it never loads mec2 anyway).
Threat model / severity
Requires the MEC2 firmware file to be absent or unrequestable on a Carrizo machine: broken install, root-deleted/replaced firmware module, or distro image gap. Availability-only (NULL-page read β panic), privileged precondition β Low.
Reproduce
Not executable on the audit guest (virtio-only, no AMD GPU, no amdgpu module). Source assertion:
./run.sh
prints the NULL-assigning fallback, the CZ-only max_me = 5, and the
unguarded mec2_fw->data dereference on the me == 4 branch.
Fix
fix.diff: only take the 5th slot when adev->gfx.mec2_fw != NULL.
DF-3599 β VERDICT
status: inconclusive (kernel run) / source certain reproduced: 0
Proof
gfx_v8_0_init_microcode:1156-1173 β on MEC2request_firmwarefailure the else branch resetserr = 0and setsadev->gfx.mec2_fw = NULL; initialization therefore succeeds with a NULL MEC2 pointer (this fallback is intentional for asics where mec2 is optional β but Carrizo's RLC init is not optional).cz_init_cp_jump_table:1309-1310 βif (adev->asic_type == CHIP_CARRIZO) max_me = 5;- :1347-1352 β the
me == 4iteration computes(const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->dataand thenle32_to_cpu(hdr->header.ucode_array_offset_bytes)at :1352,hdr->jt_offset/hdr->jt_sizeat :1321-1322 pattern β with mec2_fw == NULL these read from the NULL page (offset ofdatawithinstruct firmwareis small) β page fault β kernel panic duringgfx_v8_0_rlc_init:1418 βgfx_v8_0_sw_init:2091 returns after the probe has already emitted no error for the missing fw. - Reachability precondition: Carrizo system + missing/unreadable
amdgpufw_carrizo_mec2firmware module (broken install, deleted or replaced module). Availability-only; privileged control of firmware files β severity Low.
Stoney never reaches me == 4 (max_me stays 4, and Stoney never loads
mec2 β :1147-1148), so only Carrizo is affected.
Why not a kernel run
Audit guest is virtio-only β no AMD PCI device, no drm/amdgpu module, no
/boot/modules. The dereference path requires a Carrizo APU to probe.
inconclusive at runtime; the NULL-deref control flow is unambiguous from
source (see run.log excerpts).
Fix validation
fix.diff gates the 5th slot on adev->gfx.mec2_fw != NULL. Kernel
build/run not possible on this guest β fix_status: not_testable; diff
line-matched to gfx_v8_0.c:1309-1310.
kernel_refs
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:1170-1173 (NULL fallback)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:1309-1310 (CZ max_me=5)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:1347-1355 (unguarded deref)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:1405-1418 (caller path)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:2091 (sw_init entry)
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
not_testablefix.diff adds the mec2_fw presence check; not buildable/testable on the virtio-only guest (amdgpu module absent).
findings/poc/DF-3599/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (source excerpts of the three linked defects); VERDICT.md; fix.diff
PoC changes
authored fresh (pass 2)
Verified recommended fix
Gate the 5th jump-table slot on mec2_fw presence: if (asic_type == CHIP_CARRIZO && adev->gfx.mec2_fw) max_me = 5;
Verdict
On MEC2 firmware request failure gfx_v8_0_init_microcode sets adev->gfx.mec2_fw = NULL and err = 0 (:1170-1173) so initialization succeeds, but on Carrizo cz_init_cp_jump_table sets max_me = 5 (:1309-1310) and the me==4 iteration dereferences adev->gfx.mec2_fw->data (:1349) and the header fields at :1321-1322-pattern reads without a NULL check -> NULL-page read -> kernel panic during gfx_v8_0_rlc_init (:1418) / sw_init (:2091) whenever amdgpufw_carrizo_mec2 is missing or unreadable. Availability-only with a privileged precondition (firmware file manipulation/broken install) -> Low. Not executable on the virtio-only audit guest (no AMD GPU, no amdgpu module) -> inconclusive at runtime; control flow proven from source.
No comments yet.