Duplicate transaction DELETE double-dispatches xdisk state callbacks: kernel panic (KKASSERT on stock kernels; NULL deref at xaio_rcvdmsg:538 / xa_sync_completion:1127 otherwise)
Summary
txcmd's DELETE bit is only set by the writer thread; a dmsg peer that pipelines a second LNK_SPAN|DELETE while our terminating reply to the first is still queued passes every 'state reused' guard (they test only CREATE) and reaches the callback a second time. Stock kernels panic at the KKASSERT; non-KKASSERT builds dispatch into xdisk again with msg->state->any.xa_sc == NULL - lockmgr on NULL, or kdmsg_state_reply(NULL) on the BLK_OPEN variant. REPRODUCED LIVE twice from fresh resets with a purpose-built untrusted-peer harness (deterministic via a 100x PING reply backlog). Remote DoS by the cluster peer after root attaches. Core+guards fix validated on a rebuilt kernel (300-attempt PoC survived, duplicates dropped).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4381 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| xdpeer.c | β | 15.0 KB | view raw | |
| panic.txt | β | 1.7 KB | view raw | |
| run.patched.log | β | 6.5 KB | view raw | |
| fix_run.log | β | 6.5 KB | view raw | |
| fix.diff | β | 2.3 KB | view raw | |
| fix_build.log | β | 25.2 KB | view raw | |
| fix_install.log | β | 80.4 KB | view raw | |
| env.txt | β | 145 B | view raw |
Fix verification
fixedSingle-fix kernel (nativekernel rebuild) + fixed module: the exact PoC that panicked the stock kernel completed 300 attempts with no crash; dmesg shows the new duplicate-DELETE-dropped path firing 253 times and the pre-existing no-state-for-DELETE drop 47 times.
run.patched.log / fix_run.log; fix_build.log; fix_install.log; uname #1 Sat Sep 19 21:08:17 UTC 2026
Confirmed kernel references
Detail
Exploit chain
untrusted dmsg peer -> LNK_SPAN|CREATE -> [100x LNK_PING|CREATE + 2x LNK_SPAN|DELETE in one write] -> duplicate DELETE double-dispatch -> kernel panic (remote DoS). No memory-corruption primitive; uid0 N/A.
Evidence (decisive lines)
panic.txt (stock-kernel serial panic + backtrace); run.patched.log / fix_run.log (300 attempts survived post-fix, 253 duplicate-DELETE-dropped); fix.diff (git-apply-able)
PoC changes
authored from scratch (pass 2, no seed). Bring-up fixes: replies must invert REVTRANS|REVCIRC routing bits; backlog must use PING|CREATE transactions (one-off pings get no reply); peer must keep draining to avoid INTERLOCK deadlock instead of double-dispatch.
Verified recommended fix
kern_dmsg.c: drop duplicate DELETE with EALREADY when rxcmd already has DELETE; xdisk: NULL-guard xa_sc in span-delete and tag->state in xa_sync_completion
Verdict
Duplicate transaction DELETEs from a dmsg peer double-dispatch xdisk state callbacks: stock kernels panic at the kern_dmsg.c:1076 KKASSERT (reproduced twice from fresh resets, serial capture in panic.txt); kernels built without KKASSERT NULL-deref in xaio_rcvdmsg (xdisk.c:538, xa_sc==NULL) or xa_sync_completion (xdisk.c:1127, tag->state==NULL). Root cause: txcmd DELETE is set only by the writer thread (kern_dmsg.c:1672), so a pipelined duplicate DELETE passes all state-reused guards. Deterministic via a PING|CREATE backlog keeping the writer >100 messages behind.
No comments yet.