diff options
author | Michael Tuexen <tuexen@FreeBSD.org> | 2022-05-28 15:40:17 +0000 |
---|---|---|
committer | Michael Tuexen <tuexen@FreeBSD.org> | 2023-02-01 22:59:22 +0000 |
commit | f25aa6dc17d761c4cf2727e630f5aee128f10403 (patch) | |
tree | 4fca213cc81967c2f4a4e4c8b121c83f3428624b | |
parent | 7e995a75013c11adc1208d9741fca3a09a54be43 (diff) | |
download | src-f25aa6dc17d761c4cf2727e630f5aee128f10403.tar.gz src-f25aa6dc17d761c4cf2727e630f5aee128f10403.zip |
sctp: improve handling of send() when association is shutdown
Accept send() calls only when the association is not being
shut down or the expicit message EOR mode is used and the
application provides follow-up data.
Reported by: syzbot+341e9ebd9d24ca7dc62a@syzkaller.appspotmail.com
(cherry picked from commit 64b297e803bd8123bfef3fecaa1f8ceae9eea0e6)
-rw-r--r-- | sys/netinet/sctp_output.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 45a27e5d2e1d..dfad4e5dfa08 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -6348,8 +6348,8 @@ sctp_msg_append(struct sctp_tcb *stcb, (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || (stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING)) { /* got data while shutting down */ - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); - error = ECONNRESET; + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EPIPE); + error = EPIPE; goto out_now; } sctp_alloc_a_strmoq(stcb, sp); @@ -12291,20 +12291,10 @@ sctp_copy_it_in(struct sctp_tcb *stcb, * sb is locked however. When data is copied the protocol processing * should be enabled since this is a slower operation... */ - struct sctp_stream_queue_pending *sp = NULL; + struct sctp_stream_queue_pending *sp; int resv_in_first; *error = 0; - /* Now can we send this? */ - if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) || - (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || - (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || - (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { - /* got data while shutting down */ - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET); - *error = ECONNRESET; - goto out_now; - } sctp_alloc_a_strmoq(stcb, sp); if (sp == NULL) { SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM); @@ -12923,13 +12913,6 @@ sctp_lower_sosend(struct socket *so, KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, ("Association was aborted")); - if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) || - (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || - (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || - (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { - error = EPIPE; - goto out_unlocked; - } /* Ok, we will attempt a msgsnd :> */ if (p != NULL) { p->td_ru.ru_msgsnd++; @@ -13084,6 +13067,28 @@ skip_preblock: if (error != 0) { goto out; } + /* + * Reject the sending of a new user message, if the + * association is about to be shut down. + */ + if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) || + (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED) || + (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || + (asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) { + if (sp->data != 0) { + sctp_m_freem(sp->data); + sp->data = NULL; + sp->tail_mbuf = NULL; + sp->length = 0; + } + if (sp->net != NULL) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } + sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); + error = EPIPE; + goto out_unlocked; + } /* The out streams might be reallocated. */ strm = &asoc->strmout[srcv->sinfo_stream]; if (sp->msg_is_complete) { |