aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorLUU Duc Canh <canh.d.luu@dektech.com.au>2018-09-26 16:28:52 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-02 01:35:30 -0400
commitd949cfedbcbab4e91590576cbace2671924ad69c (patch)
treeea98181918a49cbd67784a86ea2a135f6d854648 /net/tipc/node.c
parentaeadd93f2b0a609f603ac33e574b97a9832d1b90 (diff)
tipc: ignore STATE_MSG on wrong link session
The initial session number when a link is created is based on a random value, taken from struct tipc_net->random. It is then incremented for each link reset to avoid mixing protocol messages from different link sessions. However, when a bearer is reset all its links are deleted, and will later be re-created using the same random value as the first time. This means that if the link never went down between creation and deletion we will still sometimes have two subsequent sessions with the same session number. In virtual environments with potentially long transmission times this has turned out to be a real problem. We now fix this by randomizing the session number each time a link is created. With a session number size of 16 bits this gives a risk of session collision of 1/64k. To reduce this further, we also introduce a sanity check on the very first STATE message arriving at a link. If this has an acknowledge value differing from 0, which is logically impossible, we ignore the message. The final risk for session collision is hence reduced to 1/4G, which should be sufficient. Signed-off-by: LUU Duc Canh <canh.d.luu@dektech.com.au> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index b0ee25f1f2e6..2afc4f8c37a7 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -913,6 +913,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
913 bool reset = true; 913 bool reset = true;
914 char *if_name; 914 char *if_name;
915 unsigned long intv; 915 unsigned long intv;
916 u16 session;
916 917
917 *dupl_addr = false; 918 *dupl_addr = false;
918 *respond = false; 919 *respond = false;
@@ -999,9 +1000,10 @@ void tipc_node_check_dest(struct net *net, u32 addr,
999 goto exit; 1000 goto exit;
1000 1001
1001 if_name = strchr(b->name, ':') + 1; 1002 if_name = strchr(b->name, ':') + 1;
1003 get_random_bytes(&session, sizeof(u16));
1002 if (!tipc_link_create(net, if_name, b->identity, b->tolerance, 1004 if (!tipc_link_create(net, if_name, b->identity, b->tolerance,
1003 b->net_plane, b->mtu, b->priority, 1005 b->net_plane, b->mtu, b->priority,
1004 b->window, mod(tipc_net(net)->random), 1006 b->window, session,
1005 tipc_own_addr(net), addr, peer_id, 1007 tipc_own_addr(net), addr, peer_id,
1006 n->capabilities, 1008 n->capabilities,
1007 tipc_bc_sndlink(n->net), n->bc_entry.link, 1009 tipc_bc_sndlink(n->net), n->bc_entry.link,
@@ -1625,7 +1627,6 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1625 tipc_link_create_dummy_tnl_msg(l, xmitq); 1627 tipc_link_create_dummy_tnl_msg(l, xmitq);
1626 n->failover_sent = true; 1628 n->failover_sent = true;
1627 } 1629 }
1628
1629 /* If pkts arrive out of order, use lowest calculated syncpt */ 1630 /* If pkts arrive out of order, use lowest calculated syncpt */
1630 if (less(syncpt, n->sync_point)) 1631 if (less(syncpt, n->sync_point))
1631 n->sync_point = syncpt; 1632 n->sync_point = syncpt;