From nobody Wed Feb 1 23:32:51 2023 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 4P6dWS1yNYz3cLMc; Wed, 1 Feb 2023 23:32:52 +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 4P6dWS1DS5z3Lv9; Wed, 1 Feb 2023 23:32:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1675294372; 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=qUht1eLBgmpb7SKMQria38BCbUq/ybRi7wCEFsnJ/MY=; b=k08oqKHfJ2VKzMpm2q/A9Zq8A5F3PWCa6vu4R7Y15pP8cFXCJjOBPUmUPvHNSTANBba9po VPbO3qq1IqgJ5OuUIcKYHk8bWeR3MLoRBKhtSE6MMDlIT2gfKCcyXVJPDSagrshAhsoK/K tu+nfr++wXmI5qQsgKeWejmRyqT8zZxMeGIUlMVd7sKWqFNi0DovwQmS76KMngimxATG+n Y4m4KtCKdC+iydo5rTY1Z2XbCwCf+3E5aOiXWRmBmR8AqoUd9Z3PW5ntZacPmpZghmNk1m /dIvllPe+8m7g27m48v/+T7dw5RCW+ylwajyrUvJDzCRxfqBqY5sMYgjbA7oLA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1675294372; 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=qUht1eLBgmpb7SKMQria38BCbUq/ybRi7wCEFsnJ/MY=; b=HwcMDwASlqevnq6WTwcOo5KumErXN/HvKOkWCDGi+HI58utl89RGxz/UnNDPzsaiGnGJfv KDe3aerO0AcEFBen4q8imUfcbHh2+qjKO3M193CiSWpU8jhi5P5CxoA1CqewZB9i27ZXi9 +YQKHk8IZHASA51IEa3T7tyt5HgfKF/+PL85dMnD6NvCzayMPtE7eArAo9WRYSUwzZB41t u+slubUNpOmH1XRpJHxVGpVGeFveiYteaW3DsPxxFigvdRryCvi3+V4IS42uQMXPVnAMqA qGsVPUdLZE6V8ksVHT4hMsm4DknPjofG3fhluHrYjXD9oya6J/Uhv65zkSiO2Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1675294372; a=rsa-sha256; cv=none; b=YOPKD6jfEMf+7bmL8XNjBSX+4NX+HFWX9FsFDMtfe1EUCivzGQU8WGPw7t5F8crYXXcx68 ltUvwBIhI4ShBJaC/F4PTSLq7ztFT9g5cBszS0zQtQoUMaXwLtYIXyJXL2CeSaeSlEn+TZ PbJuXGqFCqs1tq/baml+9IS7G897ZM0blzOlHL9x6ik50sqtPf+YfhxtIbwZn5gOxyvFNE VPzmX2fsp6w65t6CDga/S5vIUIi7mgsYGS4ksr/cX2Wi4+kYOSOS1nMH2gGSxRG/5vxuwj ylp/QkePmtrCU01cWL7Dusskglth8vPqGUTkROn42Y2lKOpYse4gkyiv0H8KhQ== 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 4P6dWS0GXQzYQ7; Wed, 1 Feb 2023 23:32:52 +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 311NWpPp075749; Wed, 1 Feb 2023 23:32:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 311NWpJn075747; Wed, 1 Feb 2023 23:32:51 GMT (envelope-from git) Date: Wed, 1 Feb 2023 23:32:51 GMT Message-Id: <202302012332.311NWpJn075747@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Michael Tuexen Subject: git: cb15bf432533 - stable/13 - 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/stable/13 X-Git-Reftype: branch X-Git-Commit: cb15bf432533997e47fad2c4375c19e6826f4b2b Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=cb15bf432533997e47fad2c4375c19e6826f4b2b commit cb15bf432533997e47fad2c4375c19e6826f4b2b Author: Michael Tuexen AuthorDate: 2022-08-08 10:53:42 +0000 Commit: Michael Tuexen CommitDate: 2023-02-01 23:32:26 +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 (cherry picked from commit bb995f2ef0e75e2e9cc784fc36fc3eb02d3e3113) --- 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 6736f7e9f948..6ea139795be0 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;