# DF-4554 — amdgpu_debugfs_gpr_read: VGPR path copies an UNINITIALIZED 4 KB heap buffer to userspace when read_wave_vgprs is NULL (gfx_v6/v7/v8) — independent of DF-1692

## What this is

sys/dev/drm/amd/amdgpu/amdgpu_debugfs.c, `amdgpu_debugfs_gpr_read()`
(lines 689-747):

```c
	data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);   /* 710: NOT zeroed */
	...
	if (bank == 0) {
		if (adev->gfx.funcs->read_wave_vgprs)                /* 719 */
			adev->gfx.funcs->read_wave_vgprs(...);           /* 720 */
	} else {
		if (adev->gfx.funcs->read_wave_sgprs)
			adev->gfx.funcs->read_wave_sgprs(...);
	}
	...
	while (size) {                                           /* 729 */
		uint32_t value;
		value = data[offset++];                              /* 732: copied
		                                                         regardless */
		r = put_user(value, (uint32_t *)buf);
		...
	}
```

In this tree only **gfx_v9_0.c** defines `.read_wave_vgprs`
(gfx_v9_0.c:1383); `gfx_v7_0_gfx_funcs` (gfx_v7_0.c:4283-4290) and
`gfx_v8_0_gfx_funcs` (gfx_v8_0.c:5325-5332) have `.read_wave_data` and
`.read_wave_sgprs` only — so on CIK/VI asics the VGPR callback pointer is
**NULL**, the buffer is never filled, and the copy-out loop still ships
`size` dwords of **uninitialized kernel heap** to userspace. This survives
a fix of DF-1692's byte/dword unit confusion: even with `offset = 0` and
`size = 4096` exactly, the leak discloses a full uninitialized 4 KB
kmalloc allocation. (With DF-1692 unfixed the same loop is additionally
OOB — that part is DF-1692's, not re-reported here.)

CWE-908 / CWE-200 (uninitialized memory disclosure). The SGPR path is not
affected (all three asic families define `read_wave_sgprs`).

## Reachability on DragonFly — DEAD CODE (proven three ways)

1. `sys/dev/drm/kconfig.h` does **not** define `CONFIG_DEBUG_FS`; the entire
   handler body (amdgpu_debugfs.c:70-932) is inside
   `#if defined(CONFIG_DEBUG_FS)`, so only the `#else` stubs
   (amdgpu_debugfs.c:933-942) compile.
2. The DFly compat shim `sys/dev/drm/include/linux/debugfs.h` declares **no
   functions at all** (no `debugfs_create_file`), so even defining
   `CONFIG_DEBUG_FS` would not build the handler — the porting work does
   not exist yet.
3. Runtime proof on the audit guest (see run.log): the shipped
   `/boot/kernel/amdgpu.ko` contains **none** of the handler symbols
   (`amdgpu_debugfs_regs_read`, `_gpr_read`, `_wave_read`, `_sensor_read`,
   `_regs_pcie_*`, …) — only `amdgpu_debugfs_add_files` plus the three
   `#else` stubs. Also, `/sys/kernel/debug` does not exist on DFly, and the
   guest has no AMD GPU (`pciconf -l | grep 1002` → none).

So this is a **latent** finding: real in the source, activates only for
the day a debugfs port lands and CONFIG_DEBUG_FS is enabled (and then only
on CIK/VI hardware as a 0444 debugfs file readable by root — debugfs roots
are root-only), plus it equally applies to upstream Linux amdgpu of this
vintage.

## Reproduce (on a system where the handlers ARE compiled — e.g. Linux with CONFIG_DEBUG_FS, CIK/VI GPU)

```
lseek(fd_amdgpu_gpr, (0ULL << 60) /* bank=0 VGPR */ , SEEK_SET);
read(fd_amdgpu_gpr, buf, 4096);   /* -> 4KB uninitialized heap */
```

Expected (bug): returned bytes are uninitialized kmalloc contents (heap
pointers/old data — check for non-zero kernel-pointer-like patterns).
Expected (fix): -EINVAL (no VGPR read support) or zeroed data.

## Verdict

`not_reproduced` on this guest (feature compiled out + no AMD GPU);
source-level: certain that the loop copies without checking whether the
callback ran; `likely` for the overall finding given the dead-code caveat.
