Index: bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.127 diff -u -p -r1.127 bpf.c --- bpf.c 13 Sep 2015 17:53:44 -0000 1.127 +++ bpf.c 28 Sep 2015 03:21:46 -0000 @@ -524,6 +524,8 @@ bpfwrite(dev_t dev, struct uio *uio, int struct bpf_d *d; struct ifnet *ifp; struct mbuf *m; + struct bpf_program *bf; + struct bpf_insn *fcode = NULL; int error, s; struct sockaddr_storage dst; @@ -540,8 +542,12 @@ bpfwrite(dev_t dev, struct uio *uio, int return (0); KERNEL_ASSERT_LOCKED(); /* for accessing bd_wfilter */ + bf = srp_get_locked(&d->bd_wfilter); + if (bf != NULL) + fcode = bf->bf_insns; + error = bpf_movein(uio, d->bd_bif->bif_dlt, &m, - (struct sockaddr *)&dst, srp_get_locked(&d->bd_wfilter)); + (struct sockaddr *)&dst, fcode); if (error) return (error); @@ -917,6 +923,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t int bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf) { + struct bpf_program *bf; struct srp *filter; struct bpf_insn *fcode; u_int flen, size; @@ -940,16 +947,22 @@ bpf_setf(struct bpf_d *d, struct bpf_pro fcode = mallocarray(flen, sizeof(*fp->bf_insns), M_DEVBUF, M_WAITOK); size = flen * sizeof(*fp->bf_insns); - if (copyin(fp->bf_insns, fcode, size) == 0 && - bpf_validate(fcode, (int)flen)) { - srp_update_locked(&bpf_insn_gc, filter, fcode); - s = splnet(); - bpf_reset_d(d); - splx(s); - return (0); + if (copyin(fp->bf_insns, fcode, size) != 0 || + bpf_validate(fcode, (int)flen) != 0) { + free(fcode, M_DEVBUF, size); + return (EINVAL); } - free(fcode, M_DEVBUF, size); - return (EINVAL); + + bf = malloc(sizeof(*bf), M_DEVBUF, M_WAITOK); + bf->bf_len = flen; + bf->bf_insns = fcode; + + srp_update_locked(&bpf_insn_gc, filter, fcode); + + s = splnet(); + bpf_reset_d(d); + splx(s); + return (0); } /* @@ -1134,10 +1147,14 @@ bpf_tap(caddr_t arg, u_char *pkt, u_int if ((direction & d->bd_dirfilt) != 0) slen = 0; else { - struct bpf_insn *fcode; - fcode = srp_enter(&d->bd_rfilter); + struct bpf_program *bf; + struct bpf_insn *fcode = NULL; + + bf = srp_enter(&d->bd_rfilter); + if (bf != NULL) + fcode = bf->bf_insns; slen = bpf_filter(fcode, pkt, pktlen, 0); - srp_leave(&d->bd_rfilter, fcode); + srp_leave(&d->bd_rfilter, bf); } if (slen > 0) { @@ -1214,10 +1231,14 @@ _bpf_mtap(caddr_t arg, struct mbuf *m, u else if (d->bd_queue && m->m_pkthdr.pf.qid != d->bd_queue) slen = 0; else { - struct bpf_insn *fcode; - fcode = srp_enter(&d->bd_rfilter); + struct bpf_program *bf; + struct bpf_insn *fcode = NULL; + + bf = srp_enter(&d->bd_rfilter); + if (bf != NULL) + fcode = bf->bf_insns; slen = bpf_filter(fcode, (u_char *)m, pktlen, 0); - srp_leave(&d->bd_rfilter, fcode); + srp_leave(&d->bd_rfilter, bf); } if (slen > 0) { @@ -1513,7 +1534,7 @@ bpfdetach(struct ifnet *ifp) } } - free(bp, M_DEVBUF, 0); + free(bp, M_DEVBUF, sizeof(*bp)); } else pbp = &bp->bif_next; } @@ -1679,7 +1700,11 @@ bpf_d_unref(void *null, void *d) } void -bpf_insn_dtor(void *null, void *fcode) +bpf_insn_dtor(void *null, void *f) { - free(fcode, M_DEVBUF, 0); + struct bpf_program *bf = f; + struct bpf_insn *insns = bf->bf_insns; + + free(insns, M_DEVBUF, bf->bf_len * sizeof(*insns)); + free(bf, M_DEVBUF, sizeof(*bf)); }