Unbounded non-interruptible ACK-poll loop in xgpu_ai_mailbox_trans_msg wedges unkillable kernel thread
Summary
mxgpu_ai.c:128-135 inner do { set_valid(false); trn=peek_ack(); if(trn) { pr_err; msleep(1); } } while(trn) has NO timeout and NO signal-pending check unlike every sibling poll in file (poll_ack at 79-96 bounded AI_MAILBOX_POLL_ACK_TIMEDOUT, poll_msg at 98-114 bounded, flr_work at 235-271 bounded). xgpu_ai_peek_ack (75-77) returns RREG8(AI_MAIBOX_CONTROL_TRN_OFFSET_BYTE)&2 = host-driven TRN_MSG_ACK bit; loop exits only when trn==0 which is entirely under host/PF control. msleep() at include/linux/delay.h:33-39 maps to tsleep(&dummy,0,"linux_msleep",delay) flags=0 NO PCATCH so SIGKILL cannot recover. Reachable from guest process context: amdgpu_driver_open (amdgpu_kms.c:88) -> amdgpu_virt_request_full_gpu(false) -> xgpu_ai_request_full_gpu_access -> xgpu_ai_send_access_requests -> xgpu_ai_mailbox_trans_msg -> unbounded loop. Trigger: malicious host/PF (cloud passthrough threat model) leaves TRN_MSG_ACK asserted, or benign AMDGPU PF firmware regression / VFIO emulation bug forgets to deassert ACK -> unkillable D-state process/kernel thread. guest-internal attacker cannot self-trigger (doesnt control ACK bit). Impact: permanent unkillable kernel thread D-state; possible deadlock of lock_reset-dependent paths. AV:L/AC:H/PR:H, A:L.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2022 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | readme | original PoC README | 1.1 KB | β raw |
| VERDICT.md | verdict | full source-trace verdict | 1.5 KB | β raw |
| build.sh | build-script | build/verify instructions | 438 B | view raw |
| env.txt | environment | guest environment (no matching HW) | 814 B | view raw |
| fix.diff | suggested-fix | git-apply-able fix, verified to compile -Werror | 667 B | view raw |
| fix_build.log | build-log | Phase 8 module build evidence (-Werror rc=0) | 1.5 KB | view raw |
| run.sh | run-script | run instructions (HW-gated) | 323 B | view raw |
DF-2022 PoC β Unbounded ACK-poll loop in mxgpu_ai
Trigger (host-assisted)
The guest cannot set the TRN_MSG_ACK bit it polls. The trigger is host-driven:
-
On the HOST, force
BIF_BX_PF0_MAILBOX_CONTROLTRN_MSG_ACKasserted without ever clearing it. Methods: - Patch the PF amdgpu driver's mailbox ACK path to skip the deassert - Use a VFIO/mdev test shim that forces the register read atAI_MAIBOX_CONTROL_TRN_OFFSET_BYTE(mxgpu_ai.h:56) to return bit1 set -
In the GUEST, run as an unprivileged user:
sh cc -o repro repro.c ./reproThe PoC opens/dev/dri/card0which forcesamdgpu_driver_openβamdgpu_virt_request_full_gpu(false)β ... βxgpu_ai_mailbox_trans_msgβ unboundeddo/while(trn)loop.
Expected output
- The repro process enters permanent D-state;
ps -lshows stateD kill -9(SIGKILL) does NOT reap it (tsleep flags=0, no PCATCH)procstat -p <pid>shows tsleep channellinux_msleepdmesgfloods withtrn=2 ACK should not assert! wait again !- The process is unkillable until reboot
No panic, no memory corruption β purely an unkillable-hang DoS.
VERDICT -- DF-2022 (Low)
Verdict: REPRODUCED (source-only)
Impact: dos (unkillable D-state hang); HW-gated (needs amdgpu VF/SR-IOV), source-confirmed
Confidence: likely
Mechanism (source-traced)
xgpu_ai_mailbox_trans_msg (mxgpu_ai.c:128-135) has a 'do { set_valid(false); trn=peek_ack(); if(trn){pr_err;msleep(1);} } while(trn)' loop with NO timeout and NO signal-pending check, unlike every sibling poll in the file (poll_ack at :79-96 bounded by AI_MAILBOX_POLL_ACK_TIMEDOUT, poll_msg at :98-114 bounded). peek_ack (mxgpu_ai.c:75-77) returns the host-driven TRN_MSG_ACK bit, so the loop only exits when the host deasserts it. msleep maps to tsleep flags=0 (no PCATCH) so SIGKILL cannot recover -- permanent unkillable D-state if host/PF leaves ACK asserted.
Why not runtime-reproduced
The guest (DragonFlyBSD 6.5-DEVELOPMENT #0 master DEV, KVM) has NO matching
hardware: pciconf shows no mfi/tws/iir RAID controller and no amdgpu/DRM GPU;
the driver therefore cannot attach and the vulnerable path is not runtime-
triggerable here. The defect was confirmed at the source level by tracing
the cited path:line against sys/, and the proposed fix was applied and the
affected module (amdgpu) built clean with -Werror (see fix_build.log).
Fix
mxgpu_ai.c:128-135: bound the loop with a counter (r = AI_MAILBOX_POLL_ACK_TIMEDOUT; ... while(trn && r-- > 0)) mirroring poll_ack/poll_msg, so a stuck ACK cannot wedge an unkillable thread forever.
The standalone, git-apply-able diff is fix.diff.
Fix verification
not_testableVALIDATED build.
VALIDATED build.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- a
- m
- d
- g
- p
- u
- /
- m
- x
- g
- p
- u
- _
- a
- i
- .
- c
- :
- 1
- 2
- 8
Detail
Exploit chain
none (HW-gated).
Evidence (decisive lines)
HW-GATED (no AMD GPU VF). Source-CONFIRMED. xgpu_ai_mailbox_trans_msg has unbounded do/while(trn) loop with no timeout/signal check. Host/PF leaves ACK -> permanent unkillable D-state.
Verified recommended fix
Bound loop with AI_MAILBOX_POLL_ACK_TIMEDOUT counter.
Verdict
HW-GATED (no AMD GPU VF). Source-CONFIRMED. xgpu_ai_mailbox_trans_msg has unbounded do/while(trn) loop with no timeout/signal check. Host/PF leaves ACK -> permanent unkillable D-state.
No comments yet.