On Sun, Jul 24, 2016 at 09:31:08AM -0400, Ted Unangst wrote:
> Alexander Bluhm wrote:
> > Hi,
> >
> > When running some scapy regression tests, a current i386 machine
> > triggered this panic.
>
> dunno if this is best. maybe. the refcounting of units implies that they can
> last longer than close(). therefore, if open() is expecting close() to remove
> the unit from the list, we must make sure close does that. dangling refs then
> will be freed when the refcount drops.
>
> The bpfilter_destory function is obfuscation at this point.
>
> Alas, no time to test right now.
I completely missed that bpf devices can hang around after close. With
that in mind your diff makes sense to me. I think it would be wise to
remove the dependency from bpfdetach() on the bpf_d_list, as it is not
actually required since the introduction of bd_unit, to make sure the
early LIST_REMOVE() doesn't produce any side-effects. See updated diff
below.
Alexander, could you verify this fixes the panic on your i386 machine?
natano
Index: net/bpf.c
===================================================================
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.142
diff -u -p -r1.142 bpf.c
--- net/bpf.c 10 Jun 2016 20:33:29 -0000 1.142
+++ net/bpf.c 24 Jul 2016 16:30:30 -0000
@@ -117,7 +117,6 @@ int bpf_sysctl_locked(int *, u_int, void
struct bpf_d *bpfilter_lookup(int);
struct bpf_d *bpfilter_create(int);
-void bpfilter_destroy(struct bpf_d *);
/*
* Reference count access to descriptor buffers
@@ -368,6 +367,7 @@ bpfclose(dev_t dev, int flag, int mode,
if (d->bd_bif)
bpf_detachd(d);
bpf_wakeup(d);
+ LIST_REMOVE(d, bd_list);
D_PUT(d);
splx(s);
@@ -1494,7 +1494,7 @@ bpf_freed(struct bpf_d *d)
srp_update_locked(&bpf_insn_gc, &d->bd_rfilter, NULL);
srp_update_locked(&bpf_insn_gc, &d->bd_wfilter, NULL);
- bpfilter_destroy(d);
+ free(d, M_DEVBUF, sizeof(*d));
}
/*
@@ -1548,20 +1548,8 @@ bpfdetach(struct ifnet *ifp)
if (cdevsw[maj].d_open == bpfopen)
break;
- while ((bd = SRPL_FIRST_LOCKED(&bp->bif_dlist))) {
- struct bpf_d *d;
-
- /*
- * Locate the minor number and nuke the vnode
- * for any open instance.
- */
- LIST_FOREACH(d, &bpf_d_list, bd_list)
- if (d == bd) {
- vdevgone(maj, d->bd_unit,
- d->bd_unit, VCHR);
- break;
- }
- }
+ while ((bd = SRPL_FIRST_LOCKED(&bp->bif_dlist)))
+ vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR);
free(bp, M_DEVBUF, sizeof *bp);
} else
@@ -1649,13 +1637,6 @@ bpfilter_create(int unit)
LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list);
}
return (bd);
-}
-
-void
-bpfilter_destroy(struct bpf_d *bd)
-{
- LIST_REMOVE(bd, bd_list);
- free(bd, M_DEVBUF, sizeof(*bd));
}
/*