From: Chengfeng Ye <nicoyip.dev@gmail.com>
To: Jon Maloy <jmaloy@redhat.com>,
Tung Quang Nguyen <tung.quang.nguyen@est.tech>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Ying Xue <ying.xue@windriver.com>,
GhantaKrishnamurthy MohanKrishna
<mohan.krishna.ghanta.krishnamurthy@ericsson.com>
Cc: netdev@vger.kernel.org, tipc-discussion@lists.sourceforge.net,
linux-kernel@vger.kernel.org,
Chengfeng Ye <nicoyip.dev@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH net] tipc: hold a reference to nodes found by link name
Date: Sun, 27 Sep 2026 14:40:36 +0800 [thread overview]
Message-ID: <20260927064036.3691962-1-nicoyip.dev@gmail.com> (raw)
tipc_node_find_by_name() returns a node after dropping its RCU read lock
without taking a reference. The LINK_SET, LINK_GET and LINK_RESET_STATS
handlers then lock and access the node, racing with timer-driven cleanup
of a down peer. Generic netlink serialization does not exclude the node
timer.
The following interleaving can leave a handler using a freed node:
CPU 0: find the node under RCU and release the node read lock
CPU 1: tipc_node_timeout() clears the links and unlinks the down node
CPU 1: drop the list and timer references, queuing tipc_node_free()
CPU 0: leave the RCU read-side critical section
CPU 1: complete the grace period and free the node
CPU 0: acquire the node lock through the stale pointer
LINK_SET also uses the node's media address after releasing the node
lock, when passing queued packets to tipc_bearer_xmit().
KASAN reported:
BUG: KASAN: slab-use-after-free in _raw_read_lock_bh+0x1d/0x40
Write of size 4 at addr ffff888112723808 by task poc/87
Call Trace:
_raw_read_lock_bh+0x1d/0x40
tipc_nl_node_set_link+0x30e/0x680
genl_family_rcv_msg_doit+0x1e0/0x2c0
genl_rcv_msg+0x419/0x6d0
netlink_rcv_skb+0x11f/0x350
Allocated by task 28:
tipc_node_create+0x9c1/0x1fa0
tipc_node_check_dest+0x121/0x11e0
tipc_disc_rcv+0xdbf/0x1430
Freed by task 87:
kfree+0x149/0x330
rcu_core+0x50a/0x1850
Last potentially related work creation:
__call_rcu_common.constprop.0+0x71/0xa10
tipc_node_timeout+0xb1b/0xe70
Acquire a reference to the selected node with kref_get_unless_zero()
before leaving RCU, returning NULL if the node has already been released.
Release that reference on every caller exit after the last node access,
including transmission in LINK_SET. Keep the existing link lookup order
and locking so concurrent link removal still takes the existing error
paths.
Fixes: 6a939f365bdb ("tipc: Auto removal of peer down node instance")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
net/tipc/node.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/tipc/node.c b/net/tipc/node.c
index bd91378b7540..2726bee3bb40 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -2424,6 +2424,8 @@ static struct tipc_node *tipc_node_find_by_name(struct net *net,
if (found_node)
break;
}
+ if (found_node && !kref_get_unless_zero(&found_node->kref))
+ found_node = NULL;
rcu_read_unlock();
return found_node;
@@ -2507,6 +2509,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
tipc_node_read_unlock(node);
tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr,
NULL);
+ tipc_node_put(node);
return res;
}
@@ -2558,12 +2561,14 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
link = node->links[bearer_id].link;
if (!link) {
tipc_node_read_unlock(node);
+ tipc_node_put(node);
err = -EINVAL;
goto err_free;
}
err = __tipc_nl_add_link(net, &msg, link, 0);
tipc_node_read_unlock(node);
+ tipc_node_put(node);
if (err)
goto err_free;
}
@@ -2634,11 +2639,13 @@ int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
if (!link) {
spin_unlock_bh(&le->lock);
tipc_node_read_unlock(node);
+ tipc_node_put(node);
return -EINVAL;
}
tipc_link_reset_stats(link);
spin_unlock_bh(&le->lock);
tipc_node_read_unlock(node);
+ tipc_node_put(node);
return 0;
}
--
2.43.0
next reply other threads:[~2026-09-27 6:40 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 6:40 Chengfeng Ye [this message]
2026-09-28 12:17 ` Tung Quang Nguyen
2026-09-28 16:19 ` Chengfeng Ye
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260927064036.3691962-1-nicoyip.dev@gmail.com \
--to=nicoyip.dev@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jmaloy@redhat.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mohan.krishna.ghanta.krishnamurthy@ericsson.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
--cc=tipc-discussion@lists.sourceforge.net \
--cc=tung.quang.nguyen@est.tech \
--cc=ying.xue@windriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®