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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4049 Β· 5 files
FileTypeDescriptionSize
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.

VERDICT.md
↓ download raw

DF-4049 VERDICT β€” uninitialized PS padding in dac output control

Status: untested (source-certain defect; Info severity)

  • Defect certain from source: command_table.c:1669 and :1686 declare DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; without initialization; only ucAction (offset 0) is assigned (:1671-1674, :1688-1691) and the struct is 4 bytes with 3 bytes of aucPadding (atombios.h:1657-1667). The pointer is handed to amdgpu_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_testable
baseline no→ patch + rebuild →patched clean

Hardware-gated; one-line zero-init, compile-shape only.

findings/poc/DF-4049/fix.diff
↓ fix.diffper-fix-DF-4049

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.