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)
PoC verification
Evidence pack
findings/poc/DF-1320 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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 citationsfix.diffβ clamp stream_count to MAX_CONTROLLER_NUM (6) at table updatebuild.sh/run.shβ document hardware repro + validate fix.diff appliesbuild.logβ guest evidence: amdgpu absentenv.txt,manifest.json
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_testablecompile 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.
No comments yet.