diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2011-06-01 15:08:10 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2011-06-24 16:18:18 -0400 |
commit | 1c1a551acb8b65f842824900b283a96462f907ab (patch) | |
tree | 902c7102e6d8159916c918372b6c880b109300dc /net/tipc/port.c | |
parent | e244a915ff7676b1567ba68102c9b53011f5b766 (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.c | 79 |
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 | |||
526 | void tipc_port_recv_proto_msg(struct sk_buff *buf) | 526 | void 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); | ||
580 | exit: | 584 | exit: |
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 | ||