RE: [PATCH net] tipc: cap number of nodes per net namespace
From: Tung Quang Nguyen
Date: Mon Jul 13 2026 - 09:35:24 EST
>Subject: [PATCH net] tipc: cap number of nodes per net namespace
>
>tipc_node_create() allocates a new struct tipc_node (plus a broadcast receive
>link, a unicast link slot and a keepalive timer) for every previously unseen
>(addr, node_id) pair carried in an inbound TIPC LINK_CONFIG discovery frame:
>
> n = tipc_node_find(net, addr) ?:
> tipc_node_find_by_id(net, peer_id);
> if (n) {
> ...
> }
> n = kzalloc_obj(*n, GFP_ATOMIC);
> ...
> n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
>
>Both addr (msg_prevnode) and peer_id (msg_node_id) come straight out of
>the discovery frame and are fully attacker controlled, and the dedup key above
>is keyed on exactly those two values. There is no cap on how many distinct
>nodes a net namespace may hold and no rate limit on the create path, so an
>unauthenticated peer on an enabled TIPC bearer (L2 or UDP) can flood
>LINK_CONFIG frames with a fresh (addr,
>node_id) in each one and force the kernel to keep minting new, distinct struct
>tipc_node objects without bound. A link-less spoofed node is only reclaimed
>after NODE_CLEANUP_AFTER (300 s), so at typical discovery rates the live node
>table, and the memory pinned by it, grows roughly linearly with attacker-
>supplied identities for the duration of the flood. This is (uncontrolled resource
>consumption), reachable by any unauthenticated network-adjacent host once
>tipc.ko is loaded and a bearer is enabled.
>
>Bound this the same way net/core/neighbour.c bounds the ARP/ND neighbour
>table against unauthenticated on-link input: reject new entries once a hard
>ceiling is hit instead of letting the table grow without limit. struct tipc_net
>already carries a num_nodes counter that is declared but never read or
>written anywhere in net/tipc/; wire it up on the create and delete paths and
>add a single bounds check on it in tipc_node_create(), guarded by the same tn-
>>node_list_lock spinlock that already serializes every call site of
>tipc_node_create(), tipc_node_delete_from_list(), tipc_node_delete() and
>tipc_node_stop(). No new locking, no new data structures, and no change to
>the node table's data layout or lookup semantics; legitimate peers are still
>admitted exactly as before, up to the cap.
>
>TIPC_MAX_NODES is set to 8192, well above any realistic TIPC cluster size,
>bounding worst-case pinned memory to a fixed multiple of one node's
>footprint instead of unbounded growth. It is intentionally not tuned tight;
>exposing it as a sysctl (mirroring
>net.ipv4.neigh.default.gc_thresh3) would be a reasonable follow-up but is left
>out to keep this fix minimal.
I do not see any issue with current code that requires this patch.
>
>Verified on a v6.19 KASAN build: flooding spoofed (addr, node_id) peers past
>the cap makes the patched kernel log "Too many TIPC nodes (8192)" and drop
>further peers, where the same flood grew the live node table without bound
>before this patch.
Can you provide your C reproducer and the stack trace you observed (on latest net-tree) ?
>
>Cc: stable@xxxxxxxxxxxxxxx
>Signed-off-by: Ibrahim Hashimov <security@xxxxxxxxxxxx>
>Assisted-by: AuditCode-AI:2026.07
>---
> net/tipc/node.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
>diff --git a/net/tipc/node.c b/net/tipc/node.c index
>8e4ef2630ae4..bb41f3231ce1 100644
>--- a/net/tipc/node.c
>+++ b/net/tipc/node.c
>@@ -49,6 +49,16 @@
> #define INVALID_NODE_SIG 0x10000
> #define NODE_CLEANUP_AFTER 300000
>
>+/* Hard cap on the number of live struct tipc_node entries a single net
>+ * namespace will hold. Every entry (preliminary or not) also pins a
>+ * broadcast-receive link, a unicast link slot and a keepalive timer,
>+so
>+ * this bounds worst-case memory from unauthenticated LINK_CONFIG
>+discovery
>+ * traffic the same way neigh_alloc()'s gc_thresh3 bounds the ARP/ND
>+table
>+ * (see net/core/neighbour.c). 8192 is far above any realistic TIPC
>+cluster
>+ * size and is not meant to be tight -- it only stops unbounded growth.
>+ */
>+#define TIPC_MAX_NODES 8192
>+
> /* Flags used to take different actions according to flag type
> * TIPC_NOTIFY_NODE_DOWN: notify node is down
> * TIPC_NOTIFY_NODE_UP: notify node is up @@ -535,6 +545,11 @@ struct
>tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
>
> goto exit;
> }
>+ if (tn->num_nodes >= TIPC_MAX_NODES) {
>+ pr_warn_ratelimited("Too many TIPC nodes (%u), dropping
>new peer %x\n",
>+ tn->num_nodes, addr);
>+ goto exit;
>+ }
> n = kzalloc_obj(*n, GFP_ATOMIC);
> if (!n) {
> pr_warn("Node creation failed, no memory\n"); @@ -598,6
>+613,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8
>*peer_id,
> break;
> }
> list_add_tail_rcu(&n->list, &temp_node->list);
>+ tn->num_nodes++;
> /* Calculate cluster capabilities */
> tn->capabilities = TIPC_NODE_CAPABILITIES;
> list_for_each_entry_rcu(temp_node, &tn->node_list, list) { @@ -630,6
>+646,7 @@ static void tipc_node_delete_from_list(struct tipc_node *node)
>#endif
> list_del_rcu(&node->list);
> hlist_del_rcu(&node->hash);
>+ tipc_net(node->net)->num_nodes--;
> tipc_node_put(node);
> }
>
>--
>2.50.1 (Apple Git-155)
>