--- sys/kern/kern_dmsg.c 2026-06-29 12:51:19.000000000 +0000 +++ /tmp/opencode/v26/fixtree/sys/kern/kern_dmsg.c 2026-10-24 16:53:55.813821054 +0000 @@ -92,8 +92,7 @@ #define kdmsg_state_hold(state) _kdmsg_state_hold(state) #define kdmsg_state_drop(state) _kdmsg_state_drop(state) #endif -static void _kdmsg_state_hold(kdmsg_state_t *state KDMSG_DEBUG_ARGS); -static void _kdmsg_state_drop(kdmsg_state_t *state KDMSG_DEBUG_ARGS); +/* DF-2709: prototypes now in (exported for hammer2) */ static void kdmsg_iocom_thread_rd(void *arg); static void kdmsg_iocom_thread_wr(void *arg); @@ -227,10 +226,15 @@ (msg->any.head.cmd & DMSGF_DELETE)) { /* * iocom->conn_state has a state ref, drop it when clearing. + * + * DF-2709: conn_state is shared with hammer2_volconf_update() + * and other readers; interlock the drop with msglk. */ + lockmgr(&iocom->msglk, LK_EXCLUSIVE); if (iocom->conn_state) kdmsg_state_drop(iocom->conn_state); iocom->conn_state = NULL; + lockmgr(&iocom->msglk, LK_RELEASE); kdmsg_msg_reply(msg, 0); } @@ -901,6 +905,16 @@ msg->state = state; /* inherits freerd ref */ state->parent = pstate; KKASSERT(state->iocom == iocom); + /* + * DF-2711: cap the number of transactions a peer may + * have open; without a quota a peer can pin unbounded + * kernel memory (~160 bytes per state). + */ + if (iocom->peer_states >= KDMSG_MAX_PEER_STATES) { + error = DMSG_ERR_LOSTLINK; + break; + } + ++iocom->peer_states; state->flags |= KDMSG_STATE_RBINSERTED | KDMSG_STATE_SUBINSERTED | KDMSG_STATE_OPPOSITE; @@ -1727,7 +1741,6 @@ kdmsg_state_drop(state); } -static void _kdmsg_state_hold(kdmsg_state_t *state KDMSG_DEBUG_ARGS) { @@ -1737,7 +1750,6 @@ #endif } -static void _kdmsg_state_drop(kdmsg_state_t *state KDMSG_DEBUG_ARGS) { @@ -1759,8 +1771,11 @@ KKASSERT((state->flags & KDMSG_STATE_SUBINSERTED) == 0); KKASSERT(TAILQ_EMPTY(&state->subq)); - if (state != &state->iocom->state0) + if (state != &state->iocom->state0) { + if (state->flags & KDMSG_STATE_OPPOSITE) /* DF-2711 */ + --state->iocom->peer_states; kfree(state, iocom->mmsg); + } } kdmsg_msg_t * --- sys/sys/dmsg.h 2026-06-29 12:51:19.000000000 +0000 +++ /tmp/opencode/v26/fixtree/sys/sys/dmsg.h 2026-10-24 16:46:16.995664535 +0000 @@ -803,6 +803,12 @@ * Structure embedded in e.g. mount, master control structure for * DMSG stream handling. */ +#define KDMSG_MAX_PEER_STATES 65536 /* DF-2711 */ + +/* DF-2709: exported for hammer2_volconf_update's conn_state interlock */ +void _kdmsg_state_hold(kdmsg_state_t *state); +void _kdmsg_state_drop(kdmsg_state_t *state); + struct kdmsg_iocom { struct malloc_type *mmsg; struct file *msg_fp; /* cluster pipe->userland */ @@ -819,6 +825,7 @@ void (*exit_func)(struct kdmsg_iocom *); struct kdmsg_state state0; /* root state for stacking */ struct kdmsg_state *conn_state; /* active LNK_CONN state */ + int peer_states; /* DF-2711: peer-created */ struct kdmsg_state *freerd_state; /* allocation cache */ struct kdmsg_state *freewr_state; /* allocation cache */ struct kdmsg_state_tree staterd_tree; /* active messages */