summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-03-27 10:19:19 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-29 16:47:36 -0400
commitd482994fca82380912b3a80201b74d5118ff0487 (patch)
tree42831f6ce50ea0c79fe958d71d9ec5fd02b51121
parent4d92a3e9b90e23eaf7d893d1841cd0391403b99a (diff)
tipc: fix two bugs in secondary destination lookup
A message sent to a node after a successful name table lookup may still find that the destination socket has disappeared, because distribution of name table updates is non-atomic. If so, the message will be rejected back to the sender with error code TIPC_ERR_NO_PORT. If the source socket of the message has disappeared in the meantime, the message should be dropped. However, in the currrent code, the message will instead be subject to an unwanted tertiary lookup, because the function tipc_msg_lookup_dest() doesn't check if there is an error code present in the message before performing the lookup. In the worst case, the message may now find the old destination again, and be redirected once more, instead of being dropped directly as it should be. A second bug in this function is that the "prev_node" field in the message is not updated after successful lookup, something that may have unpredictable consequences. The problems arising from those bugs occur very infrequently. The third change in this function; the test on msg_reroute_msg_cnt() is purely cosmetic, reflecting that the returned value never can be negative. This commit corrects the two bugs described above. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/addr.c7
-rw-r--r--net/tipc/addr.h1
-rw-r--r--net/tipc/msg.c7
3 files changed, 14 insertions, 1 deletions
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index 48fd3b5a73fb..ba7daa864d44 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -38,6 +38,13 @@
38#include "addr.h" 38#include "addr.h"
39#include "core.h" 39#include "core.h"
40 40
41u32 tipc_own_addr(struct net *net)
42{
43 struct tipc_net *tn = net_generic(net, tipc_net_id);
44
45 return tn->own_addr;
46}
47
41/** 48/**
42 * in_own_cluster - test for cluster inclusion; <0.0.0> always matches 49 * in_own_cluster - test for cluster inclusion; <0.0.0> always matches
43 */ 50 */
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index c700c2d28e09..7ba6d5c8ae40 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -55,6 +55,7 @@ static inline u32 tipc_cluster_mask(u32 addr)
55 return addr & TIPC_CLUSTER_MASK; 55 return addr & TIPC_CLUSTER_MASK;
56} 56}
57 57
58u32 tipc_own_addr(struct net *net);
58int in_own_cluster(struct net *net, u32 addr); 59int in_own_cluster(struct net *net, u32 addr);
59int in_own_cluster_exact(struct net *net, u32 addr); 60int in_own_cluster_exact(struct net *net, u32 addr);
60int in_own_node(struct net *net, u32 addr); 61int in_own_node(struct net *net, u32 addr);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 0c6dad8180a0..3bb499c61918 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -511,15 +511,18 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
511{ 511{
512 struct tipc_msg *msg = buf_msg(skb); 512 struct tipc_msg *msg = buf_msg(skb);
513 u32 dport; 513 u32 dport;
514 u32 own_addr = tipc_own_addr(net);
514 515
515 if (!msg_isdata(msg)) 516 if (!msg_isdata(msg))
516 return false; 517 return false;
517 if (!msg_named(msg)) 518 if (!msg_named(msg))
518 return false; 519 return false;
520 if (msg_errcode(msg))
521 return false;
519 *err = -TIPC_ERR_NO_NAME; 522 *err = -TIPC_ERR_NO_NAME;
520 if (skb_linearize(skb)) 523 if (skb_linearize(skb))
521 return false; 524 return false;
522 if (msg_reroute_cnt(msg) > 0) 525 if (msg_reroute_cnt(msg))
523 return false; 526 return false;
524 *dnode = addr_domain(net, msg_lookup_scope(msg)); 527 *dnode = addr_domain(net, msg_lookup_scope(msg));
525 dport = tipc_nametbl_translate(net, msg_nametype(msg), 528 dport = tipc_nametbl_translate(net, msg_nametype(msg),
@@ -527,6 +530,8 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
527 if (!dport) 530 if (!dport)
528 return false; 531 return false;
529 msg_incr_reroute_cnt(msg); 532 msg_incr_reroute_cnt(msg);
533 if (*dnode != own_addr)
534 msg_set_prevnode(msg, own_addr);
530 msg_set_destnode(msg, *dnode); 535 msg_set_destnode(msg, *dnode);
531 msg_set_destport(msg, dport); 536 msg_set_destport(msg, dport);
532 *err = TIPC_OK; 537 *err = TIPC_OK;