From owner-svn-src-head@freebsd.org Sat May 5 22:40:41 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5737FFBDA89; Sat, 5 May 2018 22:40:41 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id EF8FE79B3B; Sat, 5 May 2018 22:40:40 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EA76023C67; Sat, 5 May 2018 22:40:40 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w45MeeR6020556; Sat, 5 May 2018 22:40:40 GMT (envelope-from mmacy@FreeBSD.org) Received: (from mmacy@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w45MeeKM020551; Sat, 5 May 2018 22:40:40 GMT (envelope-from mmacy@FreeBSD.org) Message-Id: <201805052240.w45MeeKM020551@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmacy set sender to mmacy@FreeBSD.org using -f From: Matt Macy Date: Sat, 5 May 2018 22:40:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333277 - in head/sys: netinet netinet6 X-SVN-Group: head X-SVN-Commit-Author: mmacy X-SVN-Commit-Paths: in head/sys: netinet netinet6 X-SVN-Commit-Revision: 333277 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 May 2018 22:40:41 -0000 Author: mmacy Date: Sat May 5 22:40:40 2018 New Revision: 333277 URL: https://svnweb.freebsd.org/changeset/base/333277 Log: Currently in_pcbfree will unconditionally wunlock the pcbinfo lock to avoid a LOR on the multicast list lock in the freemoptions routines. As it turns out, tcp_usr_detach can acquire the tcbinfo lock readonly. Trying to wunlock the pcbinfo lock in that context has caused a number of reported crashes. This change unclutters in_pcbfree and moves the handling of wunlock vs runlock of pcbinfo to the freemoptions routine. Reported by: mjg@, bde@, o.hartmann at walstatt.org Approved by: sbruno Modified: head/sys/netinet/in_mcast.c head/sys/netinet/in_pcb.c head/sys/netinet/ip_var.h head/sys/netinet6/in6_mcast.c head/sys/netinet6/in6_var.h Modified: head/sys/netinet/in_mcast.c ============================================================================== --- head/sys/netinet/in_mcast.c Sat May 5 20:16:08 2018 (r333276) +++ head/sys/netinet/in_mcast.c Sat May 5 22:40:40 2018 (r333277) @@ -1639,16 +1639,29 @@ inp_findmoptions(struct inpcb *inp) * SMPng: NOTE: assumes INP write lock is held. */ void -inp_freemoptions(struct ip_moptions *imo) +inp_freemoptions(struct ip_moptions *imo, struct inpcbinfo *pcbinfo) { + int wlock; if (imo == NULL) return; + + INP_INFO_LOCK_ASSERT(pcbinfo); + wlock = INP_INFO_WLOCKED(pcbinfo); + if (wlock) + INP_INFO_WUNLOCK(pcbinfo); + else + INP_INFO_RUNLOCK(pcbinfo); + KASSERT(imo != NULL, ("%s: ip_moptions is NULL", __func__)); IN_MULTI_LIST_LOCK(); STAILQ_INSERT_TAIL(&imo_gc_list, imo, imo_link); IN_MULTI_LIST_UNLOCK(); taskqueue_enqueue(taskqueue_thread, &imo_gc_task); + if (wlock) + INP_INFO_WLOCK(pcbinfo); + else + INP_INFO_RLOCK(pcbinfo); } static void Modified: head/sys/netinet/in_pcb.c ============================================================================== --- head/sys/netinet/in_pcb.c Sat May 5 20:16:08 2018 (r333276) +++ head/sys/netinet/in_pcb.c Sat May 5 22:40:40 2018 (r333277) @@ -1388,14 +1388,12 @@ in_pcbfree(struct inpcb *inp) if (imo == NULL && im6o == NULL) return; #endif - INP_INFO_WUNLOCK(pcbinfo); #ifdef INET6 - ip6_freemoptions(im6o); + ip6_freemoptions(im6o, pcbinfo); #endif #ifdef INET - inp_freemoptions(imo); + inp_freemoptions(imo, pcbinfo); #endif - INP_INFO_WLOCK(pcbinfo); } /* Modified: head/sys/netinet/ip_var.h ============================================================================== --- head/sys/netinet/ip_var.h Sat May 5 20:16:08 2018 (r333276) +++ head/sys/netinet/ip_var.h Sat May 5 22:40:40 2018 (r333277) @@ -175,6 +175,7 @@ struct ip; struct inpcb; struct route; struct sockopt; +struct inpcbinfo; VNET_DECLARE(int, ip_defttl); /* default IP ttl */ VNET_DECLARE(int, ipforwarding); /* ip forwarding */ @@ -201,7 +202,7 @@ extern struct pr_usrreqs rip_usrreqs; #define V_rsvp_on VNET(rsvp_on) #define V_drop_redirect VNET(drop_redirect) -void inp_freemoptions(struct ip_moptions *); +void inp_freemoptions(struct ip_moptions *, struct inpcbinfo *); int inp_getmoptions(struct inpcb *, struct sockopt *); int inp_setmoptions(struct inpcb *, struct sockopt *); Modified: head/sys/netinet6/in6_mcast.c ============================================================================== --- head/sys/netinet6/in6_mcast.c Sat May 5 20:16:08 2018 (r333276) +++ head/sys/netinet6/in6_mcast.c Sat May 5 22:40:40 2018 (r333277) @@ -1585,13 +1585,20 @@ in6p_findmoptions(struct inpcb *inp) * SMPng: NOTE: assumes INP write lock is held. */ void -ip6_freemoptions(struct ip6_moptions *imo) +ip6_freemoptions(struct ip6_moptions *imo, struct inpcbinfo *pcbinfo) { struct in6_mfilter *imf; size_t idx, nmships; + int wlock; if (imo == NULL) return; + INP_INFO_LOCK_ASSERT(pcbinfo); + wlock = INP_INFO_WLOCKED(pcbinfo); + if (wlock) + INP_INFO_WUNLOCK(pcbinfo); + else + INP_INFO_RUNLOCK(pcbinfo); nmships = imo->im6o_num_memberships; for (idx = 0; idx < nmships; ++idx) { @@ -1608,6 +1615,10 @@ ip6_freemoptions(struct ip6_moptions *imo) free(imo->im6o_mfilters, M_IN6MFILTER); free(imo->im6o_membership, M_IP6MOPTS); free(imo, M_IP6MOPTS); + if (wlock) + INP_INFO_WLOCK(pcbinfo); + else + INP_INFO_RLOCK(pcbinfo); } /* Modified: head/sys/netinet6/in6_var.h ============================================================================== --- head/sys/netinet6/in6_var.h Sat May 5 20:16:08 2018 (r333276) +++ head/sys/netinet6/in6_var.h Sat May 5 22:40:40 2018 (r333277) @@ -807,6 +807,7 @@ in6m_rele_locked(struct in6_multi_head *inmh, struct i struct ip6_moptions; struct sockopt; +struct inpcbinfo; /* Multicast KPIs. */ int im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *, @@ -823,7 +824,7 @@ void in6m_print(const struct in6_multi *); int in6m_record_source(struct in6_multi *, const struct in6_addr *); void in6m_release_deferred(struct in6_multi *); void in6m_release_list_deferred(struct in6_multi_head *); -void ip6_freemoptions(struct ip6_moptions *); +void ip6_freemoptions(struct ip6_moptions *, struct inpcbinfo *); int ip6_getmoptions(struct inpcb *, struct sockopt *); int ip6_setmoptions(struct inpcb *, struct sockopt *);