aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2022-05-28 15:40:17 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2023-02-01 22:59:22 +0000
commitf25aa6dc17d761c4cf2727e630f5aee128f10403 (patch)
tree4fca213cc81967c2f4a4e4c8b121c83f3428624b
parent7e995a75013c11adc1208d9741fca3a09a54be43 (diff)
downloadsrc-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.c45
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) {