On Tue, Nov 22, 2016 at 11:54:47AM +0100, Martin Pieuchot wrote:
> Next extract diff that tweaks bpf_detachd().
>
> The goal here is to remove ``d'' from the list and NULLify ``d->bd_bif''
> before calling ifpromisc().
>
> The reason is that ifpromisc() can sleep. Think USB ;) So we'll have to
> release the mutex before calling it. So we want to make sure ``d'' is no
> longer in the interface descriptor list at this point.
>
> ok?
OK bluhm@
>
> Index: net/bpf.c
> ===================================================================
> RCS file: /cvs/src/sys/net/bpf.c,v
> retrieving revision 1.154
> diff -u -p -r1.154 bpf.c
> --- net/bpf.c 21 Nov 2016 09:15:40 -0000 1.154
> +++ net/bpf.c 22 Nov 2016 10:47:05 -0000
> @@ -288,6 +288,23 @@ bpf_detachd(struct bpf_d *d)
> struct bpf_if *bp;
>
> bp = d->bd_bif;
> + /* Not attached. */
> + if (bp == NULL)
> + return;
> +
> + /* Remove ``d'' from the interface's descriptor list. */
> + KERNEL_ASSERT_LOCKED();
> + SRPL_REMOVE_LOCKED(&bpf_d_rc, &bp->bif_dlist, d, bpf_d, bd_next);
> +
> + if (SRPL_EMPTY_LOCKED(&bp->bif_dlist)) {
> + /*
> + * Let the driver know that there are no more listeners.
> + */
> + *bp->bif_driverp = NULL;
> + }
> +
> + d->bd_bif = NULL;
> +
> /*
> * Check if this descriptor had requested promiscuous mode.
> * If so, turn it off.
> @@ -305,19 +322,6 @@ bpf_detachd(struct bpf_d *d)
> */
> panic("bpf: ifpromisc failed");
> }
> -
> - /* Remove d from the interface's descriptor list. */
> - KERNEL_ASSERT_LOCKED();
> - SRPL_REMOVE_LOCKED(&bpf_d_rc, &bp->bif_dlist, d, bpf_d, bd_next);
> -
> - if (SRPL_EMPTY_LOCKED(&bp->bif_dlist)) {
> - /*
> - * Let the driver know that there are no more listeners.
> - */
> - *d->bd_bif->bif_driverp = 0;
> - }
> -
> - d->bd_bif = NULL;
> }
>
> void
> @@ -372,8 +376,7 @@ bpfclose(dev_t dev, int flag, int mode,
>
> d = bpfilter_lookup(minor(dev));
> s = splnet();
> - if (d->bd_bif)
> - bpf_detachd(d);
> + bpf_detachd(d);
> bpf_wakeup(d);
> LIST_REMOVE(d, bd_list);
> bpf_put(d);
> @@ -1033,12 +1036,10 @@ bpf_setif(struct bpf_d *d, struct ifreq
> goto out;
> }
> if (candidate != d->bd_bif) {
> - if (d->bd_bif)
> - /*
> - * Detach if attached to something else.
> - */
> - bpf_detachd(d);
> -
> + /*
> + * Detach if attached to something else.
> + */
> + bpf_detachd(d);
> bpf_attachd(d, candidate);
> }
> bpf_resetd(d);