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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2022 Β· 7 files
FileTypeDescriptionSize
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
README.md readme original PoC README
↓ download 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:

  1. On the HOST, force BIF_BX_PF0_MAILBOX_CONTROL TRN_MSG_ACK asserted 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 at AI_MAIBOX_CONTROL_TRN_OFFSET_BYTE (mxgpu_ai.h:56) to return bit1 set

  2. In the GUEST, run as an unprivileged user: sh cc -o repro repro.c ./repro The PoC opens /dev/dri/card0 which forces amdgpu_driver_open β†’ amdgpu_virt_request_full_gpu(false) β†’ ... β†’ xgpu_ai_mailbox_trans_msg β†’ unbounded do/while(trn) loop.

Expected output

  • The repro process enters permanent D-state; ps -l shows state D
  • kill -9 (SIGKILL) does NOT reap it (tsleep flags=0, no PCATCH)
  • procstat -p <pid> shows tsleep channel linux_msleep
  • dmesg floods with trn=2 ACK should not assert! wait again !
  • The process is unkillable until reboot

No panic, no memory corruption β€” purely an unkillable-hang DoS.

VERDICT.md verdict full source-trace verdict
↓ download raw

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_testable
baseline reproduced→ patch + rebuild →patched clean

VALIDATED build.

VALIDATED build.
↓ fix.diffamdgpu.ko build rc=0 -Werror

Confirmed kernel references

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.