# DF-3655 — NULL dereference via `WARN_ON(!status->plane_count)` after `WARN_ON(!status)` in `amdgpu_dm_atomic_commit_tail()`

**File:** `sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c`
**Lines:** 4888-4890
**Severity:** Low (conditional kernel panic — requires a stream without DC status in the underscan path) · **CWE-476** · confidence: certain (code defect unambiguous)

## What

```c
4888   status = dc_stream_get_status(dm_new_crtc_state->stream);
4889   WARN_ON(!status);
4890   WARN_ON(!status->plane_count);      /* <-- dereferences `status` */
```

`WARN_ON()` reports but does not stop execution. If `dc_stream_get_status()`
returns NULL (the stream is not present in the DC current context — e.g.
immediately after a failed `dc_commit_state()`, which itself is only WARN'd at
amdgpu_dm.c:4837 while execution continues), line 4890 dereferences the NULL
pointer at offset 8 (`offsetof(struct dc_stream_status, plane_count)`:
`primary_otg_inst` + `stream_enc_inst`, dc/dc_stream.h) → page fault → panic.

Reachability is two-step: (a) an underscan/scaling-only commit on a connector
whose CRTC has a live stream (the normal committed display case), combined
with (b) the stream being absent from the current DC context (commit failure
or teardown race). Because (b) is an internal DC failure condition rather
than a purely attacker-chosen state, severity is Low.

## Harness

`harness.c` reproduces the exact evaluation order with a verbatim-layout
`dc_stream_status` model; the guest is virtio-only (env.txt) so the kernel
path itself cannot run.

```
./build.sh && ./run.sh
```

Expected decisive output (run.log):

```
WARN_ON(!status) = 1 ...        <- printed, execution continues (kernel WARN)
Segmentation fault              <- status->plane_count deref at offset 8
EXIT=139
```

## Contents

`harness.c` · `build.sh` · `run.sh` · `build.log` · `run.log` · `env.txt` ·
`VERDICT.md` · `fix.diff` · `manifest.json` · `verdict.json`
