svn commit: r236559 - head/sys/net
Alexander V. Chernikov
melifaro at FreeBSD.org
Mon Jun 4 12:36:59 UTC 2012
Author: melifaro
Date: Mon Jun 4 12:36:58 2012
New Revision: 236559
URL: http://svn.freebsd.org/changeset/base/236559
Log:
Fix panic introduced by r235745. Panic occurs after first packet traverse renamed interface.
Add several comments on locking
Found by: avg
Approved by: ae(mentor)
Tested by: avg
MFC after: 1 week
Modified:
head/sys/net/bpf.c
Modified: head/sys/net/bpf.c
==============================================================================
--- head/sys/net/bpf.c Mon Jun 4 12:28:56 2012 (r236558)
+++ head/sys/net/bpf.c Mon Jun 4 12:36:58 2012 (r236559)
@@ -1704,6 +1704,14 @@ bpfioctl(struct cdev *dev, u_long cmd, c
/*
* Set d's packet filter program to fp. If this file already has a filter,
* free it and replace it. Returns EINVAL for bogus requests.
+ *
+ * Note we need global lock here to serialize bpf_setf() and bpf_setif() calls
+ * since reading d->bd_bif can't be protected by d or interface lock due to
+ * lock order.
+ *
+ * Additionally, we have to acquire interface write lock due to bpf_mtap() uses
+ * interface read lock to read all filers.
+ *
*/
static int
bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
@@ -2535,20 +2543,32 @@ bpfdetach(struct ifnet *ifp)
}
/*
- * Interface departure handler
+ * Interface departure handler.
+ * Note departure event does not guagantee interface is going down.
*/
static void
bpf_ifdetach(void *arg __unused, struct ifnet *ifp)
{
struct bpf_if *bp;
- if ((bp = ifp->if_bpf) == NULL)
+ BPF_LOCK();
+ if ((bp = ifp->if_bpf) == NULL) {
+ BPF_UNLOCK();
+ return;
+ }
+
+ /* Check if bpfdetach() was called previously */
+ if ((bp->flags & BPFIF_FLAG_DYING) == 0) {
+ BPF_UNLOCK();
return;
+ }
CTR3(KTR_NET, "%s: freing BPF instance %p for interface %p",
__func__, bp, ifp);
ifp->if_bpf = NULL;
+ BPF_UNLOCK();
+
rw_destroy(&bp->bif_lock);
free(bp, M_BPF);
}
More information about the svn-src-all
mailing list