git: 75102e8fb9c0 - stable/13 - sctp: improve handling of INIT chunks with invalid parameters

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Tue, 22 Feb 2022 22:35:42 UTC
The branch stable/13 has been updated by tuexen:

URL: https://cgit.FreeBSD.org/src/commit/?id=75102e8fb9c0e7f05c6bfd461eecb8b20a54654c

commit 75102e8fb9c0e7f05c6bfd461eecb8b20a54654c
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2021-08-18 22:31:35 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2022-02-22 22:35:17 +0000

    sctp: improve handling of INIT chunks with invalid parameters
    
    (cherry picked from commit eba8e643b19cb7acd7c9a79acfab376b3967f20d)
---
 sys/netinet/sctp_input.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index ce017b74b674..5152c382b7b7 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -86,7 +86,7 @@ static void
 sctp_handle_init(struct mbuf *m, int iphlen, int offset,
     struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
     struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
-    struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_no_unlock,
+    struct sctp_tcb *stcb, struct sctp_nets *net,
     uint8_t mflowtype, uint32_t mflowid,
     uint32_t vrf_id, uint16_t port)
 {
@@ -100,17 +100,17 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
 	}
 	/* Validate parameters */
 	init = &cp->init;
-	if ((ntohl(init->initiate_tag) == 0) ||
-	    (ntohl(init->a_rwnd) < SCTP_MIN_RWND) ||
+	if (ntohl(init->initiate_tag) == 0) {
+		goto outnow;
+	}
+	if ((ntohl(init->a_rwnd) < SCTP_MIN_RWND) ||
 	    (ntohs(init->num_inbound_streams) == 0) ||
 	    (ntohs(init->num_outbound_streams) == 0)) {
 		/* protocol error... send abort */
 		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
-		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
-		    mflowtype, mflowid,
+		sctp_send_abort(m, iphlen, src, dst, sh, init->initiate_tag, op_err,
+		    mflowtype, mflowid, inp->fibnum,
 		    vrf_id, port);
-		if (stcb)
-			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
@@ -118,11 +118,9 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
 		/* auth parameter(s) error... send abort */
 		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
 		    "Problem with AUTH parameters");
-		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
-		    mflowtype, mflowid,
+		sctp_send_abort(m, iphlen, src, dst, sh, init->initiate_tag, op_err,
+		    mflowtype, mflowid, inp->fibnum,
 		    vrf_id, port);
-		if (stcb)
-			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	/* We are only accepting if we have a listening socket. */
@@ -4612,20 +4610,22 @@ process_control_chunks:
 			/* Honor our resource limit. */
 			if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) {
 				op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
-				sctp_abort_association(inp, stcb, m, iphlen,
-				    src, dst, sh, op_err,
-				    mflowtype, mflowid,
+				sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
+				    mflowtype, mflowid, inp->fibnum,
 				    vrf_id, port);
 				*offset = length;
+				if (stcb != NULL) {
+					SCTP_TCB_UNLOCK(stcb);
+				}
 				return (NULL);
 			}
 			sctp_handle_init(m, iphlen, *offset, src, dst, sh,
 			    (struct sctp_init_chunk *)ch, inp,
-			    stcb, *netp, &abort_no_unlock,
+			    stcb, *netp,
 			    mflowtype, mflowid,
 			    vrf_id, port);
 			*offset = length;
-			if ((!abort_no_unlock) && (stcb != NULL)) {
+			if (stcb != NULL) {
 				SCTP_TCB_UNLOCK(stcb);
 			}
 			return (NULL);