Unguarded enc_priv (NULL) dereferences in all DIG setup paths when get_lcd_info()/get_dig_info() fail β NULL-page read at amdgpu attach and NULL-page WRITE on DPMS-ON (DF-3957 amdgpu twin)
Summary
setup_dig_transmitter, setup_dig_encoder, setup_dig and set_crtc_source dereference amdgpu_encoder->enc_priv without a NULL check. enc_priv is NULL whenever get_lcd_info fails (missing/corrupt LVDS_Info VBIOS table) or get_dig_info's kzalloc fails - the dce_v8/10/11 paths assign it verbatim. Crafted/root-flashed VBIOS on an LCD-supporting UNIPHY encoder panics at attach (read) or first modeset (write of panel_mode). DoS only. NULL-guard fix mirroring the guard that exists at :91.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4103 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 3.4 KB | β raw | |
| verdict.json | β | 2.8 KB | view raw | |
| fix.diff | β | 1.8 KB | view raw |
DF-4103 β amdgpu atombios_encoders: unguarded enc_priv (NULL) dereferences in all DIG setup paths
File: sys/dev/drm/amd/amdgpu/atombios_encoders.c (pass 2)
Class: NULL-pointer dereference (CWE-476) β kernel panic / NULL-page WRITE
Hardware gate: AMD GPU (CIK/VI, DCE8/10/11 non-DC asics) with LCD-supporting UNIPHY encoder.
Family: amdgpu twin of DF-3957 (radeon atombios_encoders, same code shape).
Build
Not buildable/runnable on the audit guest: the QEMU guest has no AMD GPU
(pciconf -l: only Intel/QEMU devices; vgapci0 = bochs 1234:1111).
Source-level certainty only. See VERDICT.md.
Run (would be, on hardware / with an emulated ATI ROM)
- Craft a VBIOS image whose encoder table yields an UNIPHY encoder with
ATOM_DEVICE_LCD_SUPPORTbut with theLVDS_Infomaster data table absent (or with a master-table index of 0), soamdgpu_atombios_encoder_get_lcd_info()returns NULL (atombios_encoders.c:2081if (amdgpu_atom_parse_data_header(...))fails β returns NULL at 2205). - Boot /
kldload amdgpuβdce_v10_0_hw_init(dce_v10_0.c:2829) βamdgpu_atombios_encoder_init_dig(atombios_encoders.c:1744) βamdgpu_atombios_encoder_setup_dig_transmitter(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0)(1758) βdig = amdgpu_encoder->enc_priv;(837) βint dig_encoder = dig->dig_encoder;(848) β NULL-page READ β kernel panic.
Expected
Fatal trap 12: page fault while in kernel mode at
amdgpu_atombios_encoder_setup_dig_transmitter+0x... during amdgpu
hw_init (or later, amdgpu_atombios_encoder_setup_dig NULL WRITE at
offset of panel_mode on first DPMS-ON).
Artifacts
- VERDICT.md β full narrative with path:line trace
- verdict.json β machine verdict (status: untested, hardware absent on guest)
- fix.diff β add
if (!dig) return;guards (mirrors the guard the file already has inamdgpu_atombios_encoder_set_backlight_level, :91-93)
DF-4103 VERDICT
Status: untested (hardware-gated β no AMD GPU on the audit guest; source-level certainty certain) Impact: kernel panic (NULL-page read at boot; NULL-page write on DPMS-ON). Not exploitable beyond DoS.
Root cause
For encoders carrying ATOM_DEVICE_LCD_SUPPORT, enc_priv is produced by
amdgpu_atombios_encoder_get_lcd_info():
- dce_v8_0.c:3408, dce_v10_0.c:3520, dce_v11_0.c:3652:
amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_lcd_info(amdgpu_encoder);
That function (atombios_encoders.c:2069-2206) returns NULL when:
1. amdgpu_atom_parse_data_header(...LVDS_Info...) fails (atombios_encoders.c:2081)
β i.e. the VBIOS master data table has no LVDS_Info entry β fully
VBIOS-controlled; or
2. the kzalloc at 2085-2086 fails (OOM at boot).
For non-LCD digital encoders, enc_priv = amdgpu_atombios_encoder_get_dig_info()
(dce_v10_0.c:3524/3528) also returns NULL on kzalloc failure
(atombios_encoders.c:2212-2215).
Four sinks in this file dereference enc_priv with no NULL check:
| sink | deref | nature |
|---|---|---|
amdgpu_atombios_encoder_setup_dig_transmitter :837β848 |
dig->dig_encoder |
NULL read |
amdgpu_atombios_encoder_setup_dig_encoder :648β668 |
dig->dig_encoder == -1 |
NULL read |
amdgpu_atombios_encoder_setup_dig :1402β1414/1420-1422/1445 |
dig->panel_mode = ... |
NULL write |
amdgpu_atombios_encoder_set_crtc_source :1617β1618, :1686β1687 |
dig->dig_encoder |
NULL read |
(Contrast amdgpu_atombios_encoder_set_backlight_level :91-93, which does
guard amdgpu_encoder->enc_priv β the guards were simply never added to the
setup paths.)
Reachability
- Boot path (no user action):
dce_v10_0_hw_init(dce_v10_0.c:2829) βamdgpu_atombios_encoder_init_dig(:1744) β unconditionalsetup_dig_transmitter(ATOM_TRANSMITTER_ACTION_INIT)for every UNIPHY encoder (:1754-1759) β :848 NULL read β panic during driver attach. - Runtime path (mode set):
dce_v10_0_encoder_funcsdpms helpers (dce_v10_0.c:3421/3431) βamdgpu_atombios_encoder_dpms(:1477) βsetup_dig(:1397) β :1414 NULL write to thepanel_modeoffset.
Trigger: crafted/corrupt VBIOS on an LCD (laptop panel) system, or kzalloc failure at the wrong instant. Threat model identical to DF-1380/DF-3744 (root-flashed VBIOS or malicious PCIe device ROM). On DragonFly amd64 the NULL page is unmapped in kernel context β deterministic fatal trap. A NULL-page write at a small fixed offset is not exploitable for code execution on this platform (no mapping at 0).
Why untested
The single-tenant QEMU guest has no AMD GPU (pciconf -l shows only Intel/
QEMU devices; display is bochs 1234:1111 β see verdict.json notes/env). The
amdgpu driver never probes. Both trigger paths are inside amdgpu attach/
modeset, so no in-guest reproduction is possible without the hardware.
Traced the cited path line-by-line instead; conclusion: real defect,
certain, panic-only impact.
Fix
Add NULL guards exactly where the backlight path already has one (atombios_encoders.c:91-93). See fix.diff.
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 adds NULL guards to the four sink functions; cannot be kernel-built/tested on the guest because the amdgpu driver has no hardware to attach to.
findings/poc/DF-4103/fix.diff
Confirmed kernel references
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:837
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:848
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:648
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:668
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:1402
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:1414
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:1617
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:1686
- sys/dev/drm/amd/amdgpu/atombios_encoders.c:2069
- sys/dev/drm/amd/amdgpu/dce_v10_0.c:3516
Detail
Evidence (decisive lines)
VERDICT.md table of the four unguarded sinks; contrast with the existing guard at atombios_encoders.c:91-93; dce_v10_0.c:3516-3528 enc_priv assignment sites; dce_v10_0.c:2829-2839 boot-path caller.
PoC changes
No PoC possible on guest (hardware absent); evidence pack is a source-level trace instead of a runnable trigger.
Verified recommended fix
Guard every enc_priv dereference with if (!dig) return/break, mirroring atombios_encoders.c:91-93.
Verdict
Source-level certain: amdgpu_atombios_encoder_setup_dig_transmitter (:837/:848), setup_dig_encoder (:648/:668), setup_dig (:1402/:1414 NULL write) and set_crtc_source (:1617/:1686) all dereference amdgpu_encoder->enc_priv unguarded; enc_priv is NULL whenever amdgpu_atombios_encoder_get_lcd_info() fails (missing LVDS_Info VBIOS table, atombios_encoders.c:2081) or get_dig_info()/kzalloc fails. Boot-time sink: dce_v{8,10,11}_0_hw_init -> amdgpu_atombios_encoder_init_dig (:1744/:1758). Result is a NULL-page read/write -> deterministic kernel panic (DoS), not code execution. Not runnable: the QEMU audit guest has no AMD GPU (pciconf: bochs 1234:1111 only), so the driver never attaches.
No comments yet.