irq_source_info_dce80[] leaves DC_IRQ_SOURCE_DC{1..6}_VLINE0 (enum 84..89) zero-initialized with .funcs==NULL; dal_irq_service_set/ack dereference info->funcs unguarded β DF-2168/DF-4932/DF-4995 family instance on the DCE80 table
Summary
Designators cover 0..83 while the enum runs to 90 - slots 84..89 stay zeroed, and set/ack fault at irq_service.c:152 reading NULL+offset. No in-tree caller passes 84..89 (proven by 256x13 sweep of the IH converter) - latent like the dce110 twin. Verbatim replica SIGSEGV x2 deterministic; six dummy entries + hub guards fix; amdgpu.ko rebuild -Werror clean.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5054 Β· 14 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.7 KB | β raw | |
| VERDICT.md | β | 5.3 KB | β raw | |
| dce80_vline0gap.c | β | 28.6 KB | view raw | |
| build.sh | β | 128 B | view raw | |
| run.sh | β | 117 B | view raw | |
| build.log | β | 185 B | view raw | |
| run.log | β | 2.2 KB | view raw | |
| run.2.log | β | 187 B | view raw | |
| env.txt | β | 397 B | view raw | |
| fix.diff | β | 986 B | view raw | |
| amd_fix_apply.log | β | 850 B | view raw | |
| amdgpu_module_build.log | β | 1.2 MB | β download | |
| manifest.json | β | 2.2 KB | view raw | |
| verdict.json | β | 5.3 KB | view raw |
DF-5054 β irq_service_dce80[] leaves DC_IRQ_SOURCE_DC{1..6}_VLINE0 (enum 84..89) zero-initialized with .funcs==NULL β DF-2168/DF-4932/DF-4995 family on the DCE80 (Sea Islands) table
What
irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER=90]
(sys/dev/drm/amd/display/dc/irq/dce80/irq_service_dce80.c:188-274) has
designators covering exactly indices 0..83 (last:
vblank_int_entry(5) == DC_IRQ_SOURCE_VBLANK6 == 83). The shared enum
(irq_types.h:140-147) continues with
DC_IRQ_SOURCE_DC1_VLINE0..DC6_VLINE0 = 84..89 β those six slots stay
zero-initialized, i.e. .funcs == NULL. find_irq_source_info
(irq_service.c:82) bounds-checks only the index, and
dal_irq_service_set/dal_irq_service_ack dereference
info->funcs->set/->ack unguarded (irq_service.c:118/:152) β a
set/ack of any VLINE0 source faults reading NULL+offsetof. Hub finding:
DF-2168; family: DF-4932 (dce110), DF-4995 (dcn10).
Reproduce (on the QEMU guest; no AMD GPU needed β verbatim userland replica)
# build: sh build.sh # cc -O2 -Wall -std=gnu11 [-DFIX_DF5054] # run: sh run.sh # baseline then fixed
The replica carries the enum, structs, the dce80 entry macros (including
the dce80-specific [DC_IRQ_SOURCE_INVALID + reg_num] /
[DC_IRQ_SOURCE_HPD6 + reg_num] designator forms), the table body,
to_dal_irq_source_dce110 (the converter dce80 installs, dce80:277,
with the real VISLANDS30 constants), and the irq_service.c dispatch β
verbatim. Register addresses/masks are stubbed inert data.
Expected output
Baseline (run.log / run.2.log): table[84..89] (.funcs == NULL) x6,
controls pass (OOB index 90 rejected; PFLIP1 generic set programs its
enable reg; dce80 hpd_ack toggles polarity; 256x13 to_dal sweep: 0
VLINE0 returns β latent), then
dal_irq_service_set(DC_IRQ_SOURCE_DC1_VLINE0) β SIGSEGV exit 139
at the info->funcs->ack deref. Deterministic x2.
Fixed (-DFIX_DF5054): 0 NULL-funcs entries, dummy handlers log and
return, exit 0. Also validated by a full -Werror amdgpu.ko module
rebuild with fix.diff applied (RC=0, irq_service_dce80.o linked,
amdgpu_module_build.log), then sources reverted md5-verified.
Severity rationale
Low (family rating): kernel NULL-deref panic, latent β no in-tree caller passes a VLINE0 source (traced: suspend/resume touch HPD/HPDRX only (amdgpu_dm_irq.c:353/380/406), vblank enable is IRQ_TYPE_VBLANK+otg_inst (amdgpu_dm.c:3014-3015), pflip is IRQ_TYPE_PFLIP (amdgpu_dm_irq.c:570), and the IH path converts through to_dal_irq_source_dce110 which can never return 84..89 β proven by the replica's full src-id sweep). Guest has no AMD GPU. One future caller away from a remote-ish panic on DCE80-era ASICs (Oland/Bonaire/Hawaii/Kabini).
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), sofind_irq_source_inforeturns&info[84](non-NULL).irq_service.c:116βdal_irq_service_ackβirq_service.c:152if (info->funcs->ack)β the NULL+offsetof(.ack) load faults (dal_irq_service_setcalls 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/srcpatched (amd_fix_apply.log: patched md5 0cdb51fa69c1019438882d26fe100eda), fullmake -j6amdgpu.ko module rebuild under the module-Werrorflag 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 βfuncsitself is non-NULL and irq_service.c:118/ 152 NULL-check the members before calling; the generic fallback runs.struct irq_service_funcshas exactly one member (to_dal_irq_source, irq_service.h:59-64);irq_service_funcs_dce80sets 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_NUMoff-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.
Fix verification
fixedfixed: fix.diff (six VLINE0 dummy entries) applied to guest /usr/src (patched md5 0cdb51fa69c1019438882d26fe100eda, together with DF-5055's diff); full make -j6 amdgpu.ko rebuild under -Werror RC=0, zero error/warning diagnostics, irq_service_dce80.o linked (amdgpu_module_build.log); replica fixed mode exit 0 vs baseline SIGSEGV 139; sources reverted md5-verified pristine (f20f096b3f00c5186a514e7aa3b84db4), module objects cleaned, guest reset to the with-src snapshot.
fix.diff; amd_fix_apply.log; amdgpu_module_build.log; run.log (baseline crash + fixed exit 0); run.2.log; VERDICT.md
Confirmed kernel references
- sys/dev/drm/amd/display/dc/irq/dce80/irq_service_dce80.c:188
- sys/dev/drm/amd/display/dc/irq/dce80/irq_service_dce80.c:273
- sys/dev/drm/amd/display/dc/irq/dce80/irq_service_dce80.c:277
- sys/dev/drm/amd/display/dc/irq/irq_service.c:82
- sys/dev/drm/amd/display/dc/irq/irq_service.c:116
- sys/dev/drm/amd/display/dc/irq/irq_service.c:118
- sys/dev/drm/amd/display/dc/irq/irq_service.c:152
- sys/dev/drm/amd/display/dc/irq_types.h:140
- sys/dev/drm/amd/display/dc/irq_types.h:158
- sys/dev/drm/amd/display/dc/core/dc.c:1687
- sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c:353
- sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:3014
Detail
Evidence (decisive lines)
run.log + run.2.log (decisive: 'table[84..89] (.funcs == NULL)' x6; trigger 'dal_irq_service_set(DC_IRQ_SOURCE_DC1_VLINE0=84)' -> Segmentation fault exit 139 both runs; fixed section exit 0); dce80_vline0gap.c (verbatim replica); amd_fix_apply.log + amdgpu_module_build.log (777-line -Werror amdgpu.ko rebuild, RC=0); fix.diff; VERDICT.md
PoC changes
Authored fresh (no seed), modeled on DF-4995's dcn10 replica with the DCE80 file's own macros verbatim: one compile fix (missing bool param in the set_generic forward decl) plus keeping the vblank funcs wiring faithful (.set = dce110_vblank_set stub, cross-referenced to DF-5055 where the real body is exercised).
Verified recommended fix
Add [DC_IRQ_SOURCE_DC1..6_VLINE0] = dummy_irq_entry() designators so the table totals the shared enum; alongside (DF-2168), guard if (!info->funcs) return false; in dal_irq_service_set/ack.
Verdict
Reproduced at logic level with a verbatim userland replica of irq_source_info_dce80[] (entry macros incl. the dce80-specific [DC_IRQ_SOURCE_INVALID+reg_num]/[DC_IRQ_SOURCE_HPD6+reg_num] designator forms, table body, dce80 hpd_ack, funcs tables β irq_service_dce80.c:40-274), to_dal_irq_source_dce110 (dce110:315-393, the converter dce80 installs at :277) and the irq_service.c dispatch (:77-158), run on the audit guest. Designators cover exactly 0..83 while the shared enum runs to DAL_IRQ_SOURCES_NUMBER=90: DC_IRQ_SOURCE_DC{1..6}_VLINE0 (84..89) stay zero-initialized with .funcs==NULL; find_irq_source_info's index bounds check (:82) passes them through and dal_irq_service_ack (:152, called first by dal_irq_service_set at :116) dereferences info->funcs->ack on NULL -> SIGSEGV exit 139, deterministic x2. Controls prove the rest of the table healthy (OOB index 90 rejected; PFLIP1 generic set; dce80 hpd_ack polarity toggle) and latency (256-src x 13-ext to_dal sweep: 0 returns in 84..89 β no in-tree caller can reach the gap; suspend/resume are HPD/HPDRX-only, vblank enable is IRQ_TYPE_VBLANK+otg_inst, pflip is IRQ_TYPE_PFLIP). FIX VALIDATED: six VLINE0 dummy_irq_entry() designators (fix.diff) -> replica fixed mode exit 0 with dummy log-and-return handlers; full amdgpu.ko module rebuild with the fix on guest /usr/src under -Werror RC=0, zero diagnostics, irq_service_dce80.o linked (amdgpu_module_build.log); sources reverted md5-verified pristine. DF-2168 (hub guards) / DF-4932 (dce110) / DF-4995 (dcn10) family instance on the DCE80 (Sea Islands) table; guest has no AMD GPU so the kernel path itself cannot be driven β family-standard replica methodology. Ceiling if a future caller appears: kernel NULL-page-read panic, not controllable corruption.
No comments yet.