Call bpf_jitter() before acquiring BPF global lock due to malloc() being used inside bpf_jitter.

Eliminate bpf_buffer_alloc() and allocate BPF buffers on descriptor creation and BIOCSBLEN ioctl.
This permits us not to allocate buffers inside bpf_attachd() which is protected by global lock.

Approved by:      kib(mentor)
MFC in:            4 weeks
This commit is contained in:
Alexander V. Chernikov 2012-05-21 22:19:19 +00:00
parent afa85850e7
commit c7b0200eb5
3 changed files with 43 additions and 29 deletions

View File

@ -804,7 +804,7 @@ static int
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
int error;
int error, size;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
error = devfs_set_cdevpriv(d, bpf_dtor);
@ -831,6 +831,10 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
/* Allocate default buffers */
size = d->bd_bufsize;
bpf_buffer_ioctl_sblen(d, &size);
return (0);
}
@ -1664,7 +1668,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;
bpf_jit_filter *ofunc, *jfunc;
#endif
int need_upgrade;
#ifdef COMPAT_FREEBSD32
@ -1695,6 +1699,13 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
else
fcode = NULL; /* Make compiler happy */
#ifdef BPF_JITTER
if (fp->bf_insns != NULL)
jfunc = bpf_jitter(fcode, flen);
else
jfunc = NULL; /* Make compiler happy */
#endif
BPF_LOCK();
if (cmd == BIOCSETWF) {
@ -1755,7 +1766,7 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
else {
d->bd_rfilter = fcode;
#ifdef BPF_JITTER
d->bd_bfilter = bpf_jitter(fcode, flen);
d->bd_bfilter = jfunc;
#endif
if (cmd == BIOCSETF)
reset_d(d);
@ -1827,11 +1838,6 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
if (d->bd_sbuf == NULL)
bpf_buffer_alloc(d);
KASSERT(d->bd_sbuf != NULL, ("bpf_setif: bd_sbuf NULL"));
break;
case BPF_BUFMODE_ZBUF:
if (d->bd_sbuf == NULL)
return (EINVAL);

View File

@ -93,21 +93,6 @@ static int bpf_maxbufsize = BPF_MAXBUFSIZE;
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
&bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
void
bpf_buffer_alloc(struct bpf_d *d)
{
KASSERT(d->bd_fbuf == NULL, ("bpf_buffer_alloc: bd_fbuf != NULL"));
KASSERT(d->bd_sbuf == NULL, ("bpf_buffer_alloc: bd_sbuf != NULL"));
KASSERT(d->bd_hbuf == NULL, ("bpf_buffer_alloc: bd_hbuf != NULL"));
d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
d->bd_hbuf = NULL;
d->bd_slen = 0;
d->bd_hlen = 0;
}
/*
* Simple data copy to the current kernel buffer.
*/
@ -183,18 +168,42 @@ int
bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
{
u_int size;
caddr_t fbuf, sbuf;
BPFD_LOCK(d);
if (d->bd_bif != NULL) {
BPFD_UNLOCK(d);
return (EINVAL);
}
size = *i;
if (size > bpf_maxbufsize)
*i = size = bpf_maxbufsize;
else if (size < BPF_MINBUFSIZE)
*i = size = BPF_MINBUFSIZE;
/* Allocate buffers immediately */
fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
BPFD_LOCK(d);
if (d->bd_bif != NULL) {
/* Interface already attached, unable to change buffers */
BPFD_UNLOCK(d);
free(fbuf, M_BPF);
free(sbuf, M_BPF);
return (EINVAL);
}
/* Free old buffers if set */
if (d->bd_fbuf != NULL)
free(d->bd_fbuf, M_BPF);
if (d->bd_sbuf != NULL)
free(d->bd_sbuf, M_BPF);
/* Fill in new data */
d->bd_bufsize = size;
d->bd_fbuf = fbuf;
d->bd_sbuf = sbuf;
d->bd_hbuf = NULL;
d->bd_slen = 0;
d->bd_hlen = 0;
BPFD_UNLOCK(d);
return (0);
}

View File

@ -36,7 +36,6 @@
#error "no user-serviceable parts inside"
#endif
void bpf_buffer_alloc(struct bpf_d *d);
void bpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
void *src, u_int len);
void bpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset,