diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2008-09-18 16:28:27 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-08 19:44:45 -0700 |
commit | bb5168ca75d488ee10e4653ddbf4cd51a57707f3 (patch) | |
tree | a9579ead1829a8be1262e7b473b7b4ef5cc76b30 | |
parent | b18dfc326dd814b63abd0a484e3e300300065edc (diff) |
sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH
[ Upstream commit add52379dde2e5300e2d574b172e62c6cf43b3d3 ]
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-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 d29f792e052..1eefac20bae 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -588,11 +588,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, /* Check to see if this is a duplicate. */ peer = sctp_assoc_lookup_paddr(asoc, addr); if (peer) { + /* An UNKNOWN state is only set on transports added by + * user in sctp_connectx() call. Such transports should be + * considered CONFIRMED per RFC 4960, Section 5.4. + */ if (peer->state == SCTP_UNKNOWN) { - if (peer_state == SCTP_ACTIVE) - peer->state = SCTP_ACTIVE; - if (peer_state == SCTP_UNCONFIRMED) - peer->state = SCTP_UNCONFIRMED; + peer->state = SCTP_ACTIVE; } return peer; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 46862775d41..d024fd04913 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2321,12 +2321,10 @@ clean_up: /* Release the transport structures. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - list_del_init(pos); - sctp_transport_free(transport); + if (transport->state != SCTP_ACTIVE) + sctp_assoc_rm_peer(asoc, transport); } - asoc->peer.transport_count = 0; - nomem: return 0; } |