# DF-5084 — VERDICT

**Status: not_reproduced (runtime) / bug certain (source) — LATENT, code not
compiled on DragonFly.** Impact on any shipped DragonFly build: **none**.

## 1. What was audited and how the bug was found

`sys/dev/drm/radeon/radeon_agp.c` (285 LOC), pass 2. The AGP init path was
checked acquire/release-balance, quirk-table termination, module-parameter
validation, and the aperture-size → `mc.gtt_size` math. All the conventional
classes came back clean (see final JSON `negative_notes`), but the units of
`ai_aperture_size` did not survive the port:

* DF tree-wide convention is BYTES:
  * `sys/dev/agp/agpvar.h:50` `vm_size_t ai_aperture_size;`
  * `sys/dev/agp/agp.c:904` `info->ai_aperture_size = rman_get_size(sc->as_aperture);`
    (the aperture PCI BAR resource, i.e. bytes)
  * `sys/dev/drm/drm_agpsupport.c:500` prints `(int)(…ai_aperture_size >> 20)` as "…M"
* `radeon_agp.c:152` compares it against `32` (intent: 32 **MB**, cf. the
  `"(%juM) need at least 32M"` message) → dead guard in byte units.
* `radeon_agp.c:245` `…ai_aperture_size << 20` (intent: MB→bytes, inherited
  from old Linux `aper_size` which *was* MB) → 2^20x inflation in byte units.
  Modern Linux uses `aper_size` (bytes) directly, with no shift.

## 2. Proof the buggy code is NOT compiled on DragonFly

`sys/dev/drm/radeon/Makefile:148` force-includes `sys/dev/drm/kconfig.h`
(which does not define `CONFIG_AGP`) and `-I sys/dev/drm/include` supplies the
locally-modified `IS_ENABLED()` (`sys/dev/drm/include/linux/kconfig.h:30-39`).

On the audit guest (DragonFly 6.5-DEVELOPMENT, gcc 8.3 [DragonFly]), with the
module's exact flags:

```
$ cc -include /usr/src/sys/dev/drm/kconfig.h -I/usr/src/sys/dev/drm/include -E /tmp/iscfg2.c
const char *agp   = "AGP_DISABLED";      <- #if IS_ENABLED(CONFIG_AGP) is FALSE
const char *pci   = "PCI_ENABLED";       <- control (kconfig.h defines it)
const char *undef_ = "UNDEF_DISABLED";   <- control
const char *cik   = "CIK_ENABLED";       <- control
```

Hence `radeon_agp_init` == `{ return 0; }`, `radeon_agp_fini` == `{}`,
`radeon_agp_resume` == `{}` in every shipped build. Guest `/usr/src`
`radeon_agp.c` and `kconfig.h` are md5-identical to the audited tree
(`env.txt`), so this is not a guest-tree artifact.

## 3. What WOULD happen if CONFIG_AGP were ever defined (impact ceiling)

`units_demo` (userland arithmetic identical to `radeon_agp.c:245-247`, output
in `run.log`): every realistic AGP aperture yields

* `mc.gtt_size` = 32–256 **TB** (e.g. 64 MB @ 0xd0000000 → `gtt_end =
  0x4000cfffffff`),
* `RADEON_AIC_HI_ADDR` (`r100.c:662-663`) = low-32 of `gtt_end` =
  0xcfffffff **<** `AIC_LO_ADDR` 0xd0000000 → **inverted** GPU DMA window,
* `MC_AGP_TOP` (`r100.c:3864-3865`, `r300.c:1334-1335`, `r520.c:153-154`) =
  `0x2000cfff`-style truncated garbage,
* TTM GTT heap sized 2^20x (`radeon_ttm.c:940-941`).

GATT *binds* past the real aperture still fail closed at
`sys/dev/agp/agp.c:520-522` (`offset + mem->am_size > AGP_GET_APERTURE` →
EINVAL), so the kernel-side consequence is mis-programmed GPU address-window
registers + unallocatable GTT (functional DoS on AGP hardware); a
chipset-mediated DMA-window corruption is speculative.

Related shipped-code note (not a separate finding): because the stub returns
0 = "success" (`radeon_agp.c:256-258`), on real AGP radeon hardware the ASIC
init keeps `RADEON_IS_AGP` with `mc.gtt_size == 0`; the TT heap is then empty
(`radeon_ttm.c:940-941`) and the `!rdev->ddev->agp` guard at
`radeon_ttm.c:147-160` is itself compiled out — the driver fails closed
(no GTT objects), it does not corrupt. The guest has no AGP/ATI hardware
(`run.log`: 7 PCI devices, QEMU std VGA only, no drm modules), so none of
this is exercisable here.

## 4. Why verification stops here

* Memory-corruption escalation chain: N/A — the code is not in the kernel;
  there is no primitive to groom.
* Runtime reproduction: impossible on this guest (no AGP bridge, no radeon
  ASIC — QEMU does not emulate them) and meaningless while the code is
  compiled out.
* Fix validation (`fix.diff`): `not_testable` — the patched lines are inside
  the same `#if IS_ENABLED(CONFIG_AGP)` and do not compile into any DF build
  today; a kernel build would demonstrate nothing observable. The fix is a
  3-line units correction matching modern Linux and the DF AGP layer's byte
  convention.

## 5. Bottom line

File as **Info / latent**: a certain, tree-inconsistent units bug inherited
from an old Linux port, sitting behind a config gate that DragonFly never
opens. It becomes a real functional/DoS bug (and a speculative
hardware-DMA-window hazard) the moment someone adds `#define CONFIG_AGP 1`
to `sys/dev/drm/kconfig.h` and boots AGP radeon hardware. One-line fix;
apply `fix.diff` or leave documented as latent.

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