untrusted comment: verify with openbsd-66-base.pub RWSvK/c+cFe24GfJ1f7I1EopRSLZ5MmN+StVmNstQEhEb6cjntr/2lgIvLDRJyw33QiTJbIH9opWMcZ54YasS5jr9weqTWfcBQI= OpenBSD 6.6 errata 001, October 28, 2019: Repair bpf(4) race condition during device removal. Apply by doing: signify -Vep /etc/signify/openbsd-66-base.pub -x 001_bpf.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/net/bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.181 diff -u -p -r1.181 bpf.c --- sys/net/bpf.c 1 Oct 2019 11:51:13 -0000 1.181 +++ sys/net/bpf.c 24 Oct 2019 18:58:05 -0000 @@ -124,6 +124,13 @@ void bpf_resetd(struct bpf_d *); void bpf_prog_smr(void *); void bpf_d_smr(void *); +/* + * Reference count access to descriptor buffers + */ +void bpf_get(struct bpf_d *); +void bpf_put(struct bpf_d *); + + struct rwlock bpf_sysctl_lk = RWLOCK_INITIALIZER("bpfsz"); int @@ -318,11 +325,13 @@ bpf_detachd(struct bpf_d *d) d->bd_promisc = 0; + bpf_get(d); mtx_leave(&d->bd_mtx); NET_LOCK(); error = ifpromisc(bp->bif_ifp, 0); NET_UNLOCK(); mtx_enter(&d->bd_mtx); + bpf_put(d); if (error && !(error == EINVAL || error == ENODEV || error == ENXIO)) @@ -371,6 +380,7 @@ bpfopen(dev_t dev, int flag, int mode, s if (flag & FNONBLOCK) bd->bd_rtout = -1; + bpf_get(bd); LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list); return (0); @@ -391,13 +401,7 @@ bpfclose(dev_t dev, int flag, int mode, bpf_wakeup(d); LIST_REMOVE(d, bd_list); mtx_leave(&d->bd_mtx); - - /* - * Wait for the task to finish here, before proceeding to garbage - * collection. - */ - taskq_barrier(systq); - smr_call(&d->bd_smr, bpf_d_smr, d); + bpf_put(d); return (0); } @@ -431,6 +435,7 @@ bpfread(dev_t dev, struct uio *uio, int if (d->bd_bif == NULL) return (ENXIO); + bpf_get(d); mtx_enter(&d->bd_mtx); /* @@ -536,6 +541,7 @@ bpfread(dev_t dev, struct uio *uio, int d->bd_in_uiomove = 0; out: mtx_leave(&d->bd_mtx); + bpf_put(d); return (error); } @@ -554,7 +560,9 @@ bpf_wakeup(struct bpf_d *d) * by the KERNEL_LOCK() we have to delay the wakeup to * another context to keep the hot path KERNEL_LOCK()-free. */ - task_add(systq, &d->bd_wake_task); + bpf_get(d); + if (!task_add(systq, &d->bd_wake_task)) + bpf_put(d); } void @@ -569,6 +577,7 @@ bpf_wakeup_cb(void *xd) csignal(d->bd_pgid, d->bd_sig, d->bd_siguid, d->bd_sigeuid); selwakeup(&d->bd_sel); + bpf_put(d); } int @@ -586,6 +595,7 @@ bpfwrite(dev_t dev, struct uio *uio, int if (d->bd_bif == NULL) return (ENXIO); + bpf_get(d); ifp = d->bd_bif->bif_ifp; if (ifp == NULL || (ifp->if_flags & IFF_UP) == 0) { @@ -619,6 +629,7 @@ bpfwrite(dev_t dev, struct uio *uio, int NET_UNLOCK(); out: + bpf_put(d); return (error); } @@ -694,6 +705,8 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t } } + bpf_get(d); + switch (cmd) { default: error = EINVAL; @@ -991,6 +1004,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t break; } + bpf_put(d); return (error); } @@ -1178,6 +1192,7 @@ bpfkqfilter(dev_t dev, struct knote *kn) return (EINVAL); } + bpf_get(d); kn->kn_hook = d; SLIST_INSERT_HEAD(klist, kn, kn_selnext); @@ -1197,6 +1212,7 @@ filt_bpfrdetach(struct knote *kn) KERNEL_ASSERT_LOCKED(); SLIST_REMOVE(&d->bd_sel.si_note, kn, knote, kn_selnext); + bpf_put(d); } int @@ -1577,6 +1593,25 @@ bpf_d_smr(void *smr) bpf_prog_smr(bd->bd_wfilter); free(bd, M_DEVBUF, sizeof(*bd)); +} + +void +bpf_get(struct bpf_d *bd) +{ + atomic_inc_int(&bd->bd_ref); +} + +/* + * Free buffers currently in use by a descriptor + * when the reference count drops to zero. + */ +void +bpf_put(struct bpf_d *bd) +{ + if (atomic_dec_int_nv(&bd->bd_ref) > 0) + return; + + smr_call(&bd->bd_smr, bpf_d_smr, bd); } void * Index: sys/net/bpfdesc.h =================================================================== RCS file: /cvs/src/sys/net/bpfdesc.h,v retrieving revision 1.38 diff -u -p -r1.38 bpfdesc.h --- sys/net/bpfdesc.h 18 May 2019 12:59:32 -0000 1.38 +++ sys/net/bpfdesc.h 24 Oct 2019 18:58:05 -0000 @@ -93,6 +93,7 @@ struct bpf_d { pid_t bd_pgid; /* process or group id for signal */ uid_t bd_siguid; /* uid for process that set pgid */ uid_t bd_sigeuid; /* euid for process that set pgid */ + u_int bd_ref; /* reference count */ struct selinfo bd_sel; /* bsd select info */ int bd_unit; /* logical unit number */ LIST_ENTRY(bpf_d) bd_list; /* descriptor list */