Skip to content

Commit cb8092d

Browse files
lxindavem330
authored andcommitted
tipc: move bc link creation back to tipc_node_create
Shuang Li reported a NULL pointer dereference crash: [] BUG: kernel NULL pointer dereference, address: 0000000000000068 [] RIP: 0010:tipc_link_is_up+0x5/0x10 [tipc] [] Call Trace: [] <IRQ> [] tipc_bcast_rcv+0xa2/0x190 [tipc] [] tipc_node_bc_rcv+0x8b/0x200 [tipc] [] tipc_rcv+0x3af/0x5b0 [tipc] [] tipc_udp_recv+0xc7/0x1e0 [tipc] It was caused by the 'l' passed into tipc_bcast_rcv() is NULL. When it creates a node in tipc_node_check_dest(), after inserting the new node into hashtable in tipc_node_create(), it creates the bc link. However, there is a gap between this insert and bc link creation, a bc packet may come in and get the node from the hashtable then try to dereference its bc link, which is NULL. This patch is to fix it by moving the bc link creation before inserting into the hashtable. Note that for a preliminary node becoming "real", the bc link creation should also be called before it's rehashed, as we don't create it for preliminary nodes. Fixes: 4cbf8ac ("tipc: enable creating a "preliminary" node") Reported-by: Shuang Li <shuali@redhat.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Jon Maloy <jmaloy@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 853a761 commit cb8092d

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

net/tipc/node.c

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
472472
bool preliminary)
473473
{
474474
struct tipc_net *tn = net_generic(net, tipc_net_id);
475+
struct tipc_link *l, *snd_l = tipc_bc_sndlink(net);
475476
struct tipc_node *n, *temp_node;
476-
struct tipc_link *l;
477477
unsigned long intv;
478478
int bearer_id;
479479
int i;
@@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
488488
goto exit;
489489
/* A preliminary node becomes "real" now, refresh its data */
490490
tipc_node_write_lock(n);
491+
if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
492+
tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
493+
n->capabilities, &n->bc_entry.inputq1,
494+
&n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
495+
pr_warn("Broadcast rcv link refresh failed, no memory\n");
496+
tipc_node_write_unlock_fast(n);
497+
tipc_node_put(n);
498+
n = NULL;
499+
goto exit;
500+
}
491501
n->preliminary = false;
492502
n->addr = addr;
493503
hlist_del_rcu(&n->hash);
@@ -567,7 +577,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
567577
n->signature = INVALID_NODE_SIG;
568578
n->active_links[0] = INVALID_BEARER_ID;
569579
n->active_links[1] = INVALID_BEARER_ID;
570-
n->bc_entry.link = NULL;
580+
if (!preliminary &&
581+
!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
582+
tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
583+
n->capabilities, &n->bc_entry.inputq1,
584+
&n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
585+
pr_warn("Broadcast rcv link creation failed, no memory\n");
586+
kfree(n);
587+
n = NULL;
588+
goto exit;
589+
}
571590
tipc_node_get(n);
572591
timer_setup(&n->timer, tipc_node_timeout, 0);
573592
/* Start a slow timer anyway, crypto needs it */
@@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
11551174
bool *respond, bool *dupl_addr)
11561175
{
11571176
struct tipc_node *n;
1158-
struct tipc_link *l, *snd_l;
1177+
struct tipc_link *l;
11591178
struct tipc_link_entry *le;
11601179
bool addr_match = false;
11611180
bool sign_match = false;
@@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr,
11751194
return;
11761195

11771196
tipc_node_write_lock(n);
1178-
if (unlikely(!n->bc_entry.link)) {
1179-
snd_l = tipc_bc_sndlink(net);
1180-
if (!tipc_link_bc_create(net, tipc_own_addr(net),
1181-
addr, peer_id, U16_MAX,
1182-
tipc_link_min_win(snd_l),
1183-
tipc_link_max_win(snd_l),
1184-
n->capabilities,
1185-
&n->bc_entry.inputq1,
1186-
&n->bc_entry.namedq, snd_l,
1187-
&n->bc_entry.link)) {
1188-
pr_warn("Broadcast rcv link creation failed, no mem\n");
1189-
tipc_node_write_unlock_fast(n);
1190-
tipc_node_put(n);
1191-
return;
1192-
}
1193-
}
11941197

11951198
le = &n->links[b->identity];
11961199

0 commit comments

Comments
 (0)