aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/port.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2011-06-01 15:08:10 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-06-24 16:18:18 -0400
commit1c1a551acb8b65f842824900b283a96462f907ab (patch)
tree902c7102e6d8159916c918372b6c880b109300dc /net/tipc/port.c
parente244a915ff7676b1567ba68102c9b53011f5b766 (diff)
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: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc/port.c')
-rw-r--r--net/tipc/port.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 8be68e0bf300..1b20b963a2fc 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -526,62 +526,63 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er
526void tipc_port_recv_proto_msg(struct sk_buff *buf) 526void tipc_port_recv_proto_msg(struct sk_buff *buf)
527{ 527{
528 struct tipc_msg *msg = buf_msg(buf); 528 struct tipc_msg *msg = buf_msg(buf);
529 struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); 529 struct tipc_port *p_ptr;
530 u32 err = TIPC_OK;
531 struct sk_buff *r_buf = NULL; 530 struct sk_buff *r_buf = NULL;
532 struct sk_buff *abort_buf = NULL; 531 u32 orignode = msg_orignode(msg);
533 532 u32 origport = msg_origport(msg);
534 if (!p_ptr) { 533 u32 destport = msg_destport(msg);
535 err = TIPC_ERR_NO_PORT; 534 int wakeable;
536 } else if (p_ptr->connected) { 535
537 if ((port_peernode(p_ptr) != msg_orignode(msg)) || 536 /* Validate connection */
538 (port_peerport(p_ptr) != msg_origport(msg))) { 537
539 err = TIPC_ERR_NO_PORT; 538 p_ptr = tipc_port_lock(destport);
540 } else if (msg_type(msg) == CONN_ACK) { 539 if (!p_ptr || !p_ptr->connected ||
541 int wakeup = tipc_port_congested(p_ptr) && 540 (port_peernode(p_ptr) != orignode) ||
542 p_ptr->congested && 541 (port_peerport(p_ptr) != origport)) {
543 p_ptr->wakeup; 542 r_buf = port_build_proto_msg(origport,
544 p_ptr->acked += msg_msgcnt(msg); 543 orignode,
545 if (tipc_port_congested(p_ptr)) 544 destport,
546 goto exit;
547 p_ptr->congested = 0;
548 if (!wakeup)
549 goto exit;
550 p_ptr->wakeup(p_ptr);
551 goto exit;
552 }
553 } else if (p_ptr->published) {
554 err = TIPC_ERR_NO_PORT;
555 }
556 if (err) {
557 r_buf = port_build_proto_msg(msg_origport(msg),
558 msg_orignode(msg),
559 msg_destport(msg),
560 tipc_own_addr, 545 tipc_own_addr,
561 TIPC_HIGH_IMPORTANCE, 546 TIPC_HIGH_IMPORTANCE,
562 TIPC_CONN_MSG, 547 TIPC_CONN_MSG,
563 err, 548 TIPC_ERR_NO_PORT,
564 0); 549 0);
550 if (p_ptr)
551 tipc_port_unlock(p_ptr);
565 goto exit; 552 goto exit;
566 } 553 }
567 554
568 /* All is fine */ 555 /* Process protocol message sent by peer */
569 if (msg_type(msg) == CONN_PROBE) { 556
570 r_buf = port_build_proto_msg(msg_origport(msg), 557 switch (msg_type(msg)) {
571 msg_orignode(msg), 558 case CONN_ACK:
572 msg_destport(msg), 559 wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
560 p_ptr->wakeup;
561 p_ptr->acked += msg_msgcnt(msg);
562 if (!tipc_port_congested(p_ptr)) {
563 p_ptr->congested = 0;
564 if (wakeable)
565 p_ptr->wakeup(p_ptr);
566 }
567 break;
568 case CONN_PROBE:
569 r_buf = port_build_proto_msg(origport,
570 orignode,
571 destport,
573 tipc_own_addr, 572 tipc_own_addr,
574 CONN_MANAGER, 573 CONN_MANAGER,
575 CONN_PROBE_REPLY, 574 CONN_PROBE_REPLY,
576 TIPC_OK, 575 TIPC_OK,
577 0); 576 0);
577 break;
578 default:
579 /* CONN_PROBE_REPLY or unrecognized - no action required */
580 break;
578 } 581 }
579 p_ptr->probing_state = CONFIRMED; 582 p_ptr->probing_state = CONFIRMED;
583 tipc_port_unlock(p_ptr);
580exit: 584exit:
581 if (p_ptr)
582 tipc_port_unlock(p_ptr);
583 tipc_net_route_msg(r_buf); 585 tipc_net_route_msg(r_buf);
584 tipc_net_route_msg(abort_buf);
585 buf_discard(buf); 586 buf_discard(buf);
586} 587}
587 588