Make sure we are clearing the ZBUF_FLAG_IMMUTABLE any time a free buffer

is reclaimed by the kernel.  This fixes a bug resulted in the kernel
over writing packet data while user-space was still processing it when
zerocopy is enabled.  (Or a panic if invariants was enabled).

Discussed with:	rwatson
This commit is contained in:
Christian S.J. Peron 2008-07-05 20:11:28 +00:00
parent 4d5ed46093
commit 29f612ec71
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=180310
3 changed files with 44 additions and 0 deletions

View File

@ -199,6 +199,28 @@ bpf_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset, void *src,
}
}
/*
* This function gets called when the free buffer is re-assigned.
*/
static void
bpf_buf_reclaimed(struct bpf_d *d)
{
BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
return;
case BPF_BUFMODE_ZBUF:
bpf_zerocopy_buf_reclaimed(d);
return;
default:
panic("bpf_buf_reclaimed");
}
}
/*
* If the buffer mechanism has a way to decide that a held buffer can be made
* free, then it is exposed via the bpf_canfreebuf() interface. (1) is
@ -744,6 +766,7 @@ bpfread(struct cdev *dev, struct uio *uio, int ioflag)
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = NULL;
d->bd_hlen = 0;
bpf_buf_reclaimed(d);
BPFD_UNLOCK(d);
return (error);
@ -887,6 +910,7 @@ reset_d(struct bpf_d *d)
/* Free the hold buffer. */
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = NULL;
bpf_buf_reclaimed(d);
}
d->bd_slen = 0;
d->bd_hlen = 0;
@ -1717,6 +1741,7 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = NULL;
d->bd_hlen = 0;
bpf_buf_reclaimed(d);
}
/*

View File

@ -409,6 +409,24 @@ bpf_zerocopy_bufheld(struct bpf_d *d)
}
}
/*
* Notification from the BPF framework that the free buffer has been been
* re-assigned. This happens when the user ackknowledges the buffer.
*/
void
bpf_zerocopy_buf_reclaimed(struct bpf_d *d)
{
struct zbuf *zb;
KASSERT(d->bd_bufmode == BPF_BUFMODE_ZBUF,
("bpf_zerocopy_reclaim_buf: not in zbuf mode"));
KASSERT(d->bd_fbuf != NULL,
("bpf_zerocopy_buf_reclaimed: NULL free buff"));
zb = (struct zbuf *)d->bd_fbuf;
zb->zb_flags &= ~ZBUF_FLAG_IMMUTABLE;
}
/*
* Query from the BPF framework regarding whether the buffer currently in the
* held position can be moved to the free position, which can be indicated by

View File

@ -42,6 +42,7 @@ void bpf_zerocopy_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset,
void *src, u_int len);
void bpf_zerocopy_buffull(struct bpf_d *);
void bpf_zerocopy_bufheld(struct bpf_d *);
void bpf_zerocopy_buf_reclaimed(struct bpf_d *);
int bpf_zerocopy_canfreebuf(struct bpf_d *);
int bpf_zerocopy_canwritebuf(struct bpf_d *);
void bpf_zerocopy_free(struct bpf_d *d);