# DF-3651 — verdict narrative

## Finding
NULL-pointer dereference of rdev->pm.dpm.dyn_state.cac_tdp_table when the VBIOS has no PowerTune table: five unchecked sinks in ci_dpm.c

## Kernel references
- `sys/dev/drm/radeon/ci_dpm.c:244`
- `sys/dev/drm/radeon/ci_dpm.c:330`
- `sys/dev/drm/radeon/ci_dpm.c:414`
- `sys/dev/drm/radeon/ci_dpm.c:435`
- `sys/dev/drm/radeon/ci_dpm.c:666`
- `sys/dev/drm/radeon/ci_dpm.c:748`
- `sys/dev/drm/radeon/r600_dpm.c:1257`
- `sys/dev/drm/radeon/r600_dpm.c:1261`

## Was it reproduced?
No — not on the kernel path. The audit guest is virtio-only (0 AMD PCI devices, /dev/dri absent, no radeon/drm kld; env.txt), so `sys/dev/drm/radeon/ci_dpm.c` can never execute there. Per the pass-2 instruction for this hardware-gated file, the verdict is **inconclusive** (source-level certainty certain) rather than reproduced.


## Root cause and reasoning

Source-certain NULL deref family. cac_tdp_table is heap-allocated only when the VBIOS extended header (>= V7) carries usPowerTuneTableOffset (r600_dpm.c:1257-1265); otherwise rdev->pm.dpm.dyn_state.cac_tdp_table stays NULL (rdev is zero-allocated). pi->caps_power_containment is nevertheless set true unconditionally (ci_dpm.c:244,251), so ci_dpm_enable unconditionally reaches: ci_populate_bapm_parameters_in_dpm_table -> cac_tdp_table->tdp/configurable_tdp (ci_dpm.c:435-436, called from ci_init_smc_table:3677), ci_populate_tdc_limit -> ->tdc (330), ci_populate_bapm_vddc_base_leakage_sidd -> high/low_cac_leakage (414-415), ci_enable_power_containment -> maximum_power_delivery_limit (666), and ci_power_control_set_level -> configurable_tdp (748). None is NULL-checked; a crafted VBIOS (or simply an early/trimmed PowerTune-less extended header) deterministically panics the kernel at radeon DPM enable. First sink hit in program order is ci_dpm.c:435 during the first ci_init_smc_table. Kernel path unreachable on this GPU-less guest; inconclusive overall.

## Exploitability

Crafted VBIOS without a PowerTune table (extended header size < V7 or usPowerTuneTableOffset == 0) on a CI-class card -> NULL+offset kernel read at ci_init_smc_table time -> boot/attach panic. DoS only.

## Recommended fix
NULL-check rdev->pm.dpm.dyn_state.cac_tdp_table (return -EINVAL / skip) at the five deref sites in ci_dpm.c.
See fix.diff.

## 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.
