⬢ DragonFlyBSD Kernel Audit
DF-2711 / fix.diff
← back to finding ↓ download raw
--- 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 <sys/dmsg.h> (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 */