irq_source_info_dce120[] 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/4713/4932/4995/5054 NULL-funcs-dispatch family instance on the DCE120 table
Summary
Designators stop at 83 while the enum runs to 90 - the exact shape noted for maintainers in DF-4932. Latent (no in-tree caller passes 84..89; traced). Verbatim replica: SIGSEGV exit=139 x2 deterministic; six-dummy fix validated via full amdgpu.ko -Werror rebuild.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5078 Β· 16 files| File | Type | Description | Size | |
|---|---|---|---|---|
| dce120_vline0gap.c | β | 35.8 KB | view raw | |
| build.sh | β | 79 B | view raw | |
| run.sh | β | 103 B | view raw | |
| build.log | β | 188 B | view raw | |
| run.log | β | 2.5 KB | view raw | |
| run.2.log | β | 2.5 KB | view raw | |
| dmesg.txt | β | 1.2 KB | view raw | |
| fix.diff | β | 666 B | view raw | |
| amdgpu_module_build.log | β | 1.2 MB | β download | |
| fix_build.log | β | 1.2 MB | β download | |
| fix_run.log | β | 1.5 KB | view raw | |
| env.txt | β | 201 B | view raw | |
| VERDICT.md | β | 4.5 KB | β raw | |
| README.md | β | 2.0 KB | β raw | |
| verdict.json | β | 6.3 KB | view raw | |
| manifest.json | β | 1.3 KB | view raw |
DF-5078 β DCE120 irq table VLINE0 gap β NULL .funcs dispatch
File: sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:177-263
(DF-2168/DF-4713/DF-4932/DF-4995/DF-5054 family instance on the DCE120 table β
the shape noted for maintainers in DF-4932's verdict)
Build (on the guest)
mkdir -p /root/df5078 && cp dce120_vline0gap.c build.sh run.sh /root/df5078/ sh /root/df5078/build.sh
Run (on the guest; run twice for determinism)
sh /root/df5078/run.sh # -> run.log, run.2.log
Expected
- baseline (
dce120_vline0gap_base): - static audit: exactly 6 NULL-funcs slots β 84..89
(
DC_IRQ_SOURCE_DC{1..6}_VLINE0, enum 84..89 <DAL_IRQ_SOURCES_NUMBER=90, irq_types.h:140-148); - controls pass: ack(90) rejected; set(PFLIP1) generic; dce120 hpd_ack polarity toggle; VBLANK1..6 through the real conversion path arm pipes 0..5; to_dal sweep (256 src x 13 ext) returns 0 results in 84..89;
- trigger:
dal_irq_service_ack(DC_IRQ_SOURCE_DC1_VLINE0)β child dies signal 11 at theinfo->funcs->ackderef (irq_service.c:152);dal_irq_service_set(...)in the main process β SIGSEGV exit 139 (:116 acks first β same deref). Kernel-equivalent: page-0 read β panic. - fixed (
-DFIX_DF5078, = fix.diff): 0 NULL-funcs slots, dummy handlers log-and-return, exit 0.
Observed (guest, cc 8.3): baseline exit=139 x2 (child signal 11 + main
fault), fixed exit=0 x2. Kernel console corroborates the faults
(dmesg.txt: pid ... (dce120_vline0gap) ... exited on signal 11).
Fix validation: both dce120 fix.diffs (DF-5078 + DF-5079) applied to guest
/usr/src, full make -j6 amdgpu.ko module rebuild rc=0, 0 errors / 0
warnings under -Werror (amdgpu_module_build.log, 777 lines;
irq_service_dce110.c + irq_service_dce120.c both recompiled at :571-574);
sources reverted md5-verified pristine; make clean.
Reachability is latent (traced in VERDICT.md) and the guest has no AMD GPU β family-standard logic-level replica methodology (same as DF-4932/DF-4995/DF-5054).
DF-5078 VERDICT β dce120 VLINE0 table gap (NULL .funcs dispatch), replica-reproduced
Status: reproduced (logic level, family-standard replica), impact panic, confidence certain. Same methodology and ceiling as DF-4932 (dce110), DF-4995 (dcn10), DF-5054 (dce80) β the DCE120 instance of the family, noted for maintainers in DF-4932's verdict and now filed per-file ("each asic table is its own code").
Root cause (code-certain)
irq_source_info_dce120[DAL_IRQ_SOURCES_NUMBER] (irq_service_dce120.c:177-263)
designators cover exactly enum sources 0..83:
INVALID(0); HPD1+0..5(1..6); HPD1RX+0..5(7..12); I2C_DDC1..6(13..18); DPSINK1..6(19..24); TIMER(25); PFLIP1+0..5(26..31); PFLIP_UNDERLAY0(32); GPIOPAD0..30(33..63); DC1..6UNDERFLOW(64..69); DMCU_SCP(70); VBIOS_SW(71); VUPDATE1+0..5(72..77); VBLANK1+0..5(78..83)
The shared enum (irq_types.h:40-148) continues to
DC_IRQ_SOURCE_DC{1..6}_LINE0 = 84..89 < DAL_IRQ_SOURCES_NUMBER=90 β
those six entries stay zero-initialized, .funcs == NULL.
find_irq_source_info (irq_service.c:77-86) bounds-checks ONLY the index, so
dal_irq_service_ack (:152 β invoked FIRST by dal_irq_service_set at :116)
dereferences info->funcs->ack on NULL, and dal_irq_service_set (:118)
info->funcs->set β a read at page-0 offset ~40 β kernel page fault/panic.
DF-2168/DF-4713 is the hub-level family root; this is the dce120 table's own
completeness gap.
Reproduction (this run, on the audit guest)
Verbatim userland replica of the dce120 entry macros + FULL table body + dce120 hpd_ack + dummy funcs + dce110_vblank_set + to_dal_irq_source_dce110 + the irq_service.c:77-158 dispatch (see dce120_vline0gap.c header for the path:line map). Results (run.log, run.2.log β deterministic x2):
- static audit:
NULL-funcs entries: 84 85 86 87 88 89 (6 NULL-funcs slots) - controls: ack(90) rejected; set(PFLIP1) generic path ok; dce120 hpd_ack polarity toggle ok; VBLANK1..6 arm pipes 0..5 through the real conversion; to_dal sweep (256 src x 13 ext incl. 0xdead): 0 returns in 84..89
- trigger-child
ack(84):info->funcs == 0x0β signal 11 - trigger-main
set(84): Segmentation fault, exit 139 - fixed mode (six dummy entries = fix.diff): 0 NULL-funcs, dummy handlers log-and-return, exit 0
Kernel console corroborates the faults on the guest (dmesg.txt: four
pid ... (dce120_vline0gap) ... exited on signal 11 lines per run).
Reachability (traced honestly β latent)
- IH arrival:
amdgpu_dm_irq_handler(amdgpu_dm_irq.c:477-487) converts viato_dal_irq_source_dce110β can only return covered sources or INVALID (dummy entry), never 84..89 (sweep above). dm_irq_state(amdgpu_dm_irq.c:535-556): IRQ_TYPE_PFLIP/IRQ_TYPE_VBLANK +acrtc->otg_inst(hardware-bounded 0..5) β 26..31 / 78..83.- HPD init/fini (amdgpu_dm_irq.c:625-645, 515-527): HPD/HPDRX only.
amdgpu_dm.c:3014:IRQ_TYPE_VBLANK + acrtc->otg_inst.- The service exists only on DCE12 (Vega10/12) hardware (dce120_resource.c:1011); guest has 0 AMD PCI devices.
β No unprivileged trigger exists today; the panic is one future caller away
(a DM change using VLINE0 on DCE12, or any caller gating on the
DAL_VALID_IRQ_SRC_NUM off-by-one at irq_types.h:157-158, which admits
src == DAL_IRQ_SOURCES_NUMBER).
Ceiling
NULL-page read at a fixed small offset β hard kernel panic (local DoS). No write primitive, no leak. Severity Low (family-consistent).
Fix validation
fix.diff = six [DC_IRQ_SOURCE_DCx_VLINE0] = dummy_irq_entry() designators
completing the table over the shared enum (DF-4932/DF-4995/DF-5054's exact
per-asic shape). Applied to guest /usr/src together with DF-5079's diff:
patch -V none -p1, hunk #1 succeeded at :260; full make -j6 amdgpu.ko
rebuild rc=0, 0 error: / 0 warning: under -Werror
(amdgpu_module_build.log 777 lines; irq_service_dce120.c compiled at :574);
replica fixed mode exit 0; sources reverted md5-verified pristine
(51bd6ea8...), make clean. Guest returned to clean snapshot afterwards.
Artifacts
dce120_vline0gap.c (code_hash d196028e...), build.log, run.log, run.2.log, dmesg.txt, env.txt, fix.diff, amdgpu_module_build.log, fix_build.log, fix_run.log, manifest.json, verdict.json.
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
fixedfix.diff applied to guest /usr/src (patch -V none -p1, hunk #1 at :260); full make -j6 amdgpu.ko rebuild rc=0 with 0 errors/0 warnings under -Werror (amdgpu_module_build.log; irq_service_dce120.c compiled at :573-574); replica fixed mode (identical shape) exits 0 where baseline exits 139; sources reverted md5-verified pristine (51bd6ea8...), make clean.
fix_build.log (=amdgpu_module_build.log, rc=0, zero diagnostics); fix_run.log (fixed mode: 0 NULL-funcs slots, dummy ack/set log-and-return, exit 0); run.log (baseline exit=139)
Confirmed kernel references
- sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:177
- sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:263
- 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:147
- sys/dev/drm/amd/display/dc/irq_types.h:157
- sys/dev/drm/amd/display/dc/dce120/dce120_resource.c:1011
Detail
Evidence (decisive lines)
run.log + run.2.log (deterministic x2: 6 NULL-funcs slots 84..89; controls pass incl. VBLANK1..6 arming pipes 0..5 and to_dal sweep 0 hits in 84..89; child ack(84) signal 11; main set(84) 'Segmentation fault' exit=139; fixed mode exit=0); dmesg.txt (kernel-observed signal-11 exits of the replica); dce120_vline0gap.c header (path:line map); amdgpu_module_build.log (777 lines, rc=0, 0 error:/0 warning:, irq_service_dce120.o at :573-574)
PoC changes
Self-authored from the family template (DF-5055's harness skeleton): instantiated the FULL dce120 designator set (not just the defect region) with the dce120 SRI/IRQ_REG_ENTRY macro forms (SRI collapsed to straight mm
Verified recommended fix
Complete the dce120 table over the shared enum: six [DC_IRQ_SOURCE_DCx_VLINE0] = dummy_irq_entry() designators (fix.diff); hub-level hardening (funcs NULL guards in irq_service.c set/ack) tracked by DF-4932.
Verdict
Reproduced at logic level with a verbatim userland replica of the FULL dce120 irq table (irq_service_dce120.c:87-263 entry macros incl. the SRI/IRQ_REG_ENTRY forms, dce120 hpd_ack :40-65, funcs tables :67-85), to_dal_irq_source_dce110 (dce110:315-393, the converter dce120 installs at :266), dce110_vblank_set (dce110:195-219) and the generic dispatch (irq_service.c: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, and find_irq_source_info (irq_service.c:82) bounds-checks only the index, so dal_irq_service_ack (:152, called first by dal_irq_service_set at :116) and dal_irq_service_set (:118) dereference info->funcs->ack/.set on NULL β replica ack(84) child dies signal 11 at the deref and set(84) in the main process SIGSEGVs deterministically (exit 139, both runs), the kernel-equivalent being a page-0 read at ~offsetof(.funcs->ack) => hard panic. This is the DF-2168/DF-4713/DF-4932/DF-4995/DF-5054 NULL-funcs-dispatch family instance on the DCE120 (Vega10/12) table β the shape noted for maintainers in DF-4932's verdict; each asic table is its own code. Reachability is latent and traced honestly: every in-tree dc_interrupt_set/ack caller was checked (dm_irq_state PFLIP/VBLANK+otg_inst hardware-bounded 0..5 per amdgpu_dm_irq.c:535-556; hpd_init/fini HPD/HPDRX per amdgpu_dm_irq.c:625-645 and :515-527; amdgpu_dm.c:3014 VBLANK+otg_inst; the IH path amdgpu_dm_irq.c:477-487 can only receive to_dal-mapped covered sources or INVALID β the harness to_dal walk (256x13 combos incl. 0xdead) returns 0 results in 84..89), and the service is created only on DCE12 hardware (dce120_resource.c:1011) while the guest has no AMD GPU (0 PCI 1002: devices). No unprivileged trigger exists today; the panic is one future caller away (a DM change using VLINE0 on DCE12, or the DAL_VALID_IRQ_SRC_NUM off-by-one at irq_types.h:157-158 admitting src==90 into any caller gating on it). No write primitive, no leak; ceiling is a kernel NULL-page-read panic (local DoS). FIX VALIDATED: fix.diff (six VLINE0 dummy_irq_entry() designators completing the table, the DF-4932/DF-4995/DF-5054 per-asic shape) applied to guest /usr/src together with DF-5079's (hunk at :260); full amdgpu.ko module rebuild under -Werror rc=0, zero errors, zero warnings, irq_service_dce120.o recompiled and linked (amdgpu_module_build.log:574); replica fixed mode handles VLINE0 via dummy log-and-return handlers, exit 0 vs baseline 139; guest sources reverted md5-verified pristine (51bd6ea8...), make clean, guest returned to clean snapshot.
No comments yet.