From nobody Fri Sep 15 17:47:32 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 4RnM8h6qrYz4tSMD; Fri, 15 Sep 2023 17:47:32 +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 4RnM8h6NlSz3KFN; Fri, 15 Sep 2023 17:47:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1694800052; 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=nIsOdxzV5cTHWV+EhqZ09oR6+FVwC1wZuyIqvTt9YCY=; b=fMZaPT+I2TZpm88gXy9FVcJiUK8Ej1NQF1Sbc2oFEeSLk9mXJoMOVp161SQflQFGIQeKft k3ipeXnF+iwMYLEie1Rv17Lz0o1c++QUsUuvFPgXoss+4LlT4K/R/Nl45h2bqYmvCrtmOU 300MvBz/oRXSpuZ5h5orFYujDV8jnKRdEFocbz9IOK2JoPaUeGq4rht+1OadIcy5geKUPT mUIaw3bgQ3sjw9XEGO7ASA855PpP/yGBA68e85C6lUFufw5HmbkovAK9NGfMKbeg7oS53P Lro6TWUz1leQ/jVKPFDwozh1DWJ3z6jwRteaxY1i0y8Hx/zZjubAO8k3evJyHQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1694800052; a=rsa-sha256; cv=none; b=jV7tl/SKAas+mJDA7OXXz6SiipTSBU5G9+yFrbPtk/mebINh3ethA0mh4j7q/DIZ99d8bb cF5QEIFg3ptqVUj96Cg0tIJZFsWhJGLdf3I9tmwArusHzgS31W+7JHkgdBkQmIXu7weAKX QlDpCFmzsPqUdG7XCsATxphJ8xFOzzryZdI8yMK3LISZ43na4L1T2NyeQQI1wS2kTJwDou VAp92yN/yzVOkXhywC/3dHkULyNRwta1WaqK2PHdKWFb64eVN2HzklWA8o7ymJVA1oI4Z6 aDc2kvHix5rY/6ls5viCJHTWvWDf/niduGvA7GI8TiSTNqh9C8wWLPE5gr17ZA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1694800052; 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=nIsOdxzV5cTHWV+EhqZ09oR6+FVwC1wZuyIqvTt9YCY=; b=Z4kQqUST6ME8H45eZxK32+EB/yHcp9LUReWBYcFMD656gWuIqjxIPfOqAsAaZ3R9AWpdZL bD73OPCz7RMdQ2AcIBWQoH8V0gI8mgD0S/HEYJngRzfPS7vFIydJGVGJS9cHnbueRdaUNz CblCWizcu2uXv2PGHIhbjiH3CUwzN/5EShv0Fu/CYLswIAJbAIZmcYtpp3cm6aWhyBKQ8C +HImsGcAmDUZ/plQwd/oASFnE9zWPYbjOnK8d1M319VmCjvnL20X0+wBTfXimTrI8T5dMo mWeMespDLIj6zI03NfXJs7dBQXrUd/opEgxsVx0bDBZq48NKU64AyotPwntAow== 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 4RnM8h5SRGzZ1B; Fri, 15 Sep 2023 17:47:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 38FHlWB8056943; Fri, 15 Sep 2023 17:47:32 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 38FHlWdd056940; Fri, 15 Sep 2023 17:47:32 GMT (envelope-from git) Date: Fri, 15 Sep 2023 17:47:32 GMT Message-Id: <202309151747.38FHlWdd056940@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: c4e047ab6eb1 - stable/14 - sctp: improve shutting down the read side of a socket 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/14 X-Git-Reftype: branch X-Git-Commit: c4e047ab6eb15d27f95f46ccf12d55c46d30debd Auto-Submitted: auto-generated The branch stable/14 has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=c4e047ab6eb15d27f95f46ccf12d55c46d30debd commit c4e047ab6eb15d27f95f46ccf12d55c46d30debd Author: Michael Tuexen AuthorDate: 2023-09-12 23:33:54 +0000 Commit: Michael Tuexen CommitDate: 2023-09-15 17:45:42 +0000 sctp: improve shutting down the read side of a socket When shutdown(..., SHUT_RD) or shutdown(..., SHUT_RDWR) is called, really clean up the read queue and issue an ungraceful shutdown if user messages are affected. Reported by: syzbot+d4e1d30d578891245f59@syzkaller.appspotmail.com --- sys/netinet/sctp_usrreq.c | 90 ++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 52b4faf48574..02bb87578528 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -777,52 +777,76 @@ sctp_disconnect(struct socket *so) int sctp_flush(struct socket *so, int how) { - /* - * We will just clear out the values and let subsequent close clear - * out the data, if any. Note if the user did a shutdown(SHUT_RD) - * they will not be able to read the data, the socket will block - * that from happening. - */ + struct epoch_tracker et; + struct sctp_tcb *stcb; + struct sctp_queued_to_read *control, *ncontrol; struct sctp_inpcb *inp; + struct mbuf *m, *op_err; + bool need_to_abort = false; + /* + * For 1-to-1 style sockets, flush the read queue and trigger an + * ungraceful shutdown of the association, if and only if user + * messages are lost. Loosing notifications does not need to be + * signalled to the peer. + */ + if (how == PRU_FLUSH_WR) { + /* This function is only relevant for the read directions. */ + return (0); + } inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); } - SCTP_INP_RLOCK(inp); - /* For the 1 to many model this does nothing */ + SCTP_INP_WLOCK(inp); if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) { - SCTP_INP_RUNLOCK(inp); + /* For 1-to-many style sockets this function does nothing. */ + SCTP_INP_WUNLOCK(inp); return (0); } - SCTP_INP_RUNLOCK(inp); - if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) { - /* - * First make sure the sb will be happy, we don't use these - * except maybe the count - */ - SCTP_INP_WLOCK(inp); - SCTP_INP_READ_LOCK(inp); - inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ; - SCTP_INP_READ_UNLOCK(inp); + stcb = LIST_FIRST(&inp->sctp_asoc_list); + if (stcb == NULL) { SCTP_INP_WUNLOCK(inp); - SOCK_LOCK(so); - KASSERT(!SOLISTENING(so), - ("sctp_flush: called on listening socket %p", so)); - SCTP_SB_CLEAR(so->so_rcv); - SOCK_UNLOCK(so); + return (ENOTCONN); } - if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) { - /* - * First make sure the sb will be happy, we don't use these - * except maybe the count - */ - SOCK_LOCK(so); - KASSERT(!SOLISTENING(so), - ("sctp_flush: called on listening socket %p", so)); - SOCK_UNLOCK(so); + SCTP_TCB_LOCK(stcb); + SCTP_INP_READ_LOCK(inp); + inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ; + SOCK_LOCK(so); + TAILQ_FOREACH_SAFE(control, &inp->read_queue, next, ncontrol) { + if ((control->spec_flags & M_NOTIFICATION) == 0) { + need_to_abort = true; + } + TAILQ_REMOVE(&inp->read_queue, control, next); + control->on_read_q = 0; + for (m = control->data; m; m = SCTP_BUF_NEXT(m)) { + sctp_sbfree(control, control->stcb, &so->so_rcv, m); + } + if (control->on_strm_q == 0) { + sctp_free_remote_addr(control->whoFrom); + if (control->data) { + sctp_m_freem(control->data); + control->data = NULL; + } + sctp_free_a_readq(stcb, control); + } else { + stcb->asoc.size_on_all_streams += control->length; + } } + SOCK_UNLOCK(so); + SCTP_INP_READ_UNLOCK(inp); + if (need_to_abort) { + inp->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6; + SCTP_INP_WUNLOCK(inp); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); + NET_EPOCH_ENTER(et); + sctp_abort_an_association(inp, stcb, op_err, false, SCTP_SO_LOCKED); + NET_EPOCH_EXIT(et); + return (ECONNABORTED); + } + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_WUNLOCK(inp); return (0); }