# DF-4348 VERDICT — undefined shift counts throughout the amdgpu ATOM interpreter (DF-4340's amdgpu twin)

**Status: inconclusive (kernel runtime hardware-gated; UB divergence
demonstrated on the audit guest compiler). Defect: certain (UB),
impact low/hardening.**

## Root cause

Shift counts are untrusted VBIOS values used unmasked (all in
sys/dev/drm/amd/amdgpu/atom.c):

- `atom_op_shl` atom.c:958 — `dst <<= shift` where `shift =
  atom_get_src(...)` is a **full 32-bit** VBIOS-controlled value.
- `atom_op_shr` atom.c:977 — `dst >>= shift`, same.
- `atom_op_shift_left` atom.c:925 — `dst <<= shift`, shift is u8 (≤255).
- `atom_op_shift_right` atom.c:941 — `dst >>= shift`, u8.
- WS masks atom.c:241/244 — `1 << gctx->shift` / `~(1 << gctx->shift)`
  where `gctx->shift` is assigned from a full u32 write
  (ATOM_WS_SHIFT, atom.c:508) into a `uint8_t` member (atom.h:136) —
  so 0..255, still ≥ 32 possible.
- IIO masks atom.c:121/127/133/143/147/157 —
  `0xFFFFFFFF >> (32 - CU8(base+1))`: width 0 → `>> 32`, width > 32 →
  negative shift count.

In C, shift counts ≥ width (or negative) are undefined; compilers may
constant-fold differently from runtime hardware masking, and the
language gives no guarantee the x86 `shl %cl` count&31 behavior is
what executes.

## Demonstration (guest gcc 8.3, -O1)

`./atom_harness shift` (exit 0, `run.log`):

```
(0xffff << 40)=0x00000000  vs (0xffff << 8)=0x00ffff00  -> divergent
IIO mask width=0: >>32 gives 0x12345678 (UB relied upon)
WS OR_MASK shift=200: 1<<200 = 0x00000000 (UB relied upon)
```

- `0xffff << 40` compiled to **0** (constant-folded), while the runtime
  x86 semantics mask 40→8 and would give 0x00ffff00 — the same source
  expression yields two different results depending on folding: the
  interpreter's computed register/MMIO values are compiler-version
  dependent.
- `>> 32` folded away entirely (full value passed through as the mask).
- `1 << 200` folded to 0.

Impact: wrong values written to GPU registers (MMIO writes through
atom_put_dst), wrong PLL/mask math — a correctness/hardening hazard, not
a memory-safety primitive by itself (no OOB results from the shift value
directly).

## Fix

`fix.diff` — port of DF-4340's fix: `atom_shl`/`atom_shr` helpers
(shift ≥ 32 ⇒ 0) applied at shl/shr/shift_left/shift_right and the WS
OR/AND masks. IIO width-mask sites are additionally noted as residual
hardening (the central DF-4345 port's in_bios gates bound the IIO
*pointers*, not these width *values*; mask them the same way when
touching the file).

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