diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2008-09-18 19:28:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-18 19:28:27 -0400 |
commit | add52379dde2e5300e2d574b172e62c6cf43b3d3 (patch) | |
tree | c322f35beba73d356a44c1e31fed7a5791175eb6 | |
parent | 0ef46e285c062cbe35d60c0adbff96f530d31c86 (diff) |
sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH
If INIT-ACK is received with SupportedExtensions parameter which
indicates that the peer does not support AUTH, the packet will be
silently ignore, and sctp_process_init() do cleanup all of the
transports in the association.
When T1-Init timer is expires, OOPS happen while we try to choose
a different init transport.
The solution is to only clean up the non-active transports, i.e
the ones that the peer added. However, that introduces a problem
with sctp_connectx(), because we don't mark the proper state for
the transports provided by the user. So, we'll simply mark
user-provided transports as ACTIVE. That will allow INIT
retransmissions to work properly in the sctp_connectx() context
and prevent the crash.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sctp/associola.c | 9 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 6 |
2 files changed, 7 insertions, 8 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c4..abd51cef2413 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
599 | /* Check to see if this is a duplicate. */ | 599 | /* Check to see if this is a duplicate. */ |
600 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 600 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
601 | if (peer) { | 601 | if (peer) { |
602 | /* An UNKNOWN state is only set on transports added by | ||
603 | * user in sctp_connectx() call. Such transports should be | ||
604 | * considered CONFIRMED per RFC 4960, Section 5.4. | ||
605 | */ | ||
602 | if (peer->state == SCTP_UNKNOWN) { | 606 | if (peer->state == SCTP_UNKNOWN) { |
603 | if (peer_state == SCTP_ACTIVE) | 607 | peer->state = SCTP_ACTIVE; |
604 | peer->state = SCTP_ACTIVE; | ||
605 | if (peer_state == SCTP_UNCONFIRMED) | ||
606 | peer->state = SCTP_UNCONFIRMED; | ||
607 | } | 608 | } |
608 | return peer; | 609 | return peer; |
609 | } | 610 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fe94f42fa068..b599cbba4fbe 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2321,12 +2321,10 @@ clean_up: | |||
2321 | /* Release the transport structures. */ | 2321 | /* Release the transport structures. */ |
2322 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2322 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
2323 | transport = list_entry(pos, struct sctp_transport, transports); | 2323 | transport = list_entry(pos, struct sctp_transport, transports); |
2324 | list_del_init(pos); | 2324 | if (transport->state != SCTP_ACTIVE) |
2325 | sctp_transport_free(transport); | 2325 | sctp_assoc_rm_peer(asoc, transport); |
2326 | } | 2326 | } |
2327 | 2327 | ||
2328 | asoc->peer.transport_count = 0; | ||
2329 | |||
2330 | nomem: | 2328 | nomem: |
2331 | return 0; | 2329 | return 0; |
2332 | } | 2330 | } |