# DF-5028 — NULL-pointer dereference of `radeon_encoder->enc_priv` in `dce6_audio_get_pin()` (dce6_afmt.c)

## What this is

`sys/dev/drm/radeon/dce6_afmt.c:104-105` dereferences `dig->pin` for **every**
digital encoder on the device's encoder list without first checking that
`dig = radeon_encoder->enc_priv` is non-NULL:

```c
list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
        if (radeon_encoder_is_digital(encoder)) {          /* id-only test   */
                radeon_encoder = to_radeon_encoder(encoder);
                dig = radeon_encoder->enc_priv;
                if (dig->pin == pin)                       /* NULL deref     */
                        pin_count++;
        }
}
```

## Why enc_priv can be NULL for a *digital* encoder

`radeon_encoder_is_digital()` (sys/dev/drm/radeon/radeon_encoders.c:423-445)
filters **only** by `encoder_id`. But for several of those very ids,
`radeon_add_atom_encoder()` assigns `enc_priv` from functions that can return
NULL:

- `atombios_encoders.c:2838` and `:2872` — for `INTERNAL_LVDS`, `INTERNAL_TMDS1`,
  `INTERNAL_KLDSCP_TMDS1`, `INTERNAL_LVTM1`, `INTERNAL_UNIPHY*` with
  `ATOM_DEVICE_LCD_SUPPORT`, `enc_priv = radeon_atombios_get_lvds_info()`.
  `radeon_atombios.c:1630-1640`: when the VBIOS has no parsable
  `LVDS_Info` table (`atom_parse_data_header()` fails) the function returns its
  still-NULL `lvds`; it also returns NULL when `kzalloc` fails
  (radeon_atombios.c:1639).
- `atombios_encoders.c:2842/2876/2880` — `enc_priv = radeon_atombios_set_dig_info()`
  returns NULL on `kzalloc` failure (atombios_encoders.c:2760-2763).

So an encoder whose id satisfies `radeon_encoder_is_digital()` can carry a NULL
`enc_priv` either from a missing/malformed VBIOS LVDS table or from a failed
allocation during encoder creation.

## Reachability

Audio is enabled by default (`radeon_audio = -1`, sys/dev/drm/radeon/radeon_drv.c:180;
gate is `radeon_audio != 0`, radeon_connectors.c:1766). On every connector
(hot-)detect:

  radeon_dp_detect / radeon_dvi_detect            (radeon_connectors.c:1767, :1439)
    -> radeon_audio_detect()                      (radeon_audio.c:444)
       dig = radeon_encoder->enc_priv; ... dig->pin   <- same unguarded deref at :483
    -> radeon_audio_get_pin()                     (radeon_audio.c:425)
    -> dce6_audio_get_pin()                       (dce6_afmt.c:86)
       walks **all** encoders -> `dig->pin`        (dce6_afmt.c:105)

The walk at dce6_afmt.c:101 touches *every* digital encoder on the system, not
just the one being detected, so a NULL `enc_priv` on *any* DCE6-era digital
encoder panics the machine during an audio-capable display detect.  The sibling
unprotected derefs live in `radeon_audio.c:483` (`dig->pin` in
`radeon_audio_detect`) and `radeon_audio.c:267` (`dig->pin` in
`radeon_audio_enable`'s identical walk) — same bug family, other file.

## Impact

Kernel NULL-page read at a small fixed struct offset -> kernel panic. Not
exploitable beyond DoS (no controlled data at the dereferenced address; page 0
is unmapped). Trigger requires SI/CIK (DCE6+) radeon hardware with audio (the
default) *and* a VBIOS/an allocation state that leaves a digital encoder's
`enc_priv` NULL — hence Low severity. The same code exists verbatim in upstream
Linux drivers/gpu/drm/radeon/dce6_afmt.c.

## Why no runtime PoC on this guest

The audit guest is QEMU/KVM with a Bochs std-VGA device
(`vgapci0: chip=0x11111234`, see env.txt). There is no AMD GPU, so
`dce6_afmt.c` never executes: `radeon_audio_init` is only reached on radeon
DCE6+ ASICs. Reproduction would need SI/CIK hardware (or GPU passthrough) plus
a doctored VBIOS (or forced allocation failure) — not possible here. The
finding is a source-level proof; see VERDICT.md.
