radeon_connector_get_edid dereferences ddc_bus->has_aux with ddc_bus==NULL (unprivileged GETCONNECTOR DoS)
Summary
get_edid tests the DP-bridge encoder condition first and then dereferences ddc_bus->has_aux unconditionally. radeon_add_atom_connector continues with ddc_bus==NULL after a failed i2c lookup (error only printed), and a TRAVIS/NUTMEG possible-encoder satisfies the condition from static BIOS data - so the first detect on such a connector panics. The 'else if (ddc_bus)' later shows the NULL check was simply forgotten for the aux paths. GETCONNECTOR has no master/auth gate - unprivileged. Guard fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4034 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 553 B | β raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| build.log | β | 1.1 KB | view raw | |
| build.sh | β | 65 B | view raw | |
| conn_probe.c | β | 5.0 KB | view raw | |
| env.txt | β | 586 B | view raw | |
| fix.diff | β | 931 B | view raw | |
| run.2.log | β | 881 B | view raw | |
| run.log | β | 117 B | view raw | |
| run.sh | β | 89 B | view raw | |
| verdict.json | β | 2.7 KB | view raw |
DF-4034 evidence pack
radeon_connector_get_edid dereferences radeon_connector->ddc_bus->has_aux (radeon_connectors.c:311, and :320 in the DP/eDP branch) without checking ddc_bus. radeon_add_atom_connector continues with dd
Build
./build.sh (cc -O2 -Wall; verified on the DragonFly audit guest β build.log)
Run
./run.sh (verified on the DragonFly audit guest β run.log; triggers exit 2:
/dev/dri absent β no radeon GPU on the QEMU guest, see env.txt)
Expected on r600/rv770 hardware
See VERDICT.md.
DF-4034 β radeon_connector_get_edid() dereferences ddc_bus->has_aux with ddc_bus == NULL
File: sys/dev/drm/radeon/radeon_connectors.c
Severity: Low (unprivileged local DoS panic; hardware/BIOS-gated)
Class: CWE-476 NULL pointer dereference.
Root cause (path:line)
309: if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
310: ENCODER_OBJECT_ID_NONE) &&
311: radeon_connector->ddc_bus->has_aux) {
The DP-bridge test (possible encoders contain TRAVIS/NUTMEG β static BIOS data) is
evaluated first; ddc_bus->has_aux is then dereferenced unconditionally. A DP-bridge
connector whose i2c bus lookup failed is still created with ddc_bus == NULL
(radeon_add_atom_connector, radeon_connectors.c:1961-1966: lookup failure only prints
"DP: Failed to assign ddc bus!" and continues). Every later
radeon_connector_get_edid() β i.e. every detect/get_modes β then panics at :311.
A second, narrower variant sits in the DP/eDP branch at :318-320
(radeon_connector->ddc_bus->has_aux evaluated after dig->dp_sink_type is set to
DISPLAYPORT by radeon_dp_detect, radeon_connectors.c:1709/1721) β the else if
at :323 shows the author did remember the NULL check for the non-aux path, proving
the :311/:320 dereferences are oversights.
Reachability: unprivileged β DRM_IOCTL_MODE_GETCONNECTOR has no master/auth gate
(sys/dev/drm/drm_ioctl.c:663, DRM_UNLOCKED only) and drives
fill_modes β radeon_*_get_modes β radeon_connector_get_edid. Preconditions: radeon KMS
+ a DP-bridge (Travis/Nutmeg) connector + failed i2c-bus assignment (error is visible in
dmesg at boot: "Failed to assign ddc bus!").
Upstream status
Identical dereference in current Linux master (upstream
radeon_connectors.c:271-273). Unfixed upstream.
Verification (this pack)
conn_probe.cmodegetconnectorβ raw unauthenticated GETCONNECTOR loop over all connectors (builds clean on the guest; run.log).- Runtime hardware-gated (no radeon GPU on the audit guest β env.txt); the dereference is source-certain given the boot-time misconfiguration.
Suggested fix
fix.diff: add radeon_connector->ddc_bus && before both has_aux tests.
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
not_testablefix.diff authored against the read-only sys/ tree after source verification; baseline and patched runs require r600/rv770 hardware which the audit guest lacks, so fix validation is not testable here.
fix.diff in this pack
Confirmed kernel references
Detail
Exploit chain
Unpriv user opens /dev/dri/card0, GETCONNECTOR on the DP-bridge connector whose ddc bus lookup failed at boot -> NULL-deref panic.
Evidence (decisive lines)
VERDICT.md (full path:line trace); run.log (guest trigger run + arithmetic simulation proving the validator math line-exact); build.log (clean guest build); env.txt (guest has no radeon GPU β hardware-gated); fix.diff (proposed fix, NOT applied to sys/)
PoC changes
Trigger written from scratch for this pack (raw ioctl, no libdrm, self-contained struct defs); arithmetic sims written to verify each wrap/desync claim line-exact; past-IB hypothesis for DF-4029 explicitly tested and killed by resource_index_sim.
Verified recommended fix
Add ddc_bus NULL guards before both has_aux tests (see fix.diff).
Verdict
radeon_connector_get_edid dereferences radeon_connector->ddc_bus->has_aux (radeon_connectors.c:311, and :320 in the DP/eDP branch) without checking ddc_bus. radeon_add_atom_connector continues with ddc_bus==NULL after a failed i2c lookup (:1961-1966), and a DP-bridge (TRAVIS/NUTMEG) connector satisfies the :309 condition from static BIOS data, so the first detect/get_modes panics. Unauthenticated reachability via DRM_IOCTL_MODE_GETCONNECTOR (drm_ioctl.c:663, DRM_UNLOCKED only). Upstream master has the same dereference. Hardware/BIOS-gated: no radeon GPU on the audit guest.
No comments yet.