From 404ff76bda3e71da7cb257c04fecc745cb84220c Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Fri, 28 Aug 2020 20:05:18 +0000 Subject: [PATCH] Fix a regression with the explicit EOR mode I introduced in r364268. A short MFC time as discussed with the secteam. Reported by: Taylor Brandstetter MFC after: 1 day --- sys/netinet/sctp_output.c | 47 ++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 7c0b7b253f41..ac258281f138 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -13118,11 +13118,10 @@ sctp_lower_sosend(struct socket *so, 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; @@ -13151,19 +13150,8 @@ sctp_lower_sosend(struct socket *so, 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); - 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); if (sp == NULL) { /* ???? Huh ??? last msg is gone */ #ifdef INVARIANTS @@ -13175,7 +13163,16 @@ sctp_lower_sosend(struct socket *so, 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; @@ -13200,6 +13197,11 @@ sctp_lower_sosend(struct socket *so, 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 */ @@ -13215,6 +13217,9 @@ sctp_lower_sosend(struct socket *so, 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; } @@ -13274,6 +13279,11 @@ sctp_lower_sosend(struct socket *so, /* 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 */ @@ -13401,6 +13411,11 @@ sctp_lower_sosend(struct socket *so, } } SOCKBUF_UNLOCK(&so->so_snd); + SCTP_TCB_SEND_LOCK(stcb); + if (sp != NULL) { + sp->processing = 0; + } + SCTP_TCB_SEND_UNLOCK(stcb); goto out_unlocked; } @@ -13410,9 +13425,15 @@ sctp_lower_sosend(struct socket *so, } } 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) ||