From owner-freebsd-net@FreeBSD.ORG Mon Nov 5 23:42:53 2012 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6AA82494 for ; Mon, 5 Nov 2012 23:42:53 +0000 (UTC) (envelope-from guy.helmer@gmail.com) Received: from mail.palisadesystems.com (mail.palisadesystems.com [216.81.178.129]) by mx1.freebsd.org (Postfix) with ESMTP id 120DE8FC08 for ; Mon, 5 Nov 2012 23:42:52 +0000 (UTC) Received: from [192.168.221.160] ([192.168.221.160]) (authenticated bits=0) by mail.palisadesystems.com (8.14.3/8.14.3) with ESMTP id qA5Ng9wF029567 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO) for ; Mon, 5 Nov 2012 17:42:16 -0600 (CST) (envelope-from guy.helmer@gmail.com) X-DKIM: Sendmail DKIM Filter v2.8.3 mail.palisadesystems.com qA5Ng9wF029567 From: Guy Helmer Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Message-Id: Date: Mon, 5 Nov 2012 17:42:06 -0600 To: "freebsd-net@freebsd.org" Mime-Version: 1.0 (Mac OS X Mail 6.2 \(1499\)) X-Mailer: Apple Mail (2.1499) X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.5 (mail.palisadesystems.com [172.16.1.5]); Mon, 05 Nov 2012 17:42:17 -0600 (CST) X-Palisade-MailScanner-Information: Please contact the ISP for more information X-Palisade-MailScanner-ID: qA5Ng9wF029567 X-Palisade-MailScanner: Found to be clean X-Palisade-MailScanner-SpamCheck: not spam, SpamAssassin (score=0.084, required 5, ALL_TRUSTED -1.00, BAYES_00 -1.90, FREEMAIL_FROM 1.00, RP_8BIT 1.98) X-Palisade-MailScanner-From: guy.helmer@gmail.com Subject: Panic in bpf.c catchpacket() X-Spam-Status: No X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 05 Nov 2012 23:42:53 -0000 Still working this problem I've previously mentioned on the list, 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 =3D bpf_uiomove(d, d->bd_hbuf, d->bd_hlen, uio); =20 BPFD_LOCK(d); d->bd_fbuf =3D d->bd_hbuf; d->bd_hbuf =3D NULL; d->bd_hlen =3D 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 =3D bpf_uiomove(d, d->bd_hbuf, d->bd_hlen, uio); =20 BPFD_LOCK(d); - d->bd_fbuf =3D d->bd_hbuf; - d->bd_hbuf =3D NULL; - d->bd_hlen =3D 0; - bpf_buf_reclaimed(d); + if (d->bd_hbuf =3D=3D NULL) { + printf("bpfread: lost race: bd_hbuf=3D%p bd_sbuf=3D%p = bd_fbuf=3D%p\n", + d->bd_hbuf, d->bd_sbuf, d->bd_fbuf); + } else { + d->bd_fbuf =3D d->bd_hbuf; + d->bd_hbuf =3D NULL; + d->bd_hlen =3D 0; + bpf_buf_reclaimed(d); + } BPFD_UNLOCK(d); =20 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=