From nobody Wed Aug 10 10:09:21 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4M2lz6255Bz4YcHq; Wed, 10 Aug 2022 10:09:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4M2lz61ZGzz3CwR; Wed, 10 Aug 2022 10:09:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660126162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CHCavMtEuZTJ3TMoSWdVr/lP4be50CC31IVoDcwhdVk=; b=H0VIg/YGXwDQ6xFjGFXei1B2zkbSZfpU1zaErMG9nIEzrbp6EAzwAiZLMVShmAoU0Apxss sja1N5fBU4+1JrlLAFi/DLi1V4DKnAxvCtVFLhQhwiCLVlr7uDaG+qqRrRpxKz7YYa1RhY hbsDMaaIc2XNsu6LXexe0KzmB6PdDfoyr9fR1kkiPg9Ot6kZRA0632vUNoqPyogoWVbPaV RYWmDl4oY6AaWdONEH6Cf88k6LeU4N0l/LO3U8kiB1BHXEEZYdPJ511VgFfN51YK2j+DFF ol6B3DF70EDjrCSOZiPkdZEo/nu8eB+/MpnwglZ0cvSbUbIqOaNpYUiMtXgZzg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4M2lz60J33z16Vf; Wed, 10 Aug 2022 10:09:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 27AA9LvK081292; Wed, 10 Aug 2022 10:09:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 27AA9Lwn081291; Wed, 10 Aug 2022 10:09:21 GMT (envelope-from git) Date: Wed, 10 Aug 2022 10:09:21 GMT Message-Id: <202208101009.27AA9Lwn081291@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Michael Tuexen Subject: git: bb995f2ef0e7 - main - sctp: improve handling of send() calls with no user data` List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tuexen X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: bb995f2ef0e75e2e9cc784fc36fc3eb02d3e3113 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660126162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CHCavMtEuZTJ3TMoSWdVr/lP4be50CC31IVoDcwhdVk=; b=GBoo/O14nRx9EQ8pnOUhoapUv35Vu+6RM58bUznC2doDAjVuRI+RPLceCm+VwxkkfT5T2b HOkfKRK+4xUJMrOHt3VbUs4s1Dys5JN2tXLvEEbOol8Gc8TcQP5AHLBFG2cXi8FSgVsoMN 1BwDC1dqwBpv0TDfQPHO/j/4Xww2zMQtRNPLlG4eLG/W33H/m4OLxcqdMHoPud6tYwAdex kTwoxV/dASkNKVYzrQB1H3reEzi5eUc3tjShvxOYUzzU6+ST32HhcTDRts6lZ16s1QSRSG HF184wOroJi4dF9Jhfqqv1XSMuuryuLRjWYW6RCPfkfjKA0rMJZLBC3SQUY35Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1660126162; a=rsa-sha256; cv=none; b=D9SoXMhNRZLMNSMXnOxdPV765xkXjrIhQj2n2IWMh76UuPU2BQE21YOVs2Y3HgHnAq0P1t 0D1JmBVkFx7J1mIbIR1q6uP2JBInFnjfCZGhHd0qGwv7p0Ue7e3L+v0F9hFvW94brxNPBo Z4N404DCHFgkws9YOccjs66QoMy6bV3zzgqAH4VT2jODmA8hIOSDs0mh48NuPacCqOMxQE BS1Da+yUw/4dB/7Sd9Ao/+SeZw8u+pEvniV8lg8UNzrNHy9h4USt94fJ3gJoJHjHu9ZMnU 4Rz2oH7lGCk7OZnKS/72928nO6y2ZsQuDlSvXYdQzzZawsseyfUrvNTFxCRwiw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=bb995f2ef0e75e2e9cc784fc36fc3eb02d3e3113 commit bb995f2ef0e75e2e9cc784fc36fc3eb02d3e3113 Author: Michael Tuexen AuthorDate: 2022-08-08 10:53:42 +0000 Commit: Michael Tuexen CommitDate: 2022-08-08 10:53:42 +0000 sctp: improve handling of send() calls with no user data` In particular, don't report EAGAIN on send() calls with no user data, which might trigger a KASSERT in asyc IO. Reported by: syzbot+3b4dc5d1d63e9bd01eda@syzkaller.appspotmail.com MFC after: 1 week --- sys/netinet/sctp_output.c | 186 ++++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 88 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 49830676d7eb..feb3fc31561d 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -6342,6 +6342,18 @@ sctp_msg_append(struct sctp_tcb *stcb, error = EINVAL; goto out_now; } + if ((stcb->asoc.strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPEN) && + (stcb->asoc.strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPENING)) { + /* + * Can't queue any data while stream reset is underway. + */ + if (stcb->asoc.strmout[srcv->sinfo_stream].state > SCTP_STREAM_OPEN) { + error = EAGAIN; + } else { + error = EINVAL; + } + goto out_now; + } /* Now can we send this? */ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_SENT) || (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_ACK_SENT) || @@ -12724,83 +12736,6 @@ sctp_lower_sosend(struct socket *so, sinfo_flags |= SCTP_EOF; } } - if (sinfo_flags & SCTP_ADDR_OVER) { - if (addr != NULL) { - net = sctp_findnet(stcb, addr); - } else { - net = NULL; - } - if ((net == NULL) || - ((port != 0) && (port != stcb->rport))) { - error = EINVAL; - goto out_unlocked; - } - } else { - if (asoc->alternate != NULL) { - net = asoc->alternate; - } else { - net = asoc->primary_destination; - } - } - sinfo_stream = sndrcvninfo->sinfo_stream; - /* Is the stream no. valid? */ - if (sinfo_stream >= asoc->streamoutcnt) { - /* Invalid stream number */ - error = EINVAL; - goto out_unlocked; - } - if ((asoc->strmout[sinfo_stream].state != SCTP_STREAM_OPEN) && - (asoc->strmout[sinfo_stream].state != SCTP_STREAM_OPENING)) { - /* - * Can't queue any data while stream reset is underway. - */ - if (asoc->strmout[sinfo_stream].state > SCTP_STREAM_OPEN) { - error = EAGAIN; - } else { - error = EINVAL; - } - goto out_unlocked; - } - if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT)) { - if (sndlen > (ssize_t)asoc->smallest_mtu) { - error = EMSGSIZE; - goto out_unlocked; - } - } - atomic_add_int(&stcb->total_sends, 1); - if (SCTP_SO_IS_NBIO(so) || (flags & (MSG_NBIO | MSG_DONTWAIT)) != 0) { - non_blocking = true; - } - if (non_blocking) { - ssize_t amount; - - inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); - if (user_marks_eor == 0) { - amount = sndlen; - } else { - amount = 1; - } - if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + asoc->sb_send_resv)) || - (asoc->chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { - if ((sndlen > (ssize_t)SCTP_SB_LIMIT_SND(so)) && - (user_marks_eor == 0)) { - error = EMSGSIZE; - } else { - error = EWOULDBLOCK; - } - goto out_unlocked; - } - } - atomic_add_int(&asoc->sb_send_resv, (int)sndlen); - local_soresv = sndlen; - - KASSERT(stcb != NULL, ("stcb is NULL")); - SCTP_TCB_LOCK_ASSERT(stcb); - KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, - ("Association about to be freed")); - KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, - ("Association was aborted")); - /* Are we aborting? */ if (sinfo_flags & SCTP_ABORT) { struct mbuf *mm; @@ -12899,6 +12834,92 @@ sctp_lower_sosend(struct socket *so, goto out_unlocked; } + KASSERT(stcb != NULL, ("stcb is NULL")); + SCTP_TCB_LOCK_ASSERT(stcb); + KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, + ("Association about to be freed")); + KASSERT((asoc->state & SCTP_STATE_WAS_ABORTED) == 0, + ("Association was aborted")); + + if (sinfo_flags & SCTP_ADDR_OVER) { + if (addr != NULL) { + net = sctp_findnet(stcb, addr); + } else { + net = NULL; + } + if ((net == NULL) || + ((port != 0) && (port != stcb->rport))) { + error = EINVAL; + goto out_unlocked; + } + } else { + if (asoc->alternate != NULL) { + net = asoc->alternate; + } else { + net = asoc->primary_destination; + } + } + if (sndlen == 0) { + if (sinfo_flags & SCTP_EOF) { + got_all_of_the_send = true; + goto dataless_eof; + } else { + error = EINVAL; + goto out_unlocked; + } + } + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT)) { + if (sndlen > (ssize_t)asoc->smallest_mtu) { + error = EMSGSIZE; + goto out_unlocked; + } + } + sinfo_stream = sndrcvninfo->sinfo_stream; + /* Is the stream no. valid? */ + if (sinfo_stream >= asoc->streamoutcnt) { + /* Invalid stream number */ + error = EINVAL; + goto out_unlocked; + } + if ((asoc->strmout[sinfo_stream].state != SCTP_STREAM_OPEN) && + (asoc->strmout[sinfo_stream].state != SCTP_STREAM_OPENING)) { + /* + * Can't queue any data while stream reset is underway. + */ + if (asoc->strmout[sinfo_stream].state > SCTP_STREAM_OPEN) { + error = EAGAIN; + } else { + error = EINVAL; + } + goto out_unlocked; + } + atomic_add_int(&stcb->total_sends, 1); + if (SCTP_SO_IS_NBIO(so) || (flags & (MSG_NBIO | MSG_DONTWAIT)) != 0) { + non_blocking = true; + } + if (non_blocking) { + ssize_t amount; + + inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + if (user_marks_eor == 0) { + amount = sndlen; + } else { + amount = 1; + } + if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + asoc->sb_send_resv)) || + (asoc->chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { + if ((sndlen > (ssize_t)SCTP_SB_LIMIT_SND(so)) && + (user_marks_eor == 0)) { + error = EMSGSIZE; + } else { + error = EWOULDBLOCK; + } + goto out_unlocked; + } + } + atomic_add_int(&asoc->sb_send_resv, (int)sndlen); + local_soresv = sndlen; + KASSERT(stcb != NULL, ("stcb is NULL")); SCTP_TCB_LOCK_ASSERT(stcb); KASSERT((asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0, @@ -12910,7 +12931,6 @@ sctp_lower_sosend(struct socket *so, if (p != NULL) { p->td_ru.ru_msgsnd++; } - /* Calculate the maximum we can send */ inqueue_bytes = asoc->total_output_queue_size - (asoc->chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { @@ -13013,16 +13033,6 @@ skip_preblock: * sndlen covers for mbuf case uio_resid covers for the non-mbuf * case NOTE: uio will be null when top/mbuf is passed */ - if (sndlen == 0) { - if (sinfo_flags & SCTP_EOF) { - got_all_of_the_send = true; - goto dataless_eof; - } else { - error = EINVAL; - goto out; - } - } - if (top == NULL) { struct sctp_stream_queue_pending *sp; struct sctp_stream_out *strm;