Skip to content

Commit

Permalink
tipc: check session number before accepting link protocol messages
Browse files Browse the repository at this point in the history
In some virtual environments we observe a significant higher number of
packet reordering and delays than we have been used to traditionally.

This makes it necessary with stricter checks on incoming link protocol
messages' session number, which until now only has been validated for
RESET messages.

Since the other two message types, ACTIVATE and STATE messages also
carry this number, it is easy to extend the validation check to those
messages.

We also introduce a flag indicating if a link has a valid peer session
number or not. This eliminates the mixing of 32- and 16-bit arithmethics
we are currently using to achieve this.

Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jon Maloy authored and David S. Miller committed Jul 12, 2018
1 parent 9012de5 commit 7ea817f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
68 changes: 47 additions & 21 deletions net/tipc/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ struct tipc_link {
struct net *net;

/* Management and link supervision data */
u32 peer_session;
u32 session;
u16 peer_session;
u16 session;
u16 snd_nxt_state;
u16 rcv_nxt_state;
u32 peer_bearer_id;
Expand All @@ -138,6 +138,7 @@ struct tipc_link {
u32 abort_limit;
u32 state;
u16 peer_caps;
bool in_session;
bool active;
u32 silent_intv_cnt;
char if_name[TIPC_MAX_IF_NAME];
Expand Down Expand Up @@ -216,11 +217,6 @@ enum {
*/
#define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2)

/* Wildcard value for link session numbers. When it is known that
* peer endpoint is down, any session number must be accepted.
*/
#define ANY_SESSION 0x10000

/* Link FSM states:
*/
enum {
Expand Down Expand Up @@ -478,7 +474,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
l->addr = peer;
l->peer_caps = peer_caps;
l->net = net;
l->peer_session = ANY_SESSION;
l->in_session = false;
l->bearer_id = bearer_id;
l->tolerance = tolerance;
l->net_plane = net_plane;
Expand Down Expand Up @@ -847,7 +843,7 @@ void link_prepare_wakeup(struct tipc_link *l)

void tipc_link_reset(struct tipc_link *l)
{
l->peer_session = ANY_SESSION;
l->in_session = false;
l->session++;
l->mtu = l->advertised_mtu;
__skb_queue_purge(&l->transmq);
Expand Down Expand Up @@ -1455,6 +1451,44 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
}
}

/* tipc_link_validate_msg(): validate message against current link state
* Returns true if message should be accepted, otherwise false
*/
bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr)
{
u16 curr_session = l->peer_session;
u16 session = msg_session(hdr);
int mtyp = msg_type(hdr);

if (msg_user(hdr) != LINK_PROTOCOL)
return true;

switch (mtyp) {
case RESET_MSG:
if (!l->in_session)
return true;
/* Accept only RESET with new session number */
return more(session, curr_session);
case ACTIVATE_MSG:
if (!l->in_session)
return true;
/* Accept only ACTIVATE with new or current session number */
return !less(session, curr_session);
case STATE_MSG:
/* Accept only STATE with current session number */
if (!l->in_session)
return false;
if (session != curr_session)
return false;
if (!(l->peer_caps & TIPC_LINK_PROTO_SEQNO))
return true;
/* Accept only STATE with new sequence number */
return !less(msg_seqno(hdr), l->rcv_nxt_state);
default:
return false;
}
}

/* tipc_link_proto_rcv(): receive link level protocol message :
* Note that network plane id propagates through the network, and may
* change at any time. The node with lowest numerical id determines
Expand Down Expand Up @@ -1488,17 +1522,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
hdr = buf_msg(skb);
data = msg_data(hdr);

if (!tipc_link_validate_msg(l, hdr))
goto exit;

switch (mtyp) {
case RESET_MSG:

/* Ignore duplicate RESET with old session number */
if ((less_eq(msg_session(hdr), l->peer_session)) &&
(l->peer_session != ANY_SESSION))
break;
/* fall thru' */

case ACTIVATE_MSG:

/* Complete own link name with peer's interface name */
if_name = strrchr(l->name, ':') + 1;
if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
Expand Down Expand Up @@ -1526,16 +1555,13 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
rc = TIPC_LINK_UP_EVT;

l->peer_session = msg_session(hdr);
l->in_session = true;
l->peer_bearer_id = msg_bearer_id(hdr);
if (l->mtu > msg_max_pkt(hdr))
l->mtu = msg_max_pkt(hdr);
break;

case STATE_MSG:

if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
less(msg_seqno(hdr), l->rcv_nxt_state))
break;
l->rcv_nxt_state = msg_seqno(hdr) + 1;

/* Update own tolerance if peer indicates a non-zero value */
Expand Down
1 change: 1 addition & 0 deletions net/tipc/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ char tipc_link_plane(struct tipc_link *l);
int tipc_link_prio(struct tipc_link *l);
int tipc_link_window(struct tipc_link *l);
void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr);
unsigned long tipc_link_tolerance(struct tipc_link *l);
void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
struct sk_buff_head *xmitq);
Expand Down
5 changes: 4 additions & 1 deletion net/tipc/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
* tipc_node_check_state - check and if necessary update node state
* @skb: TIPC packet
* @bearer_id: identity of bearer delivering the packet
* Returns true if state is ok, otherwise consumes buffer and returns false
* Returns true if state and msg are ok, otherwise false
*/
static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
int bearer_id, struct sk_buff_head *xmitq)
Expand Down Expand Up @@ -1574,6 +1574,9 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
}
}

if (!tipc_link_validate_msg(l, hdr))
return false;

/* Check and update node accesibility if applicable */
if (state == SELF_UP_PEER_COMING) {
if (!tipc_link_is_up(l))
Expand Down

0 comments on commit 7ea817f

Please sign in to comment.