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

Unbounded MST stream_count overflows stack work_table[MAX_CONTROLLER_NUM=6] in update_mst_stream_alloc_table

Summary

update_mst_stream_alloc_table at dc_link.c:2322: stack struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM=6]. Loop :2339 for(i=0;i<proposed_table->stream_count;i++) writes work_table[i] at :2348/:2355-2359 with NO bounds check vs 6. ASSERT at :2335 compiles to WARN_ON (production). proposed_table from get_payload_table (amdgpu_dm_helpers.c:137-172) iterates mst_mgr->max_payloads(=63) writing stream_count. Malicious MST hub/dock reports >6 active payloads -> stack overflow (96-byte buffer, 16B per entry). Each entry: stream_enc kernel pointer + vcp_id/slot_count. Sibling of DF-1264/DF-1319. UNAUTHENTICATED: malicious DP peripheral hotplug. Fix: clamp stream_count to MAX_CONTROLLER_NUM.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1320 Β· 9 files
FileTypeDescriptionSize
VERDICT.md verdict full source trace: unbounded stream_count overflows work_table[MAX_CONTROLLER_NUM=6] 4.1 KB ↓ raw
fix.diff suggested-fix clamp stream_count to MAX_CONTROLLER_NUM at update_mst_stream_alloc_table 966 B view raw
build.sh build-script documents hardware repro + validates fix.diff applies cleanly 748 B view raw
run.sh run-script documents hardware repro path 842 B view raw
build.log build-log guest evidence: amdgpu absent, no /dev/dri, only QEMU std-VGA 254 B view raw
env.txt environment guest uname, cc, driver-availability facts 1.5 KB view raw
README.md readme summary + repro + file index 1.0 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme summary + repro + file index
↓ download raw

DF-1320 β€” Unbounded MST stream_count β†’ stack overflow (amdgpu)

Status: INCONCLUSIVE (real bug; needs AMD GPU + amdgpu + MST hardware, all absent) Impact: stack buffer overflow via malicious MST hub (unauthenticated physical-layer) Driver: amdgpu MST allocation β€” NOT in X86_64_GENERIC, not loaded

Reproduce (hardware-equipped host only)

Requires an amdgpu host with a malicious MST hub/dock advertising >6 active payloads (LOCAL/REMOTE, non-zero slots). Hotplug β†’ payload negotiation β†’ work_table[6] stack overflow in update_mst_stream_alloc_table.

On the audit guest: amdgpu absent, no AMD GPU, no MST hardware. See VERDICT.md for the source trace and fix.diff for the validated patch.

Files

  • VERDICT.md β€” full mechanism trace with path:line citations
  • fix.diff β€” clamp stream_count to MAX_CONTROLLER_NUM (6) at table update
  • build.sh/run.sh β€” document hardware repro + validate fix.diff applies
  • build.log β€” guest evidence: amdgpu absent
  • env.txt, manifest.json
VERDICT.md verdict full source trace: unbounded stream_count overflows work_table[MAX_CONTROLLER_NUM=6]
↓ download raw

DF-1320 β€” Unbounded MST stream_count β†’ stack overflow (amdgpu)

Verdict

INCONCLUSIVE (real bug, needs hardware + driver absent from guest). Source trace confirms the stack overflow; it cannot be reproduced on this QEMU audit guest because amdgpu is not in X86_64_GENERIC, is not a loadable module, and there is no AMD GPU / MST hardware. The fix was validated to apply cleanly (git apply --check) against sys/dev/drm/amd/display/dc/core/dc_link.c.

Mechanism

update_mst_stream_alloc_table copies a DRM-proposed payload table into a fixed-size stack workspace:

sys/dev/drm/amd/display/dc/core/dc_link.c:2327  struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };
                                                                          // MAX_CONTROLLER_NUM = 6
sys/dev/drm/amd/display/dc/core/dc_link.c:2335  ASSERT(proposed_table->stream_count - ... < 2);  // compiles to no-op in production
sys/dev/drm/amd/display/dc/core/dc_link.c:2339  for (i = 0; i < proposed_table->stream_count; i++) {   // NO bounds check vs 6
sys/dev/drm/amd/display/dc/core/dc_link.c:2348      work_table[i] = *dc_alloc;       // *** OOB stack write for stream_count>6 ***
sys/dev/drm/amd/display/dc/core/dc_link.c:2355      work_table[i].vcp_id = ...;      // *** and here ***
sys/dev/drm/amd/display/dc/core/dc_link.c:2359      work_table[i].stream_enc = stream_enc;  // *** kernel pointer written ***

MAX_CONTROLLER_NUM = 6 (sys/dev/drm/amd/display/include/link_service_types.h:38). Each link_mst_stream_allocation is ~16 bytes (vcp_id + slot_count + stream_enc pointer), so the 6-entry work_table is ~96 bytes on the stack. proposed_table->stream_count is built upstream by get_payload_table:

sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c:150  for (i = 0; i < mst_mgr->max_payloads; i++) {   // max_payloads up to 63
sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c:157      if (... LOCAL || REMOTE) {
sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c:167          proposed_table->stream_count++;          // can reach up to 63

A malicious MST branch device (hub/dock) that advertises >6 payloads in LOCAL/REMOTE state with non-zero num_slots drives stream_count above 6, and the stack work_table overflows. The overflow content includes the kernel stream_enc pointer plus attacker-influenced vcp_id/slot_count. The ASSERT at 2335 is a no-op in production.

This is an unauthenticated physical-layer attack: hotplug a malicious MST hub β†’ payload negotiation β†’ dm_helpers_dp_mst_update_payload_allocator β†’ update_mst_stream_alloc_table.

Reachability on this guest

Identical to DF-1319: amdgpu is absent from the kernel, no module loaded, no AMD GPU, no MST hardware, no /dev/dri. Phase-4(d): real bug, unreachable on this guest.

Exploit chain

Stack buffer overflow (write-capable) on a display-driver code path driven by physical MST-layer attacker input β€” not a userspace-reachable path on the audit guest. Realistic impact ceiling on an amdgpu host: stack corruption in update_mst_stream_alloc_table β†’ potential kernel RCE via a malicious MST peripheral. No userspace escalation chain applies.

PoC changes

No runnable userspace PoC (MST-peripheral attack). Folder was empty. Authored build.sh/run.sh documenting the hardware-required reproduction and validating fix.diff applies cleanly.

Fix

fix.diff clamps proposed_table->stream_count to MAX_CONTROLLER_NUM at the top of update_mst_stream_alloc_table (after the existing ASSERT), invoking BREAK_TO_DEBUGGER() (already used in the file at :351) on the over-count before truncating. Surplus payloads a malicious hub claims are dropped, and the fixed-size work_table can no longer be overrun. Applies cleanly (git apply --check).

Fix validation

fix_status: not_testable β€” amdgpu not in the kernel build on this guest, so neither bug nor fix is runtime/compile-exercisable here. Validated by clean git apply --check and source inspection (the clamp uses the existing MAX_CONTROLLER_NUM constant and BREAK_TO_DEBUGGER macro).

Fix verification

not_testable

compile validated

nativekernel rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. amdgpu MST stream_count unbounded vs work_table[6] -> stack overflow. amdgpu not in GENERIC.