From owner-svn-src-head@freebsd.org Mon Sep 10 19:00:30 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 B7864109906A; Mon, 10 Sep 2018 19:00:30 +0000 (UTC) (envelope-from markj@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 6F25070170; Mon, 10 Sep 2018 19:00:30 +0000 (UTC) (envelope-from markj@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 6A0704BF6; Mon, 10 Sep 2018 19:00:30 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w8AJ0UL6055230; Mon, 10 Sep 2018 19:00:30 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w8AJ0TAQ055228; Mon, 10 Sep 2018 19:00:29 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201809101900.w8AJ0TAQ055228@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Mon, 10 Sep 2018 19:00:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r338571 - in head/sys: netinet netinet6 X-SVN-Group: head X-SVN-Commit-Author: markj X-SVN-Commit-Paths: in head/sys: netinet netinet6 X-SVN-Commit-Revision: 338571 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.27 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: Mon, 10 Sep 2018 19:00:31 -0000 Author: markj Date: Mon Sep 10 19:00:29 2018 New Revision: 338571 URL: https://svnweb.freebsd.org/changeset/base/338571 Log: Fix synchronization of LB group access. Lookups are protected by an epoch section, so the LB group linkage must be a CK_LIST rather than a plain LIST. Furthermore, we were not deferring LB group frees, so in_pcbremlbgrouphash() could race with readers and cause a use-after-free. Reviewed by: sbruno, Johannes Lundberg Tested by: gallatin Approved by: re (gjb) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D17031 Modified: head/sys/netinet/in_pcb.c head/sys/netinet/in_pcb.h head/sys/netinet6/in6_pcb.c Modified: head/sys/netinet/in_pcb.c ============================================================================== --- head/sys/netinet/in_pcb.c Mon Sep 10 18:59:23 2018 (r338570) +++ head/sys/netinet/in_pcb.c Mon Sep 10 19:00:29 2018 (r338571) @@ -235,18 +235,28 @@ in_pcblbgroup_alloc(struct inpcblbgrouphead *hdr, u_ch grp->il_lport = port; grp->il_dependladdr = *addr; grp->il_inpsiz = size; - LIST_INSERT_HEAD(hdr, grp, il_list); + CK_LIST_INSERT_HEAD(hdr, grp, il_list); return (grp); } static void -in_pcblbgroup_free(struct inpcblbgroup *grp) +in_pcblbgroup_free_deferred(epoch_context_t ctx) { + struct inpcblbgroup *grp; - LIST_REMOVE(grp, il_list); + grp = __containerof(ctx, struct inpcblbgroup, il_epoch_ctx); free(grp, M_PCB); } +static void +in_pcblbgroup_free(struct inpcblbgroup *grp) +{ + + CK_LIST_REMOVE(grp, il_list); + epoch_call(net_epoch_preempt, &grp->il_epoch_ctx, + in_pcblbgroup_free_deferred); +} + static struct inpcblbgroup * in_pcblbgroup_resize(struct inpcblbgrouphead *hdr, struct inpcblbgroup *old_grp, int size) @@ -347,7 +357,7 @@ in_pcbinslbgrouphash(struct inpcb *inp) hdr = &pcbinfo->ipi_lbgrouphashbase[ INP_PCBLBGROUP_PORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { if (grp->il_vflag == inp->inp_vflag && grp->il_lport == inp->inp_lport && memcmp(&grp->il_dependladdr, @@ -409,7 +419,7 @@ in_pcbremlbgrouphash(struct inpcb *inp) INP_PCBLBGROUP_PORTHASH(inp->inp_lport, pcbinfo->ipi_lbgrouphashmask)]; - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { for (i = 0; i < grp->il_inpcnt; ++i) { if (grp->il_inp[i] != inp) continue; @@ -1972,7 +1982,7 @@ in_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, * - Load balanced group does not contain IPv4 mapped INET6 wild sockets */ local_wild = NULL; - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { #ifdef INET6 if (!(grp->il_vflag & INP_IPV4)) continue; Modified: head/sys/netinet/in_pcb.h ============================================================================== --- head/sys/netinet/in_pcb.h Mon Sep 10 18:59:23 2018 (r338570) +++ head/sys/netinet/in_pcb.h Mon Sep 10 19:00:29 2018 (r338571) @@ -70,6 +70,7 @@ */ CK_LIST_HEAD(inpcbhead, inpcb); CK_LIST_HEAD(inpcbporthead, inpcbport); +CK_LIST_HEAD(inpcblbgrouphead, inpcblbgroup); typedef uint64_t inp_gen_t; /* @@ -566,7 +567,8 @@ struct inpcbgroup { * is dynamically resized as processes bind/unbind to that specific group. */ struct inpcblbgroup { - LIST_ENTRY(inpcblbgroup) il_list; + CK_LIST_ENTRY(inpcblbgroup) il_list; + struct epoch_context il_epoch_ctx; uint16_t il_lport; /* (c) */ u_char il_vflag; /* (c) */ u_char il_pad; @@ -578,7 +580,6 @@ struct inpcblbgroup { uint32_t il_inpcnt; /* cur count in il_inp[] (h) */ struct inpcb *il_inp[]; /* (h) */ }; -LIST_HEAD(inpcblbgrouphead, inpcblbgroup); #define INP_LOCK_INIT(inp, d, t) \ rw_init_flags(&(inp)->inp_lock, (t), RW_RECURSE | RW_DUPOK) Modified: head/sys/netinet6/in6_pcb.c ============================================================================== --- head/sys/netinet6/in6_pcb.c Mon Sep 10 18:59:23 2018 (r338570) +++ head/sys/netinet6/in6_pcb.c Mon Sep 10 19:00:29 2018 (r338571) @@ -889,7 +889,7 @@ in6_pcblookup_lbgroup(const struct inpcbinfo *pcbinfo, * - Load balanced group does not contain jailed sockets. * - Load balanced does not contain IPv4 mapped INET6 wild sockets. */ - LIST_FOREACH(grp, hdr, il_list) { + CK_LIST_FOREACH(grp, hdr, il_list) { #ifdef INET if (!(grp->il_vflag & INP_IPV6)) continue;