Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 3085

kernel-2.6.18-238.el5.src.rpm

From: Eugene Teo <eteo@redhat.com>
Date: Thu, 9 Oct 2008 14:08:27 +0800
Subject: [net] sctp: INIT-ACK indicates no AUTH peer support oops
Message-id: 48ED9FDB.7010903@redhat.com
O-Subject: [RHEL5.3 patch] BZ#466082 kernel: sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH
Bugzilla: 466082
RH-Acked-by: Jiri Pirko <jpirko@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
RH-Acked-by: David Miller <davem@redhat.com>
CVE: CVE-2008-4576

This is for bz#466082. I'm still waiting for a CVE name to be assigned.

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.

Backport of upstream commit: add52379dde2e5300e2d574b172e62c6cf43b3d3

Signed-off-by: Eugene Teo <eteo@redhat.com>

diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 27329ce..a15f868 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -546,11 +546,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 17b5092..289a4fc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1956,12 +1956,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;
 }