Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Sep 2020 16:24:32 +0000 (UTC)
From:      Gordon Tetlow <gordon@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r365256 - in releng: 11.3/sys/netinet 11.4/sys/netinet 12.1/sys/netinet
Message-ID:  <202009021624.082GOWI5036990@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gordon
Date: Wed Sep  2 16:24:32 2020
New Revision: 365256
URL: https://svnweb.freebsd.org/changeset/base/365256

Log:
  Fix SCTP socket use-after-free.
  
  Approved by:	so
  Security:	FreeBSD-SA-20:25.sctp
  Security:	CVE-2020-7463

Modified:
  releng/11.3/sys/netinet/sctp_input.c
  releng/11.3/sys/netinet/sctp_output.c
  releng/11.3/sys/netinet/sctp_pcb.c
  releng/11.3/sys/netinet/sctp_structs.h
  releng/11.3/sys/netinet/sctputil.c
  releng/11.3/sys/netinet/sctputil.h
  releng/11.4/sys/netinet/sctp_input.c
  releng/11.4/sys/netinet/sctp_output.c
  releng/11.4/sys/netinet/sctp_pcb.c
  releng/11.4/sys/netinet/sctp_structs.h
  releng/11.4/sys/netinet/sctputil.c
  releng/11.4/sys/netinet/sctputil.h
  releng/12.1/sys/netinet/sctp_input.c
  releng/12.1/sys/netinet/sctp_output.c
  releng/12.1/sys/netinet/sctp_pcb.c
  releng/12.1/sys/netinet/sctp_structs.h
  releng/12.1/sys/netinet/sctputil.c
  releng/12.1/sys/netinet/sctputil.h

Modified: releng/11.3/sys/netinet/sctp_input.c
==============================================================================
--- releng/11.3/sys/netinet/sctp_input.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctp_input.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -839,7 +839,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
 	SCTP_TCB_LOCK(stcb);
 	atomic_subtract_int(&stcb->asoc.refcnt, 1);
 #endif
-	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
 	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -1989,7 +1988,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphle
 		/* send up all the data */
 		SCTP_TCB_SEND_LOCK(stcb);
 
-		sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
+		sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED);
 		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 			stcb->asoc.strmout[i].chunks_on_queues = 0;
 #if defined(SCTP_DETAILED_STR_STATS)

Modified: releng/11.3/sys/netinet/sctp_output.c
==============================================================================
--- releng/11.3/sys/netinet/sctp_output.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctp_output.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -13159,11 +13159,10 @@ skip_preblock:
 			error = EINVAL;
 			goto out;
 		}
-		SCTP_TCB_SEND_UNLOCK(stcb);
-
 		strm = &stcb->asoc.strmout[srcv->sinfo_stream];
 		if (strm->last_msg_incomplete == 0) {
 	do_a_copy_in:
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
 			if (error) {
 				goto out;
@@ -13189,13 +13188,11 @@ skip_preblock:
 			if (srcv->sinfo_flags & SCTP_UNORDERED) {
 				SCTP_STAT_INCR(sctps_sends_with_unord);
 			}
+			sp->processing = 1;
 			TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
 			stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 		} else {
-			SCTP_TCB_SEND_LOCK(stcb);
 			sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 			if (sp == NULL) {
 				/* ???? Huh ??? last msg is gone */
 #ifdef INVARIANTS
@@ -13207,7 +13204,16 @@ skip_preblock:
 				goto do_a_copy_in;
 
 			}
+			if (sp->processing) {
+				SCTP_TCB_SEND_UNLOCK(stcb);
+				SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+				error = EINVAL;
+				goto out;
+			} else {
+				sp->processing = 1;
+			}
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		while (uio->uio_resid > 0) {
 			/* How much room do we have? */
 			struct mbuf *new_tail, *mm;
@@ -13232,20 +13238,29 @@ skip_preblock:
 					if (mm) {
 						sctp_m_freem(mm);
 					}
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
 				/* Update the mbuf and count */
 				SCTP_TCB_SEND_LOCK(stcb);
-				if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+				    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 					/*
 					 * we need to get out. Peer probably
 					 * aborted.
 					 */
 					sctp_m_freem(mm);
-					if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) {
+					if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) {
 						SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
 						error = ECONNRESET;
 					}
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
 					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
@@ -13305,6 +13320,11 @@ skip_preblock:
 			/* wait for space now */
 			if (non_blocking) {
 				/* Non-blocking io in place out */
+				SCTP_TCB_SEND_LOCK(stcb);
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto skip_out_eof;
 			}
 			/* What about the INIT, send it maybe */
@@ -13428,6 +13448,11 @@ skip_preblock:
 						}
 					}
 					SOCKBUF_UNLOCK(&so->so_snd);
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out_unlocked;
 				}
 
@@ -13437,12 +13462,19 @@ skip_preblock:
 				}
 			}
 			SOCKBUF_UNLOCK(&so->so_snd);
+			SCTP_TCB_SEND_LOCK(stcb);
 			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto out_unlocked;
 			}
+			SCTP_TCB_SEND_UNLOCK(stcb);
 		}
 		SCTP_TCB_SEND_LOCK(stcb);
-		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+		if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+		    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 			SCTP_TCB_SEND_UNLOCK(stcb);
 			goto out_unlocked;
 		}
@@ -13458,6 +13490,7 @@ skip_preblock:
 				strm->last_msg_incomplete = 0;
 				asoc->stream_locked = 0;
 			}
+			sp->processing = 0;
 		} else {
 			SCTP_PRINTF("Huh no sp TSNH?\n");
 			strm->last_msg_incomplete = 0;

Modified: releng/11.3/sys/netinet/sctp_pcb.c
==============================================================================
--- releng/11.3/sys/netinet/sctp_pcb.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctp_pcb.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -4722,6 +4722,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 		/* there is no asoc, really TSNH :-0 */
 		return (1);
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
 	if (stcb->asoc.alternate) {
 		sctp_free_remote_addr(stcb->asoc.alternate);
 		stcb->asoc.alternate = NULL;
@@ -4756,6 +4757,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			/* nope, reader or writer in the way */
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 			/* no asoc destroyed */
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			SCTP_TCB_UNLOCK(stcb);
 #ifdef SCTP_LOG_CLOSING
 			sctp_log_closing(inp, stcb, 8);
@@ -4853,6 +4855,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
 		    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
@@ -4886,10 +4889,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	if (from_inpcbfree == SCTP_NORMAL_PROC) {
 		atomic_add_int(&stcb->asoc.refcnt, 1);
 
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_INP_INFO_WLOCK();
 		SCTP_INP_WLOCK(inp);
 		SCTP_TCB_LOCK(stcb);
+		SCTP_TCB_SEND_LOCK(stcb);
 	}
 	/* Double check the GONE flag */
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
@@ -4938,6 +4943,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_INP_INFO_WUNLOCK();
 			SCTP_INP_WUNLOCK(inp);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		return (0);
 	}
@@ -4981,7 +4987,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	 * in case.
 	 */
 	/* anything on the wheel needs to be removed */
-	SCTP_TCB_SEND_LOCK(stcb);
 	for (i = 0; i < asoc->streamoutcnt; i++) {
 		struct sctp_stream_out *outs;
 
@@ -5012,7 +5017,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
 		}
 	}
-	SCTP_TCB_SEND_UNLOCK(stcb);
 	/* sa_ignore FREED_MEMORY */
 	TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
 		TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
@@ -5214,6 +5218,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	/* Insert new items here :> */
 
 	/* Get rid of LOCK */
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	SCTP_TCB_UNLOCK(stcb);
 	SCTP_TCB_LOCK_DESTROY(stcb);
 	SCTP_TCB_SEND_LOCK_DESTROY(stcb);

Modified: releng/11.3/sys/netinet/sctp_structs.h
==============================================================================
--- releng/11.3/sys/netinet/sctp_structs.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctp_structs.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -535,6 +535,7 @@ struct sctp_stream_queue_pending {
 	uint8_t sender_all_done;
 	uint8_t put_last_out;
 	uint8_t discard_rest;
+	uint8_t processing;
 };
 
 /*

Modified: releng/11.3/sys/netinet/sctputil.c
==============================================================================
--- releng/11.3/sys/netinet/sctputil.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctputil.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -3858,7 +3858,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb
 }
 
 void
-sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
+sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -3884,9 +3884,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 		return;
 	}
 	/* now through all the gunk freeing chunks */
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_LOCK(stcb);
-	}
 	/* sent queue SHOULD be empty */
 	TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
 		TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
@@ -3963,10 +3960,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 			/* sa_ignore FREED_MEMORY */
 		}
 	}
-
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_UNLOCK(stcb);
-	}
 }
 
 void
@@ -3990,8 +3983,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t
 	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
 		return;
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
+	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	/* Tell them we lost the asoc */
-	sctp_report_all_outbound(stcb, error, 0, so_locked);
+	sctp_report_all_outbound(stcb, error, so_locked);
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	if (from_peer) {
 		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
 	} else {
@@ -4023,7 +4019,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct 
 	if (stcb != NULL) {
 		/* We have a TCB to abort, send notification too */
 		sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 		/* Ok, now lets free it */
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 		so = SCTP_INP_SO(inp);
@@ -4133,8 +4128,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, stru
 			}
 		}
 		return;
-	} else {
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	}
 	/* notify the peer */
 	sctp_send_abort_tcb(stcb, op_err, so_locked);

Modified: releng/11.3/sys/netinet/sctputil.h
==============================================================================
--- releng/11.3/sys/netinet/sctputil.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.3/sys/netinet/sctputil.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -163,7 +163,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *ol
 void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
 
 void
-sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
+sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif

Modified: releng/11.4/sys/netinet/sctp_input.c
==============================================================================
--- releng/11.4/sys/netinet/sctp_input.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctp_input.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -846,7 +846,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
 	SCTP_TCB_LOCK(stcb);
 	atomic_subtract_int(&stcb->asoc.refcnt, 1);
 #endif
-	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
 	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -1995,7 +1994,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphle
 		/* send up all the data */
 		SCTP_TCB_SEND_LOCK(stcb);
 
-		sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
+		sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED);
 		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 			stcb->asoc.strmout[i].chunks_on_queues = 0;
 #if defined(SCTP_DETAILED_STR_STATS)

Modified: releng/11.4/sys/netinet/sctp_output.c
==============================================================================
--- releng/11.4/sys/netinet/sctp_output.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctp_output.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -13202,11 +13202,10 @@ skip_preblock:
 			error = EINVAL;
 			goto out;
 		}
-		SCTP_TCB_SEND_UNLOCK(stcb);
-
 		strm = &stcb->asoc.strmout[srcv->sinfo_stream];
 		if (strm->last_msg_incomplete == 0) {
 	do_a_copy_in:
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
 			if (error) {
 				goto out;
@@ -13232,13 +13231,11 @@ skip_preblock:
 			if (sinfo_flags & SCTP_UNORDERED) {
 				SCTP_STAT_INCR(sctps_sends_with_unord);
 			}
+			sp->processing = 1;
 			TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
 			stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 		} else {
-			SCTP_TCB_SEND_LOCK(stcb);
 			sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 			if (sp == NULL) {
 				/* ???? Huh ??? last msg is gone */
 #ifdef INVARIANTS
@@ -13250,7 +13247,16 @@ skip_preblock:
 				goto do_a_copy_in;
 
 			}
+			if (sp->processing) {
+				SCTP_TCB_SEND_UNLOCK(stcb);
+				SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+				error = EINVAL;
+				goto out;
+			} else {
+				sp->processing = 1;
+			}
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		while (uio->uio_resid > 0) {
 			/* How much room do we have? */
 			struct mbuf *new_tail, *mm;
@@ -13275,20 +13281,29 @@ skip_preblock:
 					if (mm) {
 						sctp_m_freem(mm);
 					}
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
 				/* Update the mbuf and count */
 				SCTP_TCB_SEND_LOCK(stcb);
-				if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+				    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 					/*
 					 * we need to get out. Peer probably
 					 * aborted.
 					 */
 					sctp_m_freem(mm);
-					if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) {
+					if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) {
 						SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
 						error = ECONNRESET;
 					}
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
 					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
@@ -13348,6 +13363,11 @@ skip_preblock:
 			/* wait for space now */
 			if (non_blocking) {
 				/* Non-blocking io in place out */
+				SCTP_TCB_SEND_LOCK(stcb);
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto skip_out_eof;
 			}
 			/* What about the INIT, send it maybe */
@@ -13471,6 +13491,11 @@ skip_preblock:
 						}
 					}
 					SOCKBUF_UNLOCK(&so->so_snd);
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out_unlocked;
 				}
 
@@ -13480,12 +13505,19 @@ skip_preblock:
 				}
 			}
 			SOCKBUF_UNLOCK(&so->so_snd);
+			SCTP_TCB_SEND_LOCK(stcb);
 			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto out_unlocked;
 			}
+			SCTP_TCB_SEND_UNLOCK(stcb);
 		}
 		SCTP_TCB_SEND_LOCK(stcb);
-		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+		if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+		    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 			SCTP_TCB_SEND_UNLOCK(stcb);
 			goto out_unlocked;
 		}
@@ -13501,6 +13533,7 @@ skip_preblock:
 				strm->last_msg_incomplete = 0;
 				asoc->stream_locked = 0;
 			}
+			sp->processing = 0;
 		} else {
 			SCTP_PRINTF("Huh no sp TSNH?\n");
 			strm->last_msg_incomplete = 0;

Modified: releng/11.4/sys/netinet/sctp_pcb.c
==============================================================================
--- releng/11.4/sys/netinet/sctp_pcb.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctp_pcb.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -4725,6 +4725,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 		/* there is no asoc, really TSNH :-0 */
 		return (1);
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
 	if (stcb->asoc.alternate) {
 		sctp_free_remote_addr(stcb->asoc.alternate);
 		stcb->asoc.alternate = NULL;
@@ -4759,6 +4760,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			/* nope, reader or writer in the way */
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 			/* no asoc destroyed */
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			SCTP_TCB_UNLOCK(stcb);
 #ifdef SCTP_LOG_CLOSING
 			sctp_log_closing(inp, stcb, 8);
@@ -4827,6 +4829,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
 		    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
@@ -4860,10 +4863,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	if (from_inpcbfree == SCTP_NORMAL_PROC) {
 		atomic_add_int(&stcb->asoc.refcnt, 1);
 
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_INP_INFO_WLOCK();
 		SCTP_INP_WLOCK(inp);
 		SCTP_TCB_LOCK(stcb);
+		SCTP_TCB_SEND_LOCK(stcb);
 	}
 	/* Double check the GONE flag */
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
@@ -4911,6 +4916,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_INP_INFO_WUNLOCK();
 			SCTP_INP_WUNLOCK(inp);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		return (0);
 	}
@@ -4942,7 +4948,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	 * in case.
 	 */
 	/* anything on the wheel needs to be removed */
-	SCTP_TCB_SEND_LOCK(stcb);
 	for (i = 0; i < asoc->streamoutcnt; i++) {
 		struct sctp_stream_out *outs;
 
@@ -4973,7 +4978,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
 		}
 	}
-	SCTP_TCB_SEND_UNLOCK(stcb);
 	/* sa_ignore FREED_MEMORY */
 	TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
 		TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
@@ -5175,6 +5179,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	/* Insert new items here :> */
 
 	/* Get rid of LOCK */
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	SCTP_TCB_UNLOCK(stcb);
 	SCTP_TCB_LOCK_DESTROY(stcb);
 	SCTP_TCB_SEND_LOCK_DESTROY(stcb);

Modified: releng/11.4/sys/netinet/sctp_structs.h
==============================================================================
--- releng/11.4/sys/netinet/sctp_structs.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctp_structs.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -535,6 +535,7 @@ struct sctp_stream_queue_pending {
 	uint8_t sender_all_done;
 	uint8_t put_last_out;
 	uint8_t discard_rest;
+	uint8_t processing;
 };
 
 /*

Modified: releng/11.4/sys/netinet/sctputil.c
==============================================================================
--- releng/11.4/sys/netinet/sctputil.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctputil.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -3921,7 +3921,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb
 }
 
 void
-sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
+sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -3947,9 +3947,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 		return;
 	}
 	/* now through all the gunk freeing chunks */
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_LOCK(stcb);
-	}
 	/* sent queue SHOULD be empty */
 	TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
 		TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
@@ -4026,10 +4023,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 			/* sa_ignore FREED_MEMORY */
 		}
 	}
-
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_UNLOCK(stcb);
-	}
 }
 
 void
@@ -4053,8 +4046,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t
 	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
 		return;
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
+	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	/* Tell them we lost the asoc */
-	sctp_report_all_outbound(stcb, error, 0, so_locked);
+	sctp_report_all_outbound(stcb, error, so_locked);
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	if (from_peer) {
 		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
 	} else {
@@ -4086,7 +4082,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct 
 	if (stcb != NULL) {
 		/* We have a TCB to abort, send notification too */
 		sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 		/* Ok, now lets free it */
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 		so = SCTP_INP_SO(inp);
@@ -4196,8 +4191,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, stru
 			}
 		}
 		return;
-	} else {
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	}
 	/* notify the peer */
 	sctp_send_abort_tcb(stcb, op_err, so_locked);

Modified: releng/11.4/sys/netinet/sctputil.h
==============================================================================
--- releng/11.4/sys/netinet/sctputil.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/11.4/sys/netinet/sctputil.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -166,7 +166,7 @@ void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
 void sctp_stop_association_timers(struct sctp_tcb *, bool);
 
 void
-sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
+sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif

Modified: releng/12.1/sys/netinet/sctp_input.c
==============================================================================
--- releng/12.1/sys/netinet/sctp_input.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctp_input.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -841,7 +841,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
 	SCTP_TCB_LOCK(stcb);
 	atomic_subtract_int(&stcb->asoc.refcnt, 1);
 #endif
-	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
 	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -1987,7 +1986,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphle
 		/* send up all the data */
 		SCTP_TCB_SEND_LOCK(stcb);
 
-		sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
+		sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED);
 		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 			stcb->asoc.strmout[i].chunks_on_queues = 0;
 #if defined(SCTP_DETAILED_STR_STATS)

Modified: releng/12.1/sys/netinet/sctp_output.c
==============================================================================
--- releng/12.1/sys/netinet/sctp_output.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctp_output.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -13207,11 +13207,10 @@ skip_preblock:
 			error = EINVAL;
 			goto out;
 		}
-		SCTP_TCB_SEND_UNLOCK(stcb);
-
 		strm = &stcb->asoc.strmout[srcv->sinfo_stream];
 		if (strm->last_msg_incomplete == 0) {
 	do_a_copy_in:
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
 			if (error) {
 				goto out;
@@ -13237,13 +13236,11 @@ skip_preblock:
 			if (sinfo_flags & SCTP_UNORDERED) {
 				SCTP_STAT_INCR(sctps_sends_with_unord);
 			}
+			sp->processing = 1;
 			TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
 			stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 		} else {
-			SCTP_TCB_SEND_LOCK(stcb);
 			sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
-			SCTP_TCB_SEND_UNLOCK(stcb);
 			if (sp == NULL) {
 				/* ???? Huh ??? last msg is gone */
 #ifdef INVARIANTS
@@ -13255,7 +13252,16 @@ skip_preblock:
 				goto do_a_copy_in;
 
 			}
+			if (sp->processing) {
+				SCTP_TCB_SEND_UNLOCK(stcb);
+				SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+				error = EINVAL;
+				goto out;
+			} else {
+				sp->processing = 1;
+			}
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		while (uio->uio_resid > 0) {
 			/* How much room do we have? */
 			struct mbuf *new_tail, *mm;
@@ -13280,20 +13286,29 @@ skip_preblock:
 					if (mm) {
 						sctp_m_freem(mm);
 					}
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
 				/* Update the mbuf and count */
 				SCTP_TCB_SEND_LOCK(stcb);
-				if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+				    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 					/*
 					 * we need to get out. Peer probably
 					 * aborted.
 					 */
 					sctp_m_freem(mm);
-					if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) {
+					if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) {
 						SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
 						error = ECONNRESET;
 					}
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
 					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out;
 				}
@@ -13353,6 +13368,11 @@ skip_preblock:
 			/* wait for space now */
 			if (non_blocking) {
 				/* Non-blocking io in place out */
+				SCTP_TCB_SEND_LOCK(stcb);
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto skip_out_eof;
 			}
 			/* What about the INIT, send it maybe */
@@ -13476,6 +13496,11 @@ skip_preblock:
 						}
 					}
 					SOCKBUF_UNLOCK(&so->so_snd);
+					SCTP_TCB_SEND_LOCK(stcb);
+					if (sp != NULL) {
+						sp->processing = 0;
+					}
+					SCTP_TCB_SEND_UNLOCK(stcb);
 					goto out_unlocked;
 				}
 
@@ -13485,12 +13510,19 @@ skip_preblock:
 				}
 			}
 			SOCKBUF_UNLOCK(&so->so_snd);
+			SCTP_TCB_SEND_LOCK(stcb);
 			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+				if (sp != NULL) {
+					sp->processing = 0;
+				}
+				SCTP_TCB_SEND_UNLOCK(stcb);
 				goto out_unlocked;
 			}
+			SCTP_TCB_SEND_UNLOCK(stcb);
 		}
 		SCTP_TCB_SEND_LOCK(stcb);
-		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+		if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+		    (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
 			SCTP_TCB_SEND_UNLOCK(stcb);
 			goto out_unlocked;
 		}
@@ -13506,6 +13538,7 @@ skip_preblock:
 				strm->last_msg_incomplete = 0;
 				asoc->stream_locked = 0;
 			}
+			sp->processing = 0;
 		} else {
 			SCTP_PRINTF("Huh no sp TSNH?\n");
 			strm->last_msg_incomplete = 0;

Modified: releng/12.1/sys/netinet/sctp_pcb.c
==============================================================================
--- releng/12.1/sys/netinet/sctp_pcb.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctp_pcb.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -4726,6 +4726,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 		/* there is no asoc, really TSNH :-0 */
 		return (1);
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
 	if (stcb->asoc.alternate) {
 		sctp_free_remote_addr(stcb->asoc.alternate);
 		stcb->asoc.alternate = NULL;
@@ -4760,6 +4761,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			/* nope, reader or writer in the way */
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 			/* no asoc destroyed */
+			SCTP_TCB_SEND_UNLOCK(stcb);
 			SCTP_TCB_UNLOCK(stcb);
 #ifdef SCTP_LOG_CLOSING
 			sctp_log_closing(inp, stcb, 8);
@@ -4857,6 +4859,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
 			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
 		    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
@@ -4890,10 +4893,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	if (from_inpcbfree == SCTP_NORMAL_PROC) {
 		atomic_add_int(&stcb->asoc.refcnt, 1);
 
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_INP_INFO_WLOCK();
 		SCTP_INP_WLOCK(inp);
 		SCTP_TCB_LOCK(stcb);
+		SCTP_TCB_SEND_LOCK(stcb);
 	}
 	/* Double check the GONE flag */
 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
@@ -4941,6 +4946,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			SCTP_INP_INFO_WUNLOCK();
 			SCTP_INP_WUNLOCK(inp);
 		}
+		SCTP_TCB_SEND_UNLOCK(stcb);
 		SCTP_TCB_UNLOCK(stcb);
 		return (0);
 	}
@@ -4984,7 +4990,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	 * in case.
 	 */
 	/* anything on the wheel needs to be removed */
-	SCTP_TCB_SEND_LOCK(stcb);
 	for (i = 0; i < asoc->streamoutcnt; i++) {
 		struct sctp_stream_out *outs;
 
@@ -5015,7 +5020,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 			sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
 		}
 	}
-	SCTP_TCB_SEND_UNLOCK(stcb);
 	/* sa_ignore FREED_MEMORY */
 	TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
 		TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
@@ -5217,6 +5221,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tc
 	/* Insert new items here :> */
 
 	/* Get rid of LOCK */
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	SCTP_TCB_UNLOCK(stcb);
 	SCTP_TCB_LOCK_DESTROY(stcb);
 	SCTP_TCB_SEND_LOCK_DESTROY(stcb);

Modified: releng/12.1/sys/netinet/sctp_structs.h
==============================================================================
--- releng/12.1/sys/netinet/sctp_structs.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctp_structs.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -537,6 +537,7 @@ struct sctp_stream_queue_pending {
 	uint8_t sender_all_done;
 	uint8_t put_last_out;
 	uint8_t discard_rest;
+	uint8_t processing;
 };
 
 /*

Modified: releng/12.1/sys/netinet/sctputil.c
==============================================================================
--- releng/12.1/sys/netinet/sctputil.c	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctputil.c	Wed Sep  2 16:24:32 2020	(r365256)
@@ -3870,7 +3870,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb
 }
 
 void
-sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
+sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -3896,9 +3896,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 		return;
 	}
 	/* now through all the gunk freeing chunks */
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_LOCK(stcb);
-	}
 	/* sent queue SHOULD be empty */
 	TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
 		TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
@@ -3975,10 +3972,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16
 			/* sa_ignore FREED_MEMORY */
 		}
 	}
-
-	if (holds_lock == 0) {
-		SCTP_TCB_SEND_UNLOCK(stcb);
-	}
 }
 
 void
@@ -4002,8 +3995,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t
 	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
 		return;
 	}
+	SCTP_TCB_SEND_LOCK(stcb);
+	SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	/* Tell them we lost the asoc */
-	sctp_report_all_outbound(stcb, error, 0, so_locked);
+	sctp_report_all_outbound(stcb, error, so_locked);
+	SCTP_TCB_SEND_UNLOCK(stcb);
 	if (from_peer) {
 		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
 	} else {
@@ -4035,7 +4031,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct 
 	if (stcb != NULL) {
 		/* We have a TCB to abort, send notification too */
 		sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 		/* Ok, now lets free it */
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 		so = SCTP_INP_SO(inp);
@@ -4145,8 +4140,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, stru
 			}
 		}
 		return;
-	} else {
-		SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
 	}
 	/* notify the peer */
 	sctp_send_abort_tcb(stcb, op_err, so_locked);

Modified: releng/12.1/sys/netinet/sctputil.h
==============================================================================
--- releng/12.1/sys/netinet/sctputil.h	Wed Sep  2 16:23:15 2020	(r365255)
+++ releng/12.1/sys/netinet/sctputil.h	Wed Sep  2 16:24:32 2020	(r365256)
@@ -165,7 +165,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *ol
 void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
 
 void
-sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
+sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif



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