# DF-4788 VERDICT

* **Status:** untested (hardening / latent, no reachable path)
* **Confidence:** likely
* **Severity filed:** Info

## Analysis

### Unbounded `en` bitmap indexing (CWE-129 / CWE-787 latent)

* Sizing: `gpio_service.c:88-118` — `kcalloc((number_of_pins[id] + 31) / 32, 4)` stored
  in `service->busyness[id]`.
* Use: `gpio_service.c:190-222` — `is_pin_busy` / `set_pin_busy` / `set_pin_free` index
  `busyness[id][en/32]` with a caller-supplied `uint32_t en`; no comparison against
  `number_of_pins[id]` anywhere between `dal_gpio_service_open` (`:224`) and the bitmap
  touch. `set_pin_busy` is called at `:287` with the raw `en`.
* Bound sources today (why unreachable):
  * DDC: `dal_gpio_create_ddc` (`gpio_service.c:418`) gets `en` from
    `translate.funcs->offset_to_id()` whose mask switches only emit
    `GPIO_DDC_LINE_DDC1..I2C_PAD` (`dce110/hw_translate_dce110.c` DDC case);
    `dal_hw_ddc_create` re-validates (`hw_ddc.c:219-222`) before allocating.
  * HPD: `dal_gpio_service_create_irq` (`gpio_service.c:151`) — same translate
    mechanism, masks emit `GPIO_HPD_1..6` only; `dal_hw_hpd_create` re-validates
    (`hw_hpd.c:144-152`).
  * `dal_gpio_create_irq` rejects every id except HPD/GPIO_PAD (`gpio_service.c:373-381`)
    and GPIO_PAD pins cannot open at all (no case in `dal_gpio_service_open`).
* Consequence if a future caller passes raw `en`: OOB heap write (`set_pin_busy`) /
  read (`is_pin_busy`) — the bitmap is a small standalone kmalloc, so an overflow lands
  in adjacent slab objects. That is why the missing bound is worth fixing even though it
  is presently dead.

### NULL creator pointers

* `hw_factory_dce110.c:144-154`, `hw_factory_dce80.c:150-156`,
  `hw_factory_dce120.c:167-173`, `hw_factory_dcn10.c:162-169`: `.create_generic`,
  `.create_sync`, `.create_gsl` are NULL; `.define_*_registers` present.
* `gpio_service.c:254-270` invokes them without a NULL check (NULL text pointer call →
  panic at address 0).
* Tree-wide `rg 'GPIO_ID_GENERIC|GPIO_ID_SYNC|GPIO_ID_GSL'` shows users only inside the
  gpio directory itself (translate tables, `dal_gpio_get_sync_source` which never opens);
  no display component opens those ids → latent.

## Why untested

No AMD GPU in the audit QEMU guest (`env.txt`), and even on hardware there is no caller
that reaches the defective arms — this is a defense-in-depth finding by construction.

## Recommended fix summary

Add `en >= service->factory.number_of_pins[id] → GPIO_RESULT_INVALID_DATA` at the top of
`dal_gpio_service_open`, and NULL-check the `create_*` pointers (already included in
DF-4787/fix.diff).

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