dac1/2_output_control_v1 pass 3 uninitialized stack padding bytes as the VBIOS parameter space
Summary
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params declared without initialization in both dac output_control_v1 handlers; only ucAction is assigned, and the pointer is passed to amdgpu_atom_execute_table - the 3 uninit aucPadding stack bytes become VBIOS-interpreter-readable PS content. Honest VBIOS never reads the padding; crafted/corrupt VBIOS can consume the uninit kernel-stack bytes. No userspace disclosure path demonstrated - Info hardening, in-bounds complement of the known PS-index OOB (DF-1536/1544). {0}-init fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4049 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 1.4 KB | β raw | |
| fix.diff | β | 1.0 KB | view raw | |
| manifest.json | β | 651 B | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-4049 β dac1/2_output_control_v1 pass uninitialized stack bytes as the VBIOS parameter space
What
sys/dev/drm/amd/display/dc/bios/command_table.c:1665-1697:
static enum bp_result dac1_output_control_v1(struct bios_parser *bp, bool enable)
{
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; /* NOT initialized */
if (enable)
params.ucAction = ATOM_ENABLE;
else
params.ucAction = ATOM_DISABLE;
if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION is 4 bytes β ucAction plus
UCHAR aucPadding[3] (sys/dev/drm/amd/include/atombios.h:1657-1667). Only
offset 0 is written; the 3 padding bytes are uninitialized kernel stack
passed by pointer into amdgpu_atom_execute_table, where the atom
interpreter exposes the whole PS area to the (untrusted) VBIOS bytecode.
Every other *_control function in this file either memsets its params or
fully populates them (dac{1,2}_encoder_control_v1 set all three fields of
their 4-byte struct; transmitter/encoder/crtc paths memset). These two
functions are the only uninitialized-PS sites.
Impact
With an honest VBIOS the padding is never read (no effect). With a crafted or corrupt VBIOS β the standing threat model for this parser family (DF-3942, DF-4047) β the interpreter can read the three uninitialized stack bytes and, e.g., store them to MMIO registers (observable via GPU register reads / side channels). Kernel-stack bytes β device-visible, not directly userspace-readable; exploit value is marginal and bounded (3 bytes, adjacent stack content). Info severity hardening (CWE-457).
Fix
- DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+ DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params = {0};
in both functions (fix.diff).
Verification
Source-level (certain); not runnable β hardware-gated (no AMD GPU in guest) and requires a crafted VBIOS to observe any consumption of the padding bytes. Status: untested.
DF-4049 VERDICT β uninitialized PS padding in dac output control
Status: untested (source-certain defect; Info severity)
- Defect certain from source:
command_table.c:1669and:1686declareDISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;without initialization; onlyucAction(offset 0) is assigned (:1671-1674,:1688-1691) and the struct is 4 bytes with 3 bytes ofaucPadding(atombios.h:1657-1667). The pointer is handed toamdgpu_atom_execute_table(:1676,:1693), which exposes the full PS area to VBIOS bytecode (the same interpreter whose unbounded PS indexing is the known DF-1536/DF-1544; this finding is the in-bounds uninit-read complement, not a duplicate of the OOB index issue). - Not runnable: guest has no AMD GPU; observing consumption of the padding requires a crafted VBIOS. No runtime verification attempted (Info-level hardening finding β skipped per contract).
- Impact ceiling: 3 uninitialized kernel-stack bytes made device-register-visible under a crafted VBIOS; no userspace disclosure path demonstrated.
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_testableHardware-gated; one-line zero-init, compile-shape only.
findings/poc/DF-4049/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
README.md source quotes (command_table.c:1669/:1686 declarations, :1671-1674/:1688-1691 partial init; atombios.h:1657-1667 struct), VERDICT.md
Verified recommended fix
Initialize both params structs to zero ({0} or memset) before filling ucAction; see fix.diff
Verdict
Source-certain CWE-457: dac1_output_control_v1 (command_table.c:1665-1680) and dac2_output_control_v1 (:1682-1697) declare DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION (4 bytes: ucAction + aucPadding[3], atombios.h:1657-1667) without initialization, write only ucAction, and pass the struct by pointer to amdgpu_atom_execute_table - the 3 uninitialized stack padding bytes become VBIOS-readable PS content. With an honest VBIOS the padding is unused; with a crafted/corrupt VBIOS (DF-3942/DF-4047 threat model) the interpreter can consume them (e.g. store to MMIO). Info hardening: no userspace disclosure path demonstrated; in-bounds complement of the known PS-index OOB (DF-1536/DF-1544), not a duplicate. Not verified at runtime: hardware-gated (no AMD GPU) and observation requires a crafted VBIOS - skipped per contract for Info findings.
No comments yet.