In commit 2d18ac4ba745 ("tipc: extend broadcast link initialization
criteria") we tried to fix a problem with the initial synchronization
of broadcast link acknowledge values. Unfortunately that solution is
not sufficient to solve the problem.

We have seen it happen that a LINK_PROTOCOL/STATE message with a valid
non-zero unicast acknowledge number may bypass BCAST_PROTOCOL
initialization and NAME_DISRIBUTOR packets with invalid broadcast
acknowledge numbers, leading to premature opening of the broadcast link.
When this happens, the already correctly initialized acknowledge number
of the broadcast receive link will be overwritten by the invalid (zero)
value of the said packets, and the broadcast link risks going stale.

We now fix this by ignoring acknowledges that we know potentially may
be invalid. Identifying such acknowledges is easy, since their broadcast
acknowledge value always is zero, and since this can only happen to
BCAST_PROTOCOL and NAME_DISTRIBUTOR messages.

Reported-by: John Thompson <thompa....@gmail.com>
Signed-off-by: Jon Maloy <jon.ma...@ericsson.com>
---
 net/tipc/bcast.c | 7 ++++++-
 net/tipc/bcast.h | 3 ++-
 net/tipc/node.c  | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index ae469b3..27ffa37 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -247,11 +247,16 @@ int tipc_bcast_rcv(struct net *net, struct tipc_link *l, 
struct sk_buff *skb)
  *
  * RCU is locked, no other locks set
  */
-void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked)
+void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
+                       int usr, u16 acked)
 {
        struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
        struct sk_buff_head xmitq;
 
+       /* Ignore acks potentially sent before bcast synch point was received */
+       if (!acked && ((usr == BCAST_PROTOCOL) || (usr == NAME_DISTRIBUTOR)))
+               return;
+
        __skb_queue_head_init(&xmitq);
 
        tipc_bcast_lock(net);
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index d5e79b3..0529cb5 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -55,7 +55,8 @@ void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int 
bearer_id);
 int  tipc_bcast_get_mtu(struct net *net);
 int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);
 int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb);
-void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked);
+void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
+                       int usr, u16 acked);
 void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
                         struct tipc_msg *hdr);
 int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 2197419..42f98af 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1507,7 +1507,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, 
struct tipc_bearer *b)
        if (unlikely(usr == LINK_PROTOCOL))
                tipc_bcast_sync_rcv(net, n->bc_entry.link, hdr);
        else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
-               tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);
+               tipc_bcast_ack_rcv(net, n->bc_entry.link, usr, bc_ack);
 
        /* Receive packet directly if conditions permit */
        tipc_node_read_lock(n);
-- 
2.7.4


------------------------------------------------------------------------------
_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to