โฌข DragonFlyBSD Kernel Audit
โ† dashboard
DF-0018

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 DIOCRECLUSTER on 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).

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

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/kern_dmsg.c.
  • pending Reported to DragonFlyBSD security contact.