# DF-4347 VERDICT — amdgpu part-number VBIOS string printed/copied unbounded (DF-4339's amdgpu twin, different shape)

**Status: inconclusive (kernel runtime hardware-gated; logic-level OOB
reproduced on the audit guest). Defect: certain.**

## Root cause

The amdgpu `amdgpu_atom_parse` tail (atom.c:1340-1348) differs from
radeon's `name[512]` loop (which was DF-4339): here the part number is
used in place, with no bounded copy at all:

```c
1340: idx = CU16(ATOM_ROM_PART_NUMBER_PTR);       /* 0x6E, unvalidated */
1341: if (idx == 0)
1342:         idx = 0x80;
1344: str = CSTR(idx);
1345: if (*str != '\0') {
1346:         pr_info("ATOM BIOS: %s\n", str);
1347:         strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version));
1348: }
```

Two unbounded reads:
1. `idx` (any 16-bit VBIOS value) is dereferenced at bios+idx with no
   check — `*str` itself can be outside the allocation.
2. `%s` (printk) and `strlcpy` (as source) both walk `str` until a NUL —
   an image whose last bytes are non-NUL walks off the end of the
   `kzalloc`'d bios buffer to the first NUL in adjacent kernel heap,
   printing those bytes to the console/log (kernel heap info leak in the
   log stream) and copying up to 19 of them into `vbios_version`
   (later readable via the `vbios_version` sysfs/connector interface).

Compared with DF-4339 (radeon): same class (unterminated VBIOS string →
unbounded walk), worse shape here because there is no destination bound
enforced on the source walk before printing (radeon at least copied into
`name[512]` first; amdgpu prints the raw pointer).

## Reproduction

Guest (no AMD GPU): `./atom_harness partstr` — 512-byte image, string
from 0x100 to the (guarded) image end, no NUL → the `%s` walk traps:
**SIGSEGV exit=139** (`run.log`, case `partstr`). Fixed logic requires a
NUL inside the image before printing → clean reject, exit 0
(`fix_run.log`).

## Fix

`fix.diff` (minimal, standalone): bounded copy into `vbios_version`
(19 bytes + forced NUL) and print the bounded copy — removes the
unbounded print/copy and the unterminated-destination leak; residual:
up to 19 bytes of over-read if `idx` sits at the image end. The
complete fix (idx validated against bios_size AND NUL required inside
the image) is part of the central DF-4345 port (`fix.diff` there).

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