# DF-4202 — unchecked drm_cvt_mode() NULL results (radeon DF-4035 twin)

**File:** `sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:405-407, 459-460` (pass 2)
**Severity:** Low (OOM-gated NULL deref panic in LVDS/eDP get_modes)
**Status:** not reproduced at runtime — hardware-gated + OOM-gated;
source-level certainty.

## Root cause

`drm_cvt_mode()` returns NULL when its internal `drm_mode_create()`
fails — kzalloc failure or `drm_mode_object_add()` IDR failure
(drm_modes.c:66-80 and drm_modes.c:164-169: "If failure, we will return
directly" NULL). Both amdgpu call sites dereference unconditionally:

```c
/* amdgpu_connector_lcd_native_mode() */
mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay,
		    60, true, false, false);            /* :405 */
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;   /* :406 NULL deref */
DRM_DEBUG_KMS("... %s\n", mode->name);                          /* :407 */

/* amdgpu_connector_add_common_modes() — loops 17 common modes */
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
		    60, false, false, false);          /* :459 */
drm_mode_probed_add(connector, mode);                           /* :460 list_add(NULL) */
```

`drm_mode_probed_add` is `list_add_tail(&mode->head, ...)` — a write
through NULL+offset.

## Reach

`amdgpu_connector_lvds_get_modes()` (:668, :676) and
`amdgpu_connector_dp_get_modes()` eDP/LVDS branch (:1251, :1259) — the
no-EDID-modes fallback that every laptop panel without a usable EDID takes
on every probe — under kernel memory exhaustion. 17+ allocation attempts
per probe × repeated probes (poll + GETCONNECTOR) make the window real
under memory pressure. Upstream Linux carries the identical unguarded
code (radeon upstream added `if (mode)` guards for the same pattern).

## Evidence

- `trigger_df4202.c` — hammer probe loop with optional memory-hog children
  (`./trigger_df4202 oom`); builds and runs on the guest (no DRM device
  there — env.txt).
- `fix.diff` — `if (mode)` guards at both sites; verified to apply cleanly
  to a pristine copy of the real file.

## Fix

See `fix.diff`.
