# DF-5054 — VERDICT

**Status: reproduced (panic-equivalent SIGSEGV in the verbatim replica),
fix validated (module -Werror rebuild + replica fixed mode).**
**Impact: kernel NULL-deref panic (Low, latent). Confidence: certain.**

## The bug (path:line)

- `irq_types.h:140-147` — the shared enum runs to
  DAL_IRQ_SOURCES_NUMBER=90 with DC_IRQ_SOURCE_DC{1..6}_VLINE0 = 84..89
  (replica prints the arithmetic: VBLANK6=83, DC1_VLINE0=84,
  DC6_VLINE0=89, NUMBER=90).
- `irq_service_dce80.c:188-274` — designators cover 0..83 only:
  [INVALID]=0 (dce80:190), hpd(1..6)=[INVALID+1..+6]=1..6 (dce80:191-196),
  hpd_rx(1..6)=[HPD6+1..+6]=7..12 (dce80:197-202), i2c(1..6)=13..18,
  dpsink(1..6)=19..24, [TIMER]=25, pflip(0..5)=[PFLIP1+0..5]=26..31,
  [PFLIP_UNDERLAY0]=32, gpio(0..30)=33..63, underflow(1..6)=64..69,
  [DMCU_SCP]=70, [VBIOS_SW]=71, vupdate(0..5)=72..77,
  vblank(0..5)=78..83. Slots 84..89 have NO designators → C zero-init →
  `.funcs == NULL`.
- `irq_service.c:82` — the index bounds check passes for 84..89
  (< DAL_IRQ_SOURCES_NUMBER), so `find_irq_source_info` returns
  `&info[84]` (non-NULL).
- `irq_service.c:116` → `dal_irq_service_ack` → `irq_service.c:152`
  `if (info->funcs->ack)` — the NULL+offsetof(.ack) load faults
  (`dal_irq_service_set` calls ack FIRST, so set() never even reaches
  its own :118 deref).

Hub: DF-2168 (the missing `!info->funcs` guards). Family twins already
filed: DF-4932 (dce110 table), DF-4995 (dcn10 table). This is the DCE80
table instance — the last-but-one ASIC table (dce120 remains, noted in
DF-4932's summary).

## Reproduction (verbatim userland replica on the audit guest)

`dce80_vline0gap.c` — enum/structs/macros/table/converter/dispatch
verbatim (register data stubbed inert); `cc 8.3 [DragonFly]`.

run.log (baseline):
- `table[84]..table[89] (.funcs == NULL)` — 6 uncovered enum values;
- controls: OOB index 90 rejected by find_irq_source_info (ok); PFLIP1
  set via generic path programs enable_reg 0x2200→1 (ok); HPD1 ack runs
  the dce80-local hpd_ack, polarity bit 0xffffffff→0xfffffffb (ok);
  to_dal sweep 256 src x 13 ext: 246 mapped to covered sources, **0 to
  VLINE0** (latent proof for hunt item c);
- trigger: `dal_irq_service_set(DC_IRQ_SOURCE_DC1_VLINE0=84)` →
  **Segmentation fault, exit 139**.
run.2.log: second baseline, exit 139 again (deterministic).
Fixed (`-DFIX_DF5054`): 0 NULL-funcs; `dal_irq_service_dummy_ack/set`
log-and-return; survived; exit 0.

## Fix validation (fix_status: fixed)

- `fix.diff`: six `[DC_IRQ_SOURCE_DCx_VLINE0] = dummy_irq_entry()`
  designators making the table total over the shared enum (DF-4932/
  DF-4995's shape). Applies clean to the real tree (`patch -p1`, Hunk #1
  succeeded at 271; dry-run verified host-side first).
- Guest `/usr/src` patched (amd_fix_apply.log: patched md5
  0cdb51fa69c1019438882d26fe100eda), full `make -j6` amdgpu.ko module
  rebuild under the module `-Werror` flag set: **RC=0, zero
  error/warning diagnostics, irq_service_dce80.o linked**
  (amdgpu_module_build.log, 777 lines untrimmed; amdgpu.ko 3741304 B).
- Behavioral: replica fixed mode exit 0 (re-run post-build on the same
  guest).
- Revert: reverse patch, md5 back to pristine
  f20f096b3f00c5186a514e7aa3b84db4; `make clean`; scratch removed;
  guest reset to the with-src snapshot afterwards.
- Defense-in-depth (DF-2168's territory, recommended alongside): add
  `if (!info->funcs) return false;` guards in dal_irq_service_set/ack.

## Reachability / ceiling (honest)

Latent: no in-tree caller passes 84..89 (see README). The guest has no
AMD GPU, so the kernel path cannot be driven on this machine — hence the
family's replica-harness methodology (identical to DF-4932/DF-4933/
DF-4995 verdicts). Ceiling if a future caller appears: kernel panic
(NULL-page read), not controllable corruption (the faulting deref reads
a fixed NULL+offset).

## Also checked on this file (pass-2 negatives)

- `hpd_rx_irq_info_funcs`/`pflip_irq_info_funcs` (.set/.ack all NULL,
  dce80:72-80): SAFE — `funcs` itself is non-NULL and irq_service.c:118/
  152 NULL-check the members before calling; the generic fallback runs.
- `struct irq_service_funcs` has exactly one member
  (to_dal_irq_source, irq_service.h:59-64); `irq_service_funcs_dce80`
  sets it (dce80:276-278) — no dce80/dce110 type mismatch (hunt item d).
- hpd pin ranges: mmDC_HPD1..6 for hpd(1..6)/hpd_rx(1..6), field masks
  borrowed from HPD1 across pins (identical DCE8 layout, AMD pattern);
  pflip(0..5) → mmDCP0..5; gpio 0..30; vupdate/vblank CRTC0..5 — all in
  range on DCE80 (hunt item e).
- vblank `.src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 +
  reg_num` (dce80:162): src_ids 19..24 are consecutive
  (ivsrcid_vislands30.h:66-156) — correct.
- `DAL_VALID_IRQ_SRC_NUM` off-by-one (irq_types.h:157-158 allows src==90):
  DF-2168/DF-4932-noted, amdgpu_dm_irq.c-side, harmless against
  find_irq_source_info's own bounds check — not re-filed.
- vupdate entries lacking .src_id → DF-5055 (filed separately).

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