From nobody Thu Jan 11 12:58:48 2024 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 4T9l951VDDz55ghp; Thu, 11 Jan 2024 12:58:49 +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 4T9l950vZ3z4DkK; Thu, 11 Jan 2024 12:58:49 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1704977929; 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=qugw9W2odbqeXEvLIEAJbZCqsnVom3DIXqPKyeR+tyY=; b=RF8/oKVLPXRYNYhs6vZPEsbaZO3S8vaJj0ZkDJF7RJ3Cozpv3SMz4bcwLC0rR5pAzskXXR iBhHLC/f371enukEy8xZcagsLCB2nWh/8NVDLvyAmAkM0OW+t8RTOtCNP0N1OgM8TtpcO1 u6sMaXE30jX+0bLYqCi08RTZyU/9rOUW1pfWDCCYbgr+3p4GalUmrubdOMWPZfipDzDNIt sgaY7Ipl07wxLnA2ByiRnpTM8wG3YVRcn6k6HkJJ49qZ4gLmsazVTGheCpqm/wdqLprCdo OiXLV6s9nIkQ010ngl9k0ySWkZQS12cWX/fdsTsp2CGBXP38WDyVHhfR0MjZ8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1704977929; 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=qugw9W2odbqeXEvLIEAJbZCqsnVom3DIXqPKyeR+tyY=; b=QOqZGodKr2ALjzm1S2wrY4OX6/nx7j6EN/LAdgtxDMhf2NkR62qy1k2LluGpwO+IXINcPR qHR2AfnDz7pkSyxvOIvvfE9XLanTi98OV7dWwyvh77IqtjQxiFSs2c6xMmV4X6x1MQ87NR 9HVFZGYiqAoO7qQVJX6hDBgziUaIgrdvhkv3i8dTR9dzVdne1oeozSw2wRHRkP4DmY4657 kImF3XozD2zOk1yGV/HlBxi3jmEAt6Li+KNb7eDOpZjo8prKpNqIaiTgeP67BP5EiiJHkj VPC0K/hscV/KpCHk5+BbpR+Xz3WkzvvHSqCC1oAz2sCn1wFlrkgMWpkt+SyF9A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1704977929; a=rsa-sha256; cv=none; b=O20zHyRXSLreIPrdOm/zRzer4k39dKOyR6gkh1y9lb9X7Gfm10exsRJ5tcMqQtXGezyo5x o4AcmpC/KnSxE8Qv8OoDI588Tvk2qRi0NdH0TyjppgJHrgshT+lf8+iZ8gJYbmJXGbUkde 3PmHX7dMlPW5s0TXyqQDZfBmiGqON14n0EKhkPhaJJBTCF8Io8IF9j2fEdXcj+zQ3wGVg3 vmOvb26g06jbh5CwOujNRHTFbs0Sn4yiiTybuE3MfeQxdK1lHFXBgVyZdZubIsP/X5/A/9 /wWEoV+3Y3VkqtbOUfYyQ2MX2xCavZ7l0fZVwt8T1IvFa8ZYJA8TOpInXh/O6A== 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 4T9l947494zJrN; Thu, 11 Jan 2024 12:58:48 +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 40BCwmg1055003; Thu, 11 Jan 2024 12:58:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 40BCwmZ1055000; Thu, 11 Jan 2024 12:58:48 GMT (envelope-from git) Date: Thu, 11 Jan 2024 12:58:48 GMT Message-Id: <202401111258.40BCwmZ1055000@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: e207b7b8b371 - stable/13 - 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/13 X-Git-Reftype: branch X-Git-Commit: e207b7b8b3716fdb64ed5ef10688e0f0cbe954cc Auto-Submitted: auto-generated The branch stable/13 has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=e207b7b8b3716fdb64ed5ef10688e0f0cbe954cc commit e207b7b8b3716fdb64ed5ef10688e0f0cbe954cc Author: Michael Tuexen AuthorDate: 2023-09-12 23:33:54 +0000 Commit: Michael Tuexen CommitDate: 2024-01-11 12:58:11 +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 (cherry picked from commit 81c5f0fac91dfae64205a6c4f9b2a469d1187372) --- 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 a7af1da8624a..9f1a33b5ff2a 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -789,52 +789,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); }