On Mon, Nov 28, 2016 at 04:01:14PM +0100, Martin Pieuchot wrote: > @@ -313,7 +319,13 @@ bpf_detachd(struct bpf_d *d) > int error; > > d->bd_promisc = 0; > + > + bpf_get(d); > + mtx_leave(&d->bd_mtx); > error = ifpromisc(bp->bif_ifp, 0); > + mtx_enter(&d->bd_mtx); > + bpf_put(d); > +
If I see something like this, I ask myself wether bp has to be protected by the mutex like this: bpf_get(d); ifp = bp->bif_ifp; mtx_leave(&d->bd_mtx); error = ifpromisc(ifp, 0); mtx_enter(&d->bd_mtx); bpf_put(d); But I think your code is safe as bd_bif is only modified with kernel lock. > @@ -542,6 +568,7 @@ bpf_wakeup_cb(void *xd) > > selwakeup(&d->bd_sel); > bpf_put(d); > + > } > > int This new line is wrong. > @@ -717,7 +753,9 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t > *(u_int *)addr = size = bpf_maxbufsize; > else if (size < BPF_MINBUFSIZE) > *(u_int *)addr = size = BPF_MINBUFSIZE; > + mtx_enter(&d->bd_mtx); > d->bd_bufsize = size; > + mtx_leave(&d->bd_mtx); > } > break; > bd_bufsize needs protection, but you only add it in BIOCSBLEN, you should also put a mutex in BIOCGBLEN. > @@ -778,30 +815,36 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t > * Get device parameters. > */ > case BIOCGDLT: > + mtx_enter(&d->bd_mtx); > if (d->bd_bif == NULL) > error = EINVAL; > else > *(u_int *)addr = d->bd_bif->bif_dlt; > + mtx_leave(&d->bd_mtx); > break; bd_bif is not protected elsewhere. bif_dlt is only set during attach. So I think you need no mutex here. > > /* > * Set device parameters. > */ > case BIOCSDLT: > + mtx_enter(&d->bd_mtx); > if (d->bd_bif == NULL) > error = EINVAL; > else > error = bpf_setdlt(d, *(u_int *)addr); > + mtx_leave(&d->bd_mtx); > break; bd_bif needs not protection, so put the mutex only in the else path. Then it is obvious why it is there. > > /* > * Set interface name. > */ > case BIOCGETIF: > + mtx_enter(&d->bd_mtx); > if (d->bd_bif == NULL) > error = EINVAL; > else > bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); > + mtx_leave(&d->bd_mtx); > break; The interface name is not used by bpf without kernel lock. You do not need a mutex here. > @@ -1151,6 +1197,8 @@ filt_bpfread(struct knote *kn, long hint > { > struct bpf_d *d = kn->kn_hook; > > + KERNEL_ASSERT_LOCKED(); > + > kn->kn_data = d->bd_hlen; > if (d->bd_immediate) > kn->kn_data += d->bd_slen; You need the mutex here to access bd_slen. > @@ -1232,12 +1279,10 @@ _bpf_mtap(caddr_t arg, const struct mbuf > if (!gottime++) > microtime(&tv); > > - KERNEL_LOCK(); > - s = splnet(); > + mtx_enter(&d->bd_mtx); > bpf_catchpacket(d, (u_char *)m, pktlen, slen, cpfn, > &tv); > - splx(s); > - KERNEL_UNLOCK(); > + mtx_leave(&d->bd_mtx); > > if (d->bd_fildrop) > drop = 1; bd_fildrop can be changed by ioctl. Can we expect to read the correct value without a memory barrier? Same question applies to bd_dirfilt. bd_rcount is a long value incremented atomically in _bpf_mtap(). It is read from an other CPU with kernel lock during an ioctl. Is this sufficient to get a consisten value? Do we also need an atomic operation when reading it? > --- net/bpfdesc.h 22 Aug 2016 10:40:36 -0000 1.31 > +++ net/bpfdesc.h 28 Nov 2016 14:51:06 -0000 > @@ -56,15 +56,17 @@ struct bpf_d { > * fbuf (free) - When read is done, put cluster here. > * On receiving, if sbuf is full and fbuf is 0, packet is dropped. > */ > + struct mutex bd_mtx; /* protect buffer slots below */ > caddr_t bd_sbuf; /* store slot */ > caddr_t bd_hbuf; /* hold slot */ > caddr_t bd_fbuf; /* free slot */ > int bd_slen; /* current length of store buffer */ > int bd_hlen; /* current length of hold buffer */ > - > int bd_bufsize; /* absolute length of buffers */ So bd_mtx is protecting the fields above. Everything below must either be not accessed without kernel lock, or only be set during attach. Is that correct or do I have a wrong understanding of the SMP model? > > - struct bpf_if * bd_bif; /* interface descriptor */ > + int __in_uiomove; Why do you prefix it with __ ? bd_uiomove would be more consistent. bluhm