Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 May 2020 00:23:07 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r360724 - stable/11/sys/netinet
Message-ID:  <202005070023.0470N7tu015829@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Thu May  7 00:23:07 2020
New Revision: 360724
URL: https://svnweb.freebsd.org/changeset/base/360724

Log:
  MFC r350508: Improve sending of ABORT message in SCTP
  
  When responding with an ABORT to an INIT chunk containing a
  HOSTNAME parameter or a parameter with an illegal length, only
  include an error cause indicating why the ABORT was sent.
  This also fixes an mbuf leak which could occur.

Modified:
  stable/11/sys/netinet/sctp_output.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/sctp_output.c
==============================================================================
--- stable/11/sys/netinet/sctp_output.c	Wed May  6 23:31:30 2020	(r360723)
+++ stable/11/sys/netinet/sctp_output.c	Thu May  7 00:23:07 2020	(r360724)
@@ -5108,55 +5108,42 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_
 			break;
 		case SCTP_HOSTNAME_ADDRESS:
 			{
-				/* We can NOT handle HOST NAME addresses!! */
+				/* Hostname parameters are deprecated. */
+				struct sctp_gen_error_cause *cause;
 				int l_len;
 
 				SCTPDBG(SCTP_DEBUG_OUTPUT1, "Can't handle hostname addresses.. abort processing\n");
 				*abort_processing = 1;
-				if (op_err == NULL) {
-					/* Ok need to try to get a mbuf */
+				sctp_m_freem(op_err);
+				op_err = NULL;
 #ifdef INET6
-					l_len = SCTP_MIN_OVERHEAD;
+				l_len = SCTP_MIN_OVERHEAD;
 #else
-					l_len = SCTP_MIN_V4_OVERHEAD;
+				l_len = SCTP_MIN_V4_OVERHEAD;
 #endif
-					l_len += sizeof(struct sctp_chunkhdr);
-					l_len += sizeof(struct sctp_gen_error_cause);
-					op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA);
-					if (op_err) {
-						SCTP_BUF_LEN(op_err) = 0;
-						/*
-						 * Pre-reserve space for IP,
-						 * SCTP, and chunk header.
-						 */
+				l_len += sizeof(struct sctp_chunkhdr);
+				l_len += sizeof(struct sctp_gen_error_cause);
+				op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA);
+				if (op_err) {
+					/*
+					 * Pre-reserve space for IP, SCTP,
+					 * and chunk header.
+					 */
 #ifdef INET6
-						SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
+					SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
 #else
-						SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
+					SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
 #endif
-						SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
-						SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
-					}
-				}
-				if (op_err) {
-					/* If we have space */
-					struct sctp_gen_error_cause cause;
-
-					if (err_at % 4) {
-						uint32_t cpthis = 0;
-
-						pad_needed = 4 - (err_at % 4);
-						m_copyback(op_err, err_at, pad_needed, (caddr_t)&cpthis);
-						err_at += pad_needed;
-					}
-					cause.code = htons(SCTP_CAUSE_UNRESOLVABLE_ADDR);
-					cause.length = htons((uint16_t)(sizeof(struct sctp_gen_error_cause) + plen));
-					m_copyback(op_err, err_at, sizeof(struct sctp_gen_error_cause), (caddr_t)&cause);
-					err_at += sizeof(struct sctp_gen_error_cause);
+					SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
+					SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
+					SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
+					cause = mtod(op_err, struct sctp_gen_error_cause *);
+					cause->code = htons(SCTP_CAUSE_UNRESOLVABLE_ADDR);
+					cause->length = htons((uint16_t)(sizeof(struct sctp_gen_error_cause) + plen));
 					SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(mat, at, plen, M_NOWAIT);
 					if (SCTP_BUF_NEXT(op_err) == NULL) {
 						sctp_m_freem(op_err);
-						return (NULL);
+						op_err = NULL;
 					}
 				}
 				return (op_err);
@@ -5243,7 +5230,10 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_
 invalid_size:
 	SCTPDBG(SCTP_DEBUG_OUTPUT1, "abort flag set\n");
 	*abort_processing = 1;
-	if ((op_err == NULL) && phdr) {
+	sctp_m_freem(op_err);
+	op_err = NULL;
+	if (phdr != NULL) {
+		struct sctp_paramhdr *param;
 		int l_len;
 #ifdef INET6
 		l_len = SCTP_MIN_OVERHEAD;
@@ -5262,24 +5252,14 @@ invalid_size:
 #endif
 			SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
 			SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
+			SCTP_BUF_LEN(op_err) = 2 * sizeof(struct sctp_paramhdr);
+			param = mtod(op_err, struct sctp_paramhdr *);
+			param->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
+			param->param_length = htons(2 * sizeof(struct sctp_paramhdr));
+			param++;
+			param->param_type = htons(ptype);
+			param->param_length = htons(plen);
 		}
-	}
-	if ((op_err) && phdr) {
-		struct sctp_paramhdr s;
-
-		if (err_at % 4) {
-			uint32_t cpthis = 0;
-
-			pad_needed = 4 - (err_at % 4);
-			m_copyback(op_err, err_at, pad_needed, (caddr_t)&cpthis);
-			err_at += pad_needed;
-		}
-		s.param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-		s.param_length = htons(sizeof(s) + sizeof(struct sctp_paramhdr));
-		m_copyback(op_err, err_at, sizeof(s), (caddr_t)&s);
-		err_at += sizeof(s);
-		/* Only copy back the p-hdr that caused the issue */
-		m_copyback(op_err, err_at, sizeof(struct sctp_paramhdr), (caddr_t)phdr);
 	}
 	return (op_err);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202005070023.0470N7tu015829>