# DF-4965 VERDICT

**Status: reproduced (unit-level contract violation executed on the DF guest with the
verbatim DCE110 functions); kernel consequence chain proven by code trace,
probabilistic final stage. Identical defect family to DF-4943 (dce80) /
DF-4945 (dce120) / DF-4946 (dcn10).**

## What was executed

`harness_dce110.c` carries verbatim copies of the dce110 `offset_to_id`
(hw_translate_dce110.c:39-179) and `id_to_offset` (hw_translate_dce110.c:181-366)
with the real DCE11 register constants taken from
`sys/dev/drm/amd/include/asic_reg/dce/dce_11_0_d.h` and `dce_11_0_sh_mask.h`.
The dce110 switch constants are **absolute MMIO offsets**
(mmDC_GPIO_DDCVGA_A=0x4881, mmDC_GPIO_I2CPAD_A=0x4899, dce_11_0_d.h:1481,1504),
which is exactly the domain the VBIOS stores in `GPIO_Pin_LUT.usGpioPin_AIndex`
(bios_parser.c:1819-1820, v1 parser used for DCE110-era asics) and which
`get_hpd_gpio` (dc_link.c:115-118) forwards into `dal_gpio_service_create_irq`.
The mask arrives as `1 << ucGpioPinBitShift` (bios_parser.c:1825-1826) — the
DDC-family branches do not consult it at all.

Guest run (`run.log`, stable across `run.2.log`):

- All eight DDC-family offsets (DDC1-0x4869 .. DDC6-0x487d, DDCVGA-0x4881,
  I2CPAD-0x4899) return **true** with `*en` set (0..7) and `*id` **UNWRITTEN**
  (poison 0xA11CE0D5 preserved through the call).
- Controls prove the methodology: GENERIC/HPD/SYNCA branches *do* write `*id`;
  PWRSEQ/DEBUG/PAD_STRENGTH/unknown offsets are rejected with `false`.

## Kernel consequence chain (code trace)

`dal_gpio_service_create_irq` (gpio_service.c:148) declares `enum gpio_id id;`
**uninitialized** → CWE-457. With garbage `id`:

- garbage != GPIO_ID_HPD(3) && != GPIO_ID_GPIO_PAD(4) → `dal_gpio_create_irq`
  (gpio_service.c:373-381) returns NULL — benign.
- garbage == GPIO_ID_GPIO_PAD(4) → `dal_gpio_service_open` rejects it in the
  switch default (gpio_service.c:271-274) — benign.
- **garbage == GPIO_ID_HPD(3)** → `dal_gpio_create(HPD, en)` →
  `dal_gpio_service_open` (gpio_service.c:258-262) → `create_hpd` +
  `define_hpd_registers(pin, en)` → `hpd->regs = &hpd_regs[en]`
  (hw_factory_dce110.c:139,142). `hpd_regs[]` has exactly **6** entries
  (hw_factory_dce110.c:57-64; `number_of_pins[GPIO_ID_HPD]=6`, line 171), so
  **en=6 (DDC_VGA) and en=7 (I2C_PAD) index 1 and 2 entries out of bounds** —
  an OOB read of `const` rodata whose garbage `int_status`/`toggle_filt_cntl`
  descriptors then drive MMIO via `REG_GET`/`REG_UPDATE` (hw_hpd.c).

## DCE110 differences vs the dce80 twin, both verified on the guest

- (a) **No `mmGPIOPAD_A` reverse-map case** — the register is not even defined
  in dce_11_0_d.h; feeding the dce80 value 0x183 returns `false` (T[GPIOPAD]).
  The deterministic DF-4942 producer (GPIOPAD → en up to 30 → ddc arrays) is
  structurally absent on dce110. The uninit-id path is the only cross-domain
  route and is probabilistic (needs garbage == 3).
- (b) **No `GPIO_ID_GPIO_PAD` forward-map case** in `id_to_offset` → the
  DF-4944 mask-vs-index defect does not exist here (T: id_to_offset(GPIO_PAD,5)
  = false).
- (c) `ddc_data_regs[]`/`ddc_clk_regs[]` have 8 entries (hw_factory_dce110.c:80-100),
  consistent with the DDC-line domain 0..7 — in-bounds (no finding).

## Fix validation

`fix.diff` = dce110 hunks (8× `*id = GPIO_ID_DDC_DATA`) + consumer hardening in
`dal_gpio_service_create_irq` (init `id = GPIO_ID_UNKNOWN`, reject if still
unknown). The `-DFIXED` build of the harness applies exactly the 8-branch edit:
`fixrun.log` shows all eight DDC-family decodes now write `id=DDC_DATA(0)`
(poison eliminated) with **zero regressions** on the controls; with the fix,
`dal_gpio_create_irq` deterministically rejects DDC_DATA (default branch → NULL)
instead of switching on garbage.

## Severity

Low (matches DF-4945/DF-4946): crafted-VBIOS precondition + stack-garbage==HPD
final stage; worst case OOB rodata read → wild MMIO → panic/attach failure on
Tonga/Fiji/Carrizo-class (DCE110) hardware. Not unprivileged-user-reachable on
stock systems.

## Guest

DragonFly 6.5-DEVELOPMENT #0 (X86_64_GENERIC, 2026-07-02), gcc 8.3.
`amdgpu` modules loaded: 0; AMD PCI devices: 0; `/dev/dri` absent — kernel-stage
execution of the VBIOS-driven GPIO decode is impossible on this QEMU guest, so
the verbatim translate functions were executed at unit level instead.

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