Panic in bpf.c catchpacket()

Guy Helmer guy.helmer at gmail.com
Fri Nov 2 14:42:35 UTC 2012


Still working this problem I've previously mentioned, and my working theory now is a race between catchpacket() and this code in bpfread():

        /*
         * At this point, we know we have something in the hold slot.
         */
        BPFD_UNLOCK(d);

        /*
         * Move data from hold buffer into user space.
         * We know the entire buffer is transferred since
         * we checked above that the read buffer is bpf_bufsize bytes.
         *
         * XXXRW: More synchronization needed here: what if a second thread
         * issues a read on the same fd at the same time?  Don't want this
         * getting invalidated.
         */
        error = bpf_uiomove(d, d->bd_hbuf, d->bd_hlen, uio);
 
        BPFD_LOCK(d);
        d->bd_fbuf = d->bd_hbuf;
        d->bd_hbuf = NULL;
        d->bd_hlen = 0;
        bpf_buf_reclaimed(d);
       BPFD_UNLOCK(d);

Assuming it's unwise to hold the descriptor lock over the uiomove() call, it seems we at least need to check to make sure bd_hbuf is still valid:

@@ -809,10 +948,15 @@ bpfread(struct cdev *dev, struct uio *uio, int iof
        error = bpf_uiomove(d, d->bd_hbuf, d->bd_hlen, uio);
 
        BPFD_LOCK(d);
-       d->bd_fbuf = d->bd_hbuf;
-       d->bd_hbuf = NULL;
-       d->bd_hlen = 0;
-       bpf_buf_reclaimed(d);
+       if (d->bd_hbuf == NULL) {
+               printf("bpfread: lost race: bd_hbuf=%p bd_sbuf=%p bd_fbuf=%p\n",
+                      d->bd_hbuf, d->bd_sbuf, d->bd_fbuf);
+       } else {
+               d->bd_fbuf = d->bd_hbuf;
+               d->bd_hbuf = NULL;
+               d->bd_hlen = 0;
+               bpf_buf_reclaimed(d);
+       }
        BPFD_UNLOCK(d);
 
        return (error);

This still seems vulnerable to me -- a ROTATE_BUFFERS() or reset_d() could be done between the BPFD_UNLOCK() and the bpf_uiomove(). Would a new lock to protect the buffers be necessary, or a flag+condition variable to indicate "hold buffer in use"?

Guy


More information about the freebsd-hackers mailing list