Commit 1c1a551a authored by Allan Stephens's avatar Allan Stephens Committed by Paul Gortmaker

tipc: Reject connection protocol message sent to unconnected port

Restructures the logic used in tipc_port_recv_proto_msg() to ensure
that incoming connection protocol messages are handled properly. The
routine now uses a two-stage process that first ensures the message
applies on an existing connection and then processes the request.
This corrects a loophole that allowed a connection probe request to
be processed if it was sent to an unconnected port that had no names
bound to it.
Signed-off-by: default avatarAllan Stephens <allan.stephens@windriver.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent e244a915
...@@ -526,62 +526,63 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er ...@@ -526,62 +526,63 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er
void tipc_port_recv_proto_msg(struct sk_buff *buf) void tipc_port_recv_proto_msg(struct sk_buff *buf)
{ {
struct tipc_msg *msg = buf_msg(buf); struct tipc_msg *msg = buf_msg(buf);
struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); struct tipc_port *p_ptr;
u32 err = TIPC_OK;
struct sk_buff *r_buf = NULL; struct sk_buff *r_buf = NULL;
struct sk_buff *abort_buf = NULL; u32 orignode = msg_orignode(msg);
u32 origport = msg_origport(msg);
if (!p_ptr) { u32 destport = msg_destport(msg);
err = TIPC_ERR_NO_PORT; int wakeable;
} else if (p_ptr->connected) {
if ((port_peernode(p_ptr) != msg_orignode(msg)) || /* Validate connection */
(port_peerport(p_ptr) != msg_origport(msg))) {
err = TIPC_ERR_NO_PORT; p_ptr = tipc_port_lock(destport);
} else if (msg_type(msg) == CONN_ACK) { if (!p_ptr || !p_ptr->connected ||
int wakeup = tipc_port_congested(p_ptr) && (port_peernode(p_ptr) != orignode) ||
p_ptr->congested && (port_peerport(p_ptr) != origport)) {
p_ptr->wakeup; r_buf = port_build_proto_msg(origport,
p_ptr->acked += msg_msgcnt(msg); orignode,
if (tipc_port_congested(p_ptr)) destport,
goto exit;
p_ptr->congested = 0;
if (!wakeup)
goto exit;
p_ptr->wakeup(p_ptr);
goto exit;
}
} else if (p_ptr->published) {
err = TIPC_ERR_NO_PORT;
}
if (err) {
r_buf = port_build_proto_msg(msg_origport(msg),
msg_orignode(msg),
msg_destport(msg),
tipc_own_addr, tipc_own_addr,
TIPC_HIGH_IMPORTANCE, TIPC_HIGH_IMPORTANCE,
TIPC_CONN_MSG, TIPC_CONN_MSG,
err, TIPC_ERR_NO_PORT,
0); 0);
if (p_ptr)
tipc_port_unlock(p_ptr);
goto exit; goto exit;
} }
/* All is fine */ /* Process protocol message sent by peer */
if (msg_type(msg) == CONN_PROBE) {
r_buf = port_build_proto_msg(msg_origport(msg), switch (msg_type(msg)) {
msg_orignode(msg), case CONN_ACK:
msg_destport(msg), wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
p_ptr->wakeup;
p_ptr->acked += msg_msgcnt(msg);
if (!tipc_port_congested(p_ptr)) {
p_ptr->congested = 0;
if (wakeable)
p_ptr->wakeup(p_ptr);
}
break;
case CONN_PROBE:
r_buf = port_build_proto_msg(origport,
orignode,
destport,
tipc_own_addr, tipc_own_addr,
CONN_MANAGER, CONN_MANAGER,
CONN_PROBE_REPLY, CONN_PROBE_REPLY,
TIPC_OK, TIPC_OK,
0); 0);
break;
default:
/* CONN_PROBE_REPLY or unrecognized - no action required */
break;
} }
p_ptr->probing_state = CONFIRMED; p_ptr->probing_state = CONFIRMED;
tipc_port_unlock(p_ptr);
exit: exit:
if (p_ptr)
tipc_port_unlock(p_ptr);
tipc_net_route_msg(r_buf); tipc_net_route_msg(r_buf);
tipc_net_route_msg(abort_buf);
buf_discard(buf); buf_discard(buf);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment