Duplicate DELETE for same DMSG msgid triggers KKASSERT panic (DoS)
| Field | Value |
|---|---|
| ID | DF-0018 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-617 Reachable Assertion |
| File | sys/kern/kern_dmsg.c |
| Lines | 1076 |
| Area | kern |
| Confidence | likely |
| Discovered | 2026-06-29 |
| Reported | pending |
Summary
kdmsg_state_msgrx() unconditionally asserts
KKASSERT((state->rxcmd & DMSGF_DELETE) == 0) at kern_dmsg.c:1076 when
processing a received DELETE. A peer can send two DELETE messages for the same
transaction msgid back-to-back. The first DELETE sets
state->rxcmd |= DMSGF_DELETE but does not remove the state from the RB tree
(removal requires txcmd to also carry DELETE, which depends on the writer
thread transmitting the reply). The second DELETE finds the same state still
in the tree and reaches :1076, where the assertion fires. Note: in
DragonFlyBSD both KASSERT and KKASSERT are #ifdef INVARIANTS
(sys/sys/systm.h:94-118) โ the assertion is INVARIANTS-only, so the
panic occurs on debug/INVARIANTS kernels; on a production
(non-INVARIANTS) kernel the KKASSERT compiles to a no-op and the second
DELETE is absorbed benignly (rxcmd |= DMSGF_DELETE is idempotent and the
txcmd & DMSGF_DELETE RB_REMOVE branch is not taken because the writer has
not yet transmitted the reply). This is the same INVARIANTS-only class as
DF-0001; recorded as an INVARIANTS-kernel remote DoS (Low).
Root cause
sys/kern/kern_dmsg.c:1075-1093:
} else if (msg->any.head.cmd & DMSGF_DELETE) {
KKASSERT((state->rxcmd & DMSGF_DELETE) == 0); /* :1076 */
state->rxcmd |= DMSGF_DELETE;
if (state->txcmd & DMSGF_DELETE) {
...
RB_REMOVE(kdmsg_state_tree, &iocom->staterd_tree, state); /* :1088 */
...
}
}
The state is found by RB_FIND and remains in the tree after the first DELETE
because RB_REMOVE only runs when both rxcmd and txcmd carry DELETE
(:1078). The DELETE switch-case guard (:943) checks for msgid reuse
((state->rxcmd & DMSGF_CREATE) == 0), not for a pre-existing DELETE flag.
The window between the reader finishing the first DELETE and the writer
transmitting the reply is the race window; two back-to-back DELETEs win it
reliably.
Threat model & preconditions
- Attacker position: a DMSG peer (same reachability as DF-0017: the userland
hammer2 relay daemon over the cluster network, or locally via
DIOCRECLUSTERon a disk device node). CRC not verified on receive. - Privileges gained or impact: kernel panic (full-system DoS). No integrity/ confidentiality impact.
- Required config or capabilities: a reachable DMSG link (HAMMER2 clustering in use for the network vector).
- Reachability: CREATE a msgid, then two rapid DELETEs for it.
Proof of concept
PoC source: findings/poc/DF-0018/kdmsg_dupdelete.c
Sends a CREATE for msgid 42, then two back-to-back DELETEs for msgid 42.
Build & run
cc -o kdmsg_dupdelete findings/poc/DF-0018/kdmsg_dupdelete.c ./kdmsg_dupdelete <connected-dmsg-fd> # see DF-0017 for obtaining the fd
Expected output
panic: (state->rxcmd & DMSGF_DELETE) == 0
Impact
Reliable (race-favored, easily won by sending both DELETEs back-to-back)
INVARIANTS-kernel panic from any DMSG peer; on a production
(non-INVARIANTS) kernel the second DELETE is absorbed benignly (the
KKASSERT is a no-op and txcmd lacks DELETE so no double-RB_REMOVE).
Low (INVARIANTS-only DoS, same class as DF-0001).
Recommended fix
Discard a duplicate DELETE benignly rather than asserting, mirroring the
existing EALREADY handling for the ABORT+DELETE races (:926-930,
:944-947):
--- a/sys/kern/kern_dmsg.c
+++ b/sys/kern/kern_dmsg.c
@@ -942,6 +942,13 @@
break;
}
}
+
+ /*
+ * A duplicate DELETE can race our reply transmission.
+ * Discard it silently rather than tripping the KKASSERT below.
+ */
+ if (state->rxcmd & DMSGF_DELETE) {
+ error = EALREADY;
+ break;
+ }
error = 0;
break;
References
sys/kern/kern_dmsg.c:1076โKKASSERT((state->rxcmd & DMSGF_DELETE) == 0).sys/kern/kern_dmsg.c:1078-1093โRB_REMOVErequirestxcmdDELETE.- CWE-617 Reachable Assertion.
Timeline
- 2026-06-29 Discovered during automated file-by-file audit of
sys/kern/kern_dmsg.c. - pending Reported to DragonFlyBSD security contact.