* [PATCH net] tipc: cap number of nodes per net namespace
@ 2026-07-10 15:03 Ibrahim Hashimov
0 siblings, 0 replies; only message in thread
From: Ibrahim Hashimov @ 2026-07-10 15:03 UTC (permalink / raw)
To: Jon Maloy, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Simon Horman, netdev, tipc-discussion, linux-kernel, stable
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.
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.
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
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)
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-10 15:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10 15:03 [PATCH net] tipc: cap number of nodes per net namespace Ibrahim Hashimov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox