git: 64b297e803bd - main - sctp: improve handling of send() when association is shutdown
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 28 May 2022 16:34:39 UTC
The branch main has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=64b297e803bd8123bfef3fecaa1f8ceae9eea0e6 commit 64b297e803bd8123bfef3fecaa1f8ceae9eea0e6 Author: Michael Tuexen <tuexen@FreeBSD.org> AuthorDate: 2022-05-28 15:40:17 +0000 Commit: Michael Tuexen <tuexen@FreeBSD.org> CommitDate: 2022-05-28 15:40:17 +0000 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 MFC after: 3 days --- sys/netinet/sctp_output.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index b8844fdc0295..3b674ba22666 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); @@ -12293,20 +12293,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); @@ -12925,13 +12915,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++; @@ -13086,6 +13069,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) {