From owner-freebsd-bugs@FreeBSD.ORG Wed Sep 1 08:00:12 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0E90710656A7 for ; Wed, 1 Sep 2010 08:00:12 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id C4EE08FC1D for ; Wed, 1 Sep 2010 08:00:11 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o8180BU8092822 for ; Wed, 1 Sep 2010 08:00:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o8180BEp092773; Wed, 1 Sep 2010 08:00:11 GMT (envelope-from gnats) Resent-Date: Wed, 1 Sep 2010 08:00:11 GMT Resent-Message-Id: <201009010800.o8180BEp092773@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Guy Harris Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7960A10656B9 for ; Wed, 1 Sep 2010 07:58:02 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 4E15B8FC0A for ; Wed, 1 Sep 2010 07:58:02 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o817w1V5014027 for ; Wed, 1 Sep 2010 07:58:01 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id o817w11s014026; Wed, 1 Sep 2010 07:58:01 GMT (envelope-from nobody) Message-Id: <201009010758.o817w11s014026@www.freebsd.org> Date: Wed, 1 Sep 2010 07:58:01 GMT From: Guy Harris To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: misc/150176: p->cc can go negative in libpcap X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Sep 2010 08:00:12 -0000 >Number: 150176 >Category: misc >Synopsis: p->cc can go negative in libpcap >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Sep 01 08:00:10 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Guy Harris >Release: Top of CVS tree >Organization: >Environment: >Description: In pcap_read_bpf(), ep is set based on the return value of read(), but read() from a BPF device doesn't necessarily return a value that's a multiple of the alignment value for BPF_WORDALIGN(). However, whenever we increment bp, we round up the increment value by a value rounded up by BPF_WORDALIGN(), so we could increment bp past ep after processing the last packet in the buffer. >How-To-Repeat: Run a program that opens a capture device with a timeout of 0, in a loop, calls pcap_dispatch() with a cnt argument of 1, and reports when it returns a value of 0. The timeout of 0 means that the read() that libpcap does shouldn't return until there's packet data, so a timeout won't cause pcap_dispatch() to return 0. Do a large amount of network data transfer, to fill up the BPF bucket; notice that, on occasion, the program will report that pcap_dispatch() returns 0. >Fix: Patch attached with submission follows: diff --git a/pcap-bpf.c b/pcap-bpf.c index 666acf9..bcbfbef 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -955,14 +955,28 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * processed so far. */ if (p->break_loop) { + p->bp = bp; + p->cc = ep - bp; + /* + * ep is set based on the return value of read(), + * but read() from a BPF device doesn't necessarily + * return a value that's a multiple of the alignment + * value for BPF_WORDALIGN(). However, whenever we + * increment bp, we round up the increment value by + * a value rounded up by BPF_WORDALIGN(), so we + * could increment bp past ep after processing the + * last packet in the buffer. + * + * We treat ep < bp as an indication that this + * happened, and just set p->cc to 0. + */ + if (p->cc < 0) + p->cc = 0; if (n == 0) { p->break_loop = 0; return (PCAP_ERROR_BREAK); - } else { - p->bp = bp; - p->cc = ep - bp; + } else return (n); - } } caplen = bhp->bh_caplen; @@ -1014,6 +1028,11 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; + /* + * See comment above about p->cc < 0. + */ + if (p->cc < 0) + p->cc = 0; return (n); } } else { >Release-Note: >Audit-Trail: >Unformatted: