# VERDICT — DF-3943

## Bottom line
**not_reproduced on the audit guest — source-level certain.** The audit QEMU
guest has no AMD GPU (virtio-gpu 0x1111:1234, no /dev/dri, drm not built into
the running kernel — env.txt), so the kernel path cannot be exercised. The bug
is however provable by direct reading of the cited lines, and the control-flow
was executed 1:1 in a userland harness on the guest (run.log): every failed
interlaced validation leaves `pipe_ctx->stream->dst.height` doubled.

## Root cause (path:line)
`resource_build_scaling_params()` mutates the **shared** `dc_stream_state`:

- sys/dev/drm/amd/display/dc/core/dc_resource.c:1118-1119 —
  `if (pipe_ctx->stream->timing.flags.INTERLACE) pipe_ctx->stream->dst.height *= 2;`
- sys/dev/drm/amd/display/dc/core/dc_resource.c:1125-1126 —
  `if (viewport.height < 16 || viewport.width < 16) return false;` ← early
  return, skips the compensating divide
- sys/dev/drm/amd/display/dc/core/dc_resource.c:1188-1189 —
  `if (INTERLACE) pipe_ctx->stream->dst.height /= 2;` ← only on the fall-through path

`pipe_ctx->stream` is the refcounted `struct dc_stream_state` owned by
amdgpu_dm (`dm_new_crtc_state->stream`), not a per-validation copy; a failed
`dc_validate_global_state()` → `DC_FAIL_SCALING` (dc_resource.c:1201-1206,
1195-1209) aborts the atomic commit but leaves the stream object corrupted.
amdgpu_dm reuses the same stream object across commits that keep the same
mode, so the doubling **compounds**: N failed attempts → dst.height × 2^N.
int (32-bit) overflows after ~21 attempts from 1080 (see run.log attempt 21:
-2030043136 = 1080·2^21 wrapped). Downstream sinks of the corrupted field:
calculate_recout() :637-657 (recout.height numerator), calculate_scaling_ratios()
:713-737 (out_h), scl_data.h_active/v_active — all part of the same commit path.

## Why upstream confirms this is wrong
The whole "double dst.height in the shared stream during validation" pattern was
removed from mainline by Linux v5.4 (resource_build_scaling_params in v5.4 has
no INTERLACE mutation at all; verified against the v5.4 blob fetched from
api.github.com — /tmp/opencode/dc_v5.4.c:962ff). No dedicated fix commit exists;
it died in the DC refactoring between 4.17 and 5.4.

## Impact
Local persistent display-state corruption / DoS reachable by the graphical
session user (DRM master) on DCE8+/DCN amdgpu hardware in interlaced modes.
Not memory corruption: the corrupted value is a bounded int used in display
math; worst case is garbage scaling parameters, display corruption, and
errant division results (denominators are separately validated by amdgpu_dm;
DF-1301 tracks the raw zero-rect class). Severity Medium.

## PoC changes vs seed
None — no seed existed (pass-2 new finding). Harness written from scratch;
logic transcribed verbatim from dc_resource.c:1118-1189.

## Fix validation
Not possible on this guest (no AMD GPU): fix_status=not_testable,
fix_baseline_reproduced=0, fix_patched_reproduced=0. fix.diff is
`git apply --check`-clean against sys/ (verified in-place).

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