mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
tipc: fix NULL deref in tipc_named_node_up() on empty publication list
User-space applications can bind a large number of service addresses to
one or more sockets. Each binding of a local-scope service address inserts
one entry (publication) into the TIPC name table. If the number of these
publications exceeds TIPC_MAX_PUBL (65535), protocol service types
(such as node state and link state) are no longer inserted into the name
table. This causes two issues:
1. User-space applications subscribing to node or link up/down events
stop receiving notifications.
2. A NULL pointer dereference can occur:
BUG: kernel NULL pointer dereference, address: 00000000000000d0
...
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.2.0-rc4-default+ #5 PREEMPT(full)
...
RIP: 0010:tipc_named_node_up (./include/linux/skbuff.h:2251 net/tipc/name_distr.c:195 net/tipc/name_distr.c:221)
...
Call Trace:
<IRQ>
tipc_node_write_unlock (net/tipc/node.c:428)
tipc_rcv (net/tipc/node.c:934 net/tipc/node.c:2189)
tipc_udp_recv (net/tipc/udp_media.c:389)
Thread 1 (tipc_net_finalize) | Thread 2 (named_distribute)
-----------------------------|-----------------------------
| ...
| list_for_each_entry(publ, pls, binding_node) {
| ...
| __skb_queue_tail(list, skb);
| ...
| }
| ...
| hdr = buf_msg(skb_peek_tail(list));
... |
tipc_nametbl_publish(); |
If 'tipc_nametbl_publish()' (Thread 1) fails because the number of
local publications reaches TIPC_MAX_PUBL, list (Thread 2) will be empty. As a
result, NULL is passed to 'buf_msg()', leading to a NULL pointer dereference.
Fix these issues by allowing protocol service types (node state, link state,
and topology server) to be inserted into the name table unconditionally.
This ensures that users subscribing to these types always receive
notifications. In addition, the maximum number of local user publications is
reduced to (TIPC_MAX_PUBL - 1). This ensures that the maximum bulk size
calculated in tipc_link_set_queue_limits() remains valid.
Fixes: a5e7ac5ce1 ("tipc: fix regression bug where node events are not being generated")
Reported-by: Xiang Mei <xmei5@asu.edu>
Tested-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/20260827111418.164957-1-tung.quang.nguyen@est.tech
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
f88bbbbe96
commit
b3b76e9f4f
|
|
@ -763,21 +763,40 @@ struct publication *tipc_nametbl_publish(struct net *net, struct tipc_uaddr *ua,
|
|||
struct tipc_socket_addr *sk, u32 key)
|
||||
{
|
||||
struct name_table *nt = tipc_name_table(net);
|
||||
u32 max_user_pub = TIPC_MAX_PUBL - 1;
|
||||
struct tipc_net *tn = tipc_net(net);
|
||||
struct publication *p = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
bool protocol_type = false;
|
||||
u32 rc_dests;
|
||||
|
||||
spin_lock_bh(&tn->nametbl_lock);
|
||||
if (ua->sr.type == TIPC_NODE_STATE || ua->sr.type == TIPC_LINK_STATE ||
|
||||
ua->sr.type == TIPC_TOP_SRV)
|
||||
protocol_type = true;
|
||||
|
||||
if (nt->local_publ_count >= TIPC_MAX_PUBL) {
|
||||
pr_warn("Bind failed, max limit %u reached\n", TIPC_MAX_PUBL);
|
||||
spin_lock_bh(&tn->nametbl_lock);
|
||||
if (protocol_type)
|
||||
goto insert;
|
||||
|
||||
/* Reserve one entry for node state service type because it has cluster
|
||||
* scope and it is distributed in bulk. So, the maximum number of user's
|
||||
* publications is (TIPC_MAX_PUBL - 1).
|
||||
*/
|
||||
if (nt->local_publ_count >= max_user_pub) {
|
||||
pr_warn("Bind failed, max limit %u reached\n", max_user_pub);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
insert:
|
||||
p = tipc_nametbl_insert_publ(net, ua, sk, key);
|
||||
if (p) {
|
||||
nt->local_publ_count++;
|
||||
/* Not count node state, link state and topology server types
|
||||
* so that maximum nt->local_publ_count does not prevent
|
||||
* protocol service types from being inserted into the name
|
||||
* table.
|
||||
*/
|
||||
if (!protocol_type)
|
||||
nt->local_publ_count++;
|
||||
skb = tipc_named_publish(net, p);
|
||||
}
|
||||
rc_dests = nt->rc_dests;
|
||||
|
|
@ -810,7 +829,10 @@ void tipc_nametbl_withdraw(struct net *net, struct tipc_uaddr *ua,
|
|||
|
||||
p = tipc_nametbl_remove_publ(net, ua, sk, key);
|
||||
if (p) {
|
||||
nt->local_publ_count--;
|
||||
if (p->sr.type != TIPC_NODE_STATE &&
|
||||
p->sr.type != TIPC_LINK_STATE &&
|
||||
p->sr.type != TIPC_TOP_SRV)
|
||||
nt->local_publ_count--;
|
||||
skb = tipc_named_withdraw(net, p);
|
||||
list_del_init(&p->binding_sock);
|
||||
kfree_rcu(p, rcu);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user