fix Jon's email address. On Mon, Jun 6, 2022 at 11:24 AM Xin Long <lucien....@gmail.com> wrote: > > 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: 4cbf8ac2fe5a ("tipc: enable creating a "preliminary" node") > Reported-by: Shuang Li <shu...@redhat.com> > Signed-off-by: Xin Long <lucien....@gmail.com> > --- > net/tipc/node.c | 41 ++++++++++++++++++++++------------------- > 1 file changed, 22 insertions(+), 19 deletions(-) > > diff --git a/net/tipc/node.c b/net/tipc/node.c > index 6ef95ce565bd..b48d97cbbe29 100644 > --- a/net/tipc/node.c > +++ b/net/tipc/node.c > @@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 > addr, u8 *peer_id, > bool preliminary) > { > struct tipc_net *tn = net_generic(net, tipc_net_id); > + struct tipc_link *l, *snd_l = tipc_bc_sndlink(net); > struct tipc_node *n, *temp_node; > - struct tipc_link *l; > unsigned long intv; > int bearer_id; > int i; > @@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 > addr, u8 *peer_id, > goto exit; > /* A preliminary node becomes "real" now, refresh its data */ > tipc_node_write_lock(n); > + if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, > peer_id, U16_MAX, > + tipc_link_min_win(snd_l), > tipc_link_max_win(snd_l), > + n->capabilities, > &n->bc_entry.inputq1, > + &n->bc_entry.namedq, snd_l, > &n->bc_entry.link)) { > + pr_warn("Broadcast rcv link refresh failed, no > memory\n"); > + tipc_node_write_unlock_fast(n); > + tipc_node_put(n); > + n = NULL; > + goto exit; > + } > n->preliminary = false; > n->addr = addr; > hlist_del_rcu(&n->hash); > @@ -567,7 +577,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 > addr, u8 *peer_id, > n->signature = INVALID_NODE_SIG; > n->active_links[0] = INVALID_BEARER_ID; > n->active_links[1] = INVALID_BEARER_ID; > - n->bc_entry.link = NULL; > + if (!preliminary && > + !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, > U16_MAX, > + tipc_link_min_win(snd_l), > tipc_link_max_win(snd_l), > + n->capabilities, &n->bc_entry.inputq1, > + &n->bc_entry.namedq, snd_l, > &n->bc_entry.link)) { > + pr_warn("Broadcast rcv link creation failed, no memory\n"); > + kfree(n); > + n = NULL; > + goto exit; > + } > tipc_node_get(n); > timer_setup(&n->timer, tipc_node_timeout, 0); > /* Start a slow timer anyway, crypto needs it */ > @@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr, > bool *respond, bool *dupl_addr) > { > struct tipc_node *n; > - struct tipc_link *l, *snd_l; > + struct tipc_link *l; > struct tipc_link_entry *le; > bool addr_match = false; > bool sign_match = false; > @@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr, > return; > > tipc_node_write_lock(n); > - if (unlikely(!n->bc_entry.link)) { > - snd_l = tipc_bc_sndlink(net); > - if (!tipc_link_bc_create(net, tipc_own_addr(net), > - addr, peer_id, U16_MAX, > - tipc_link_min_win(snd_l), > - tipc_link_max_win(snd_l), > - n->capabilities, > - &n->bc_entry.inputq1, > - &n->bc_entry.namedq, snd_l, > - &n->bc_entry.link)) { > - pr_warn("Broadcast rcv link creation failed, no > mem\n"); > - tipc_node_write_unlock_fast(n); > - tipc_node_put(n); > - return; > - } > - } > > le = &n->links[b->identity]; > > -- > 2.31.1 >
_______________________________________________ tipc-discussion mailing list tipc-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tipc-discussion