diff options
author | melifaro <melifaro@FreeBSD.org> | 2012-05-29 12:52:30 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2012-05-29 12:52:30 +0000 |
commit | ce59e84fbe903b8c54083cbe8ebece53d25e4c39 (patch) | |
tree | af1e61bbdeb3ff8b79dd59977d77024c26a95d65 /sys/net | |
parent | ff66e936dd305e4b4b5e2bdab0b958a7d4d17278 (diff) | |
download | FreeBSD-src-ce59e84fbe903b8c54083cbe8ebece53d25e4c39.zip FreeBSD-src-ce59e84fbe903b8c54083cbe8ebece53d25e4c39.tar.gz |
Fix BPF_JITTER code broken by r235746.
Pointed by: jkim
Reviewed by: jkim (except locking changes)
Approved by: (mentor)
MFC after: 2 weeks
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/bpf.c | 94 |
1 files changed, 48 insertions, 46 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index accbcd5..4b48dda 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1711,7 +1711,7 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd) struct bpf_insn *fcode, *old; u_int wfilter, flen, size; #ifdef BPF_JITTER - bpf_jit_filter *ofunc, *jfunc; + bpf_jit_filter *jfunc, *ofunc; #endif int need_upgrade; #ifdef COMPAT_FREEBSD32 @@ -1737,13 +1737,20 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd) need_upgrade = 0; size = flen * sizeof(*fp->bf_insns); - if (size > 0) + if (size > 0) { + /* We're setting up new filter. Copy and check actual data */ fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK); - else + if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) != 0 || + bpf_validate(fcode, (int)flen) == 0) { + free(fcode, M_BPF); + return (EINVAL); + } + /* Filter is copied inside fcode and is perfectly valid */ + } else fcode = NULL; /* Make compiler happy */ #ifdef BPF_JITTER - if (fp->bf_insns != NULL) + if (fcode != NULL) jfunc = bpf_jitter(fcode, flen); else jfunc = NULL; /* Make compiler happy */ @@ -1764,7 +1771,7 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd) ofunc = d->bd_bfilter; #endif } - if (fp->bf_insns == NULL) { + if (fcode == NULL) { /* * Protect filter removal by interface lock. * Additionally, we are protected by global lock here. @@ -1795,55 +1802,50 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd) return (0); } - if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && - bpf_validate(fcode, (int)flen)) { - /* - * Protect filter change by interface lock - * Additionally, we are protected by global lock here. - */ - if (d->bd_bif != NULL) - BPFIF_WLOCK(d->bd_bif); - BPFD_LOCK(d); - if (wfilter) - d->bd_wfilter = fcode; - else { - d->bd_rfilter = fcode; + /* + * Set up new filter. + * Protect filter change by interface lock + * Additionally, we are protected by global lock here. + */ + if (d->bd_bif != NULL) + BPFIF_WLOCK(d->bd_bif); + BPFD_LOCK(d); + if (wfilter) + d->bd_wfilter = fcode; + else { + d->bd_rfilter = fcode; #ifdef BPF_JITTER - d->bd_bfilter = jfunc; + d->bd_bfilter = jfunc; #endif - if (cmd == BIOCSETF) - reset_d(d); + if (cmd == BIOCSETF) + reset_d(d); - /* - * Do not require upgrade by first BIOCSETF - * (used to set snaplen) by pcap_open_live() - */ - if ((d->bd_writer != 0) && (--d->bd_writer == 0)) - need_upgrade = 1; - CTR4(KTR_NET, "%s: filter function set by pid %d, " - "bd_writer counter %d, need_upgrade %d", - __func__, d->bd_pid, d->bd_writer, need_upgrade); - } - BPFD_UNLOCK(d); - if (d->bd_bif != NULL) - BPFIF_WUNLOCK(d->bd_bif); - if (old != NULL) - free((caddr_t)old, M_BPF); + /* + * Do not require upgrade by first BIOCSETF + * (used to set snaplen) by pcap_open_live() + */ + if ((d->bd_writer != 0) && (--d->bd_writer == 0)) + need_upgrade = 1; + CTR4(KTR_NET, "%s: filter function set by pid %d, " + "bd_writer counter %d, need_upgrade %d", + __func__, d->bd_pid, d->bd_writer, need_upgrade); + } + BPFD_UNLOCK(d); + if (d->bd_bif != NULL) + BPFIF_WUNLOCK(d->bd_bif); + if (old != NULL) + free((caddr_t)old, M_BPF); #ifdef BPF_JITTER - if (ofunc != NULL) - bpf_destroy_jit_filter(ofunc); + if (ofunc != NULL) + bpf_destroy_jit_filter(ofunc); #endif - /* Move d to active readers list */ - if (need_upgrade != 0) - bpf_upgraded(d); + /* Move d to active readers list */ + if (need_upgrade != 0) + bpf_upgraded(d); - BPF_UNLOCK(); - return (0); - } - free((caddr_t)fcode, M_BPF); BPF_UNLOCK(); - return (EINVAL); + return (0); } /* |