# VERDICT — DF-4450

**Status: `inconclusive` (kernel-path hardware-blocked; arithmetic defect proven)**
**Finding-level severity: Low · confidence: certain (math), hardware manifestation not exercisable on this guest**

## Root cause (path:line)

* `sys/dev/drm/i915/intel_psr.c:205-215` — `intel_dp_get_sink_sync_latency()`
  reads one sink-controlled DPCD byte and masks it with
  `DP_MAX_RESYNC_FRAME_COUNT_MASK` = `0xf` (include/drm/drm_dp_helper.h:800),
  i.e. accepts 0..15 with **no upper bound check for the PSR2 use**.
* `sys/dev/drm/i915/intel_psr.c:418-421` — `hsw_activate_psr2()` computes
  `idle_frames = max(6, vbt)` then `max(idle_frames, sink_sync_latency + 1)`
  and writes `val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT`.
* `sys/dev/drm/i915/intel_psr.c:430` — `val |= EDP_PSR2_FRAME_BEFORE_SU(sink_sync_latency + 1)`.
* `sys/dev/drm/i915/i915_reg.h:4217-4222` — both `EDP_PSR2_IDLE_FRAME_MASK`
  (`0xf`, bits 3:0) and `EDP_PSR2_FRAME_BEFORE_SU_MASK` (`0xf << 4`, bits 7:4)
  are **4-bit fields**; `EDP_PSR2_TP2_TIME_MASK` occupies bits 9:8.

With `sink_sync_latency == 15` (a fully spec-legal DPCD value, attacker-chosen
by a crafted sink — dongle/dock/panel firmware): `15 + 1 = 16` does not fit a
4-bit field, in two places, in the same register write.

## Proof

`psr2_reg_demo.c` reproduces the kernel's value construction verbatim
(build+run logs on the DF 6.5-DEVELOPMENT guest, cc 8.3):

```
latency=14 (max legal) EDP_PSR2_CTL=0xc00002ff -> IDLE_FRAME=15 FRAME_BEFORE_SU=15 TP2_TIME=2500us
latency=15 (SPILLS!)   EDP_PSR2_CTL=0xc0000310 -> IDLE_FRAME=0  FRAME_BEFORE_SU=1  TP2_TIME=50us
```

Three independent PSR2 timing fields end up wrong in a single MMIO write:
IDLE_FRAME silently 0 (below the enforced minimum of 6), FRAME_BEFORE_SU 1
instead of 16, TP2_TIME 50us instead of the requested 2500us.

## Impact assessment (honest)

* No kernel memory-safety effect: `EDP_PSR2_CTL` is a device register; the
  spill corrupts *display timing configuration* only.
* Practical ceiling: a crafted sink can destabilize PSR2 entry timing on
  GLK/CNL+/gen9 PSR2 platforms (link errors, blanking, flicker) — a local,
  hardware-assisted denial-of-service against display usability. PSR2 also
  requires `sink_psr2_support` (Y-coordinate + ALPM capable sink),
  further narrowing the trigger.
* The PSR1 path is safe: `EDP_PSR_CTL`'s idle-frame field is 8 bits wide
  (i915_reg.h:4151 area), and 16 fits.

## Why the kernel path itself was not run

Guest hardware is virtio-gpu only (`env.txt`), so i915 never binds and
`EDP_PSR2_CTL` (0x6f900) is not reachable. Building the demo on the guest and
running it there (done) is the maximum achievable verification on this
platform; the defect itself is arithmetic and reproducible by inspection.

## Fix

`fix.diff` — refuse PSR2 in `intel_psr2_config_valid()` when
`sink_sync_latency + 1` overflows the 4-bit fields (i.e. > `EDP_PSR2_IDLE_FRAME_MASK`).
One hunk, no behavior change for latency ≤ 14.

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