β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4033

NULL radeon_encoder dereference family in connector property handlers and monitor-bpc path

Summary

scaling-mode/output-csc blocks, radeon_lvds_set_property and radeon_get_monitor_bpc's LVDS/eDP branch obtain the encoder via best_encoder() when connector->encoder==NULL and dereference it unchecked; best_encoder returns NULL when the possible-encoder list is empty (connector-table/BIOS misconfiguration or partial bring-up). Local DoS via DRM_MASTER-gated SETPROPERTY or any modeset reaching monitor_bpc. NULL-guard fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4033 Β· 11 files
FileTypeDescriptionSize
README.md β€” 553 B ↓ raw
VERDICT.md β€” 3.1 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 β€” 1.6 KB view raw
run.2.log β€” 881 B view raw
run.log β€” 117 B view raw
run.sh β€” 89 B view raw
verdict.json β€” 2.9 KB view raw

DF-4033 evidence pack

Connector property handlers and radeon_get_monitor_bpc dereference radeon_encoder without a NULL check after best_encoder() (radeon_connectors.c:733/737, :753, :972/975, :161-165). radeon_dvi_encoder

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.

VERDICT.md
↓ download raw

DF-4033 β€” NULL radeon_encoder dereference family in connector property handlers and monitor-bpc path

File: sys/dev/drm/radeon/radeon_connectors.c Severity: Low (local DoS panic; DRM_MASTER-gated for the property paths, misconfiguration-gated) Class: CWE-476 NULL pointer dereference.

Root cause (path:line)

Three property handlers and one bpc helper obtain the encoder via connector_funcs->best_encoder(connector) (when connector->encoder == NULL) and then dereference the result without a NULL check:

  • radeon_connector_set_property() scaling-mode block β€” deref at radeon_connectors.c:733 (radeon_encoder->rmx_type) and :737 (->native_mode.clock); encoder from :719-724.
  • radeon_connector_set_property() output-csc block β€” deref at radeon_connectors.c:753 (radeon_encoder->output_csc); encoder from :746-751.
  • radeon_lvds_set_property() β€” deref at radeon_connectors.c:972/:975; encoder from :958-963.
  • radeon_get_monitor_bpc() LVDS/eDP branch β€” deref at radeon_connectors.c:163-165 (dig = radeon_encoder->enc_priv; dig->lcd_misc); encoder from :161 (radeon_best_single_encoder returns NULL on an empty possible-encoder list).

best_encoder is radeon_dvi_encoder for DVI/DP connectors (radeon_connectors.c:1453-1478), which returns NULL when the connector's possible-encoder list is empty (all three loops fall through to return NULL at :1477), and radeon_best_single_encoder (:379-389) returns NULL in the same situation. Empty possible-encoder lists occur on connector-table/BIOS misconfigurations and on partially failed connector bring-up (the same class of misconfiguration that DF-1343/DF-1344 depend on).

Reachability: DRM_IOCTL_MODE_SETPROPERTY/MODE_OBJ_SETPROPERTY are DRM_MASTER (sys/dev/drm/drm_ioctl.c:667,679) β€” i.e. the X server/compositor or any process that acquires master on an unclaimed device; the bpc path is reached from modesets (atombios_crtc.c:987, atombios_dp.c:310, evergreen.c:1290, r600.c:299, rs600.c:164, cik.c:8770). Impact: kernel NULL-deref panic (local DoS).

Upstream status

Upstream Linux master has the identical missing guards (verified against the master file: no if (!radeon_encoder) after any of the four sites). Unfixed upstream.

Verification (this pack)

  • conn_probe.c mode setprop β€” raw DRM_IOCTL_MODE_OBJ_SETPROPERTY probe of the connector-property surface (builds clean on the guest; run.log).
  • Runtime hardware-gated (no radeon GPU on the audit guest β€” env.txt); the dereference itself is source-certain given an empty possible-encoder list.

Suggested fix

fix.diff: NULL-check radeon_encoder (three property sites) and NULL-check encoder/enc_priv in radeon_get_monitor_bpc.

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_testable
baseline no→ patch + rebuild →patched clean

fix.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
↓ fix.diffper-fix-DF-4033

Confirmed kernel references

Detail

Exploit chain

DRM master (or unclaimed-master process) sets a connector's scaling-mode property on a connector whose possible-encoder list is empty -> immediate kernel 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

NULL-check radeon_encoder at the four sites (see fix.diff).

Verdict

Connector property handlers and radeon_get_monitor_bpc dereference radeon_encoder without a NULL check after best_encoder() (radeon_connectors.c:733/737, :753, :972/975, :161-165). radeon_dvi_encoder (best_encoder for DVI/DP) returns NULL on an empty possible-encoder list (radeon_connectors.c:1453-1478), so a connector-table misconfiguration turns DRM_MASTER-gated property ioctls (drm_ioctl.c:667/679) and modesets into a NULL-deref panic. Same missing guards exist in upstream Linux master. Hardware-gated: no radeon GPU on the audit guest.