Date: Wed, 30 Aug 2017 21:18:56 +0000 (UTC) From: Kristof Provost <kp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r323034 - stable/11/sys/net Message-ID: <201708302118.v7ULIuwf035747@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kp Date: Wed Aug 30 21:18:56 2017 New Revision: 323034 URL: https://svnweb.freebsd.org/changeset/base/323034 Log: MFC r322590: bpf: Fix incorrect cleanup Cleaning up a bpf_if is a two stage process. We first move it to the bpf_freelist (in bpfdetach()) and only later do we actually free it (in bpf_ifdetach()). We cannot set the ifp->if_bpf to NULL from bpf_ifdetach() because it's possible that the ifnet has already gone away, or that it has been assigned a new bpf_if. This can lead to a struct ifnet which is up, but has if_bpf set to NULL, which will panic when we try to send the next packet. Keep track of the pointer to the bpf_if (because it's not always ifp->if_bpf), and NULL it immediately in bpfdetach(). PR: 213896 Differential Revision: https://reviews.freebsd.org/D11782 Modified: stable/11/sys/net/bpf.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/net/bpf.c ============================================================================== --- stable/11/sys/net/bpf.c Wed Aug 30 21:18:43 2017 (r323033) +++ stable/11/sys/net/bpf.c Wed Aug 30 21:18:56 2017 (r323034) @@ -106,6 +106,7 @@ struct bpf_if { struct rwlock bif_lock; /* interface lock */ LIST_HEAD(, bpf_d) bif_wlist; /* writer-only list */ int bif_flags; /* Interface flags */ + struct bpf_if **bif_bpf; /* Pointer to pointer to us */ }; CTASSERT(offsetof(struct bpf_if, bif_ext) == 0); @@ -2563,6 +2564,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, bp->bif_dlt = dlt; rw_init(&bp->bif_lock, "bpf interface lock"); KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized")); + bp->bif_bpf = driverp; *driverp = bp; BPF_LOCK(); @@ -2633,6 +2635,7 @@ bpfdetach(struct ifnet *ifp) */ BPFIF_WLOCK(bp); bp->bif_flags |= BPFIF_FLAG_DYING; + *bp->bif_bpf = NULL; BPFIF_WUNLOCK(bp); CTR4(KTR_NET, "%s: sheduling free for encap %d (%p) for if %p", @@ -2702,13 +2705,6 @@ bpf_ifdetach(void *arg __unused, struct ifnet *ifp) nmatched++; } BPF_UNLOCK(); - - /* - * Note that we cannot zero other pointers to - * custom DLTs possibly used by given interface. - */ - if (nmatched != 0) - ifp->if_bpf = NULL; } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708302118.v7ULIuwf035747>