From owner-dev-commits-src-branches@freebsd.org Wed Sep 8 12:41:51 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id C270C67A895; Wed, 8 Sep 2021 12:41:51 +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 4H4MG72jpxz3hWW; Wed, 8 Sep 2021 12:41:51 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 38E4E26181; Wed, 8 Sep 2021 12:41:51 +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 188CfpJl065279; Wed, 8 Sep 2021 12:41:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 188CfpBQ065278; Wed, 8 Sep 2021 12:41:51 GMT (envelope-from git) Date: Wed, 8 Sep 2021 12:41:51 GMT Message-Id: <202109081241.188CfpBQ065278@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: aacbd4dd578e - stable/13 - sctp: Implement sctp_inpcb_bind_locked() MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: aacbd4dd578e472b116814a4b7dcb27850e37df9 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Sep 2021 12:41:51 -0000 The branch stable/13 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=aacbd4dd578e472b116814a4b7dcb27850e37df9 commit aacbd4dd578e472b116814a4b7dcb27850e37df9 Author: Mark Johnston AuthorDate: 2021-09-01 14:04:47 +0000 Commit: Mark Johnston CommitDate: 2021-09-08 12:41:16 +0000 sctp: Implement sctp_inpcb_bind_locked() This will be used by sctp_listen() to avoid dropping locks when performing an implicit bind. No functional change intended. Reviewed by: tuexen Sponsored by: The FreeBSD Foundation (cherry picked from commit 457abbb85794ad8b28d11a7cd44260eabdf3114d) --- sys/netinet/sctp_pcb.c | 53 +++++++++++++++++++++++++++++++++----------------- sys/netinet/sctp_pcb.h | 3 +++ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index fb3b9fe6bdb8..3e517889d171 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -2801,14 +2801,19 @@ sctp_remove_laddr(struct sctp_laddr *laddr) SCTP_DECR_LADDR_COUNT(); } -/* sctp_ifap is used to bypass normal local address validation checks */ +/* + * Bind the socket, with the PCB and global info locks held. Note, if a + * socket address is specified, the PCB lock may be dropped and re-acquired. + * + * sctp_ifap is used to bypass normal local address validation checks. + */ int -sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, +sctp_inpcb_bind_locked(struct sctp_inpcb *inp, struct sockaddr *addr, struct sctp_ifa *sctp_ifap, struct thread *td) { /* bind a ep to a socket address */ struct sctppcbhead *head; - struct sctp_inpcb *inp, *inp_tmp; + struct sctp_inpcb *inp_tmp; struct inpcb *ip_inp; int port_reuse_active = 0; int bindall; @@ -2821,8 +2826,11 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, error = 0; lport = 0; bindall = 1; - inp = (struct sctp_inpcb *)so->so_pcb; - ip_inp = (struct inpcb *)so->so_pcb; + ip_inp = &inp->ip_inp.inp; + + SCTP_INP_INFO_WLOCK_ASSERT(); + SCTP_INP_WLOCK_ASSERT(inp); + #ifdef SCTP_DEBUG if (addr) { SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n", @@ -2831,8 +2839,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); } #endif - SCTP_INP_INFO_WLOCK(); - SCTP_INP_WLOCK(inp); if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { error = EINVAL; /* already did a bind, subsequent binds NOT allowed ! */ @@ -2925,20 +2931,16 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, vrf_id = inp->def_vrf_id; if (lport) { - /* increase our count due to the unlock we do */ - SCTP_INP_INCR_REF(inp); - /* * Did the caller specify a port? if so we must see if an ep * already has this one bound. */ /* got to be root to get at low ports */ - if (ntohs(lport) < IPPORT_RESERVED) { - if ((error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) { - SCTP_INP_DECR_REF(inp); - goto out; - } + if (ntohs(lport) < IPPORT_RESERVED && + (error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) { + goto out; } + SCTP_INP_INCR_REF(inp); SCTP_INP_WUNLOCK(inp); if (bindall) { vrf_id = inp->def_vrf_id; @@ -2962,10 +2964,11 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, port_reuse_active = 1; goto continue_anyway; } + SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); error = EADDRINUSE; SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); - goto out_inp_unlocked; + goto out; } } else { inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); @@ -2988,10 +2991,11 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, port_reuse_active = 1; goto continue_anyway; } + SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); error = EADDRINUSE; SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); - goto out_inp_unlocked; + goto out; } } continue_anyway: @@ -3201,8 +3205,21 @@ continue_anyway: ("%s: inp %p is already bound", __func__, inp)); inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND; out: + return (error); +} + +int +sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, + struct sctp_ifa *sctp_ifap, struct thread *td) +{ + struct sctp_inpcb *inp; + int error; + + inp = so->so_pcb; + SCTP_INP_INFO_WLOCK(); + SCTP_INP_WLOCK(inp); + error = sctp_inpcb_bind_locked(inp, addr, sctp_ifap, td); SCTP_INP_WUNLOCK(inp); -out_inp_unlocked: SCTP_INP_INFO_WUNLOCK(); return (error); } diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index c978e8c72b42..e14c9f39356c 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -526,6 +526,9 @@ struct sctp_inpcb *sctp_pcb_findep(struct sockaddr *, int, int, uint32_t); int sctp_inpcb_bind(struct socket *, struct sockaddr *, struct sctp_ifa *, struct thread *); +int +sctp_inpcb_bind_locked(struct sctp_inpcb *, struct sockaddr *, + struct sctp_ifa *, struct thread *); struct sctp_tcb * sctp_findassociation_addr(struct mbuf *, int,