svn commit: r323034 - stable/11/sys/net
Kristof Provost
kp at FreeBSD.org
Wed Aug 30 21:18:58 UTC 2017
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;
}
/*
More information about the svn-src-stable-11
mailing list