From leres@hot.ee.lbl.gov Thu Jul  1 19:51:20 1999
Return-Path: <leres@hot.ee.lbl.gov>
Received: from hot.ee.lbl.gov (hot.ee.lbl.gov [131.243.1.42])
	by hub.freebsd.org (Postfix) with ESMTP id AB38414CEF
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  1 Jul 1999 19:51:18 -0700 (PDT)
	(envelope-from leres@hot.ee.lbl.gov)
Received: (from leres@localhost)
	by hot.ee.lbl.gov (8.9.2/8.9.2) id TAA28620;
	Thu, 1 Jul 1999 19:51:18 -0700 (PDT)
Message-Id: <199907020251.TAA28620@hot.ee.lbl.gov>
Date: Thu, 01 Jul 1999 19:51:18 PDT
From: Craig Leres <leres@ee.lbl.gov>
Sender: leres@hot.ee.lbl.gov
To: FreeBSD-gnats-submit@freebsd.org
Cc: vern@ee.lbl.gov (Vern Paxson),
	mccanne@eecs.berkeley.edu (Steven McCanne)
Subject: [PATCH] bpf_filter() broken
X-Send-Pr-Version: 3.2

>Number:         12484
>Category:       kern
>Synopsis:       [PATCH] bpf_filter() broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul  1 20:00:01 PDT 1999
>Closed-Date:    Sat Jul 21 10:29:25 PDT 2001
>Last-Modified:  Sat Jul 21 10:30:47 PDT 2001
>Originator:     Craig Leres
>Release:        FreeBSD 3.2-RELEASE i386
>Organization:
Lawrence Berkeley National Laboratory
>Environment:

>Description:

	Revision 1.12 of sys/bpf_filter.c breaks certain packet filters.

>How-To-Repeat:

	We noticed after upgrading our security system from
	3.0-980414-SNAP to 3.2-RELEASE that the tcpdump filter:
	
	    'tcp[13] & 0x7 != 0'

	would not capture such packets. Debugging turned up a problem
	in this case:

	    case BPF_LD|BPF_B|BPF_IND:
		    k = X + pc->k;
		    if (pc->k >= buflen || X >= buflen - k) {
	
	The conditional can be rewritten with "k" expanded:

		    if (pc->k >= buflen || X >= buflen - (X + pc->k)) {

	which is the same as:

		    if (pc->k >= buflen || X + X + pc->k >= buflen) {
	
	and is clearly wrong.

	Other cases where "k" is initialized to "X + pc->k" appear to
	either be broken or at least contain unnecessary checks.

	We consider this a serious bug because it breaks security
	monitoring software (including our "bro" package).

>Fix:
	
	The appended context changes are against 1.13 (it looks like
	3.2-RELEASE shipped with 1.12).

RCS file: RCS/bpf_filter.c,v
retrieving revision 1.3
diff -c -r1.3 bpf_filter.c
*** /tmp/,RCSt1z29845	Thu Jul  1 19:43:31 1999
- --- bpf_filter.c	Thu Jul  1 19:42:40 1999
***************
*** 217,223 ****
  
  		case BPF_LD|BPF_W|BPF_ABS:
  			k = pc->k;
! 			if (k > buflen || sizeof(int32_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
- --- 217,223 ----
  
  		case BPF_LD|BPF_W|BPF_ABS:
  			k = pc->k;
! 			if (sizeof(int32_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
***************
*** 241,247 ****
  
  		case BPF_LD|BPF_H|BPF_ABS:
  			k = pc->k;
! 			if (k > buflen || sizeof(int16_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
- --- 241,247 ----
  
  		case BPF_LD|BPF_H|BPF_ABS:
  			k = pc->k;
! 			if (sizeof(int16_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
***************
*** 285,292 ****
  
  		case BPF_LD|BPF_W|BPF_IND:
  			k = X + pc->k;
! 			if (pc->k > buflen || X > buflen - pc->k ||
! 			    sizeof(int32_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
- --- 285,291 ----
  
  		case BPF_LD|BPF_W|BPF_IND:
  			k = X + pc->k;
! 			if (sizeof(int32_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
***************
*** 310,317 ****
  
  		case BPF_LD|BPF_H|BPF_IND:
  			k = X + pc->k;
! 			if (X > buflen || pc->k > buflen - X ||
! 			    sizeof(int16_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
- --- 309,315 ----
  
  		case BPF_LD|BPF_H|BPF_IND:
  			k = X + pc->k;
! 			if (sizeof(int16_t) > buflen - k) {
  #ifdef KERNEL
  				int merr;
  
***************
*** 330,336 ****
  
  		case BPF_LD|BPF_B|BPF_IND:
  			k = X + pc->k;
! 			if (pc->k >= buflen || X >= buflen - k) {
  #ifdef KERNEL
  				register struct mbuf *m;
  
- --- 328,334 ----
  
  		case BPF_LD|BPF_B|BPF_IND:
  			k = X + pc->k;
! 			if (k >= buflen) {
  #ifdef KERNEL
  				register struct mbuf *m;
  

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBN3wpAr2JLbUEFcrxAQFg8wP8Cs1hzHa/s6VjDMQFy2SSbM8oH5lr272A
/MMSl8tlreDcjZUcIhndB8DwVaQlTgMkZG+sAuxvCh4gglFOczxwk/oeikNuUFlt
oCahmi/LjnTPAn/VRKvvw+LPA21mZ940V87sOdqhpE/PtOc5s8zNa0oGP0KWXsb/
3IHfY3c49qI=
=I7G8
-----END PGP SIGNATURE-----

>Release-Note:
>Audit-Trail:

From: Bruce Evans <bde@zeta.org.au>
To: eivind@freebsd.org, FreeBSD-gnats-submit@freebsd.org,
	leres@ee.lbl.gov
Cc: mccanne@eecs.berkeley.edu, vern@ee.lbl.gov
Subject: Re: kern/12484: [PATCH] bpf_filter() broken
Date: Fri, 2 Jul 1999 17:00:13 +1000

 >	would not capture such packets. Debugging turned up a problem
 >	in this case:
 >
 >	    case BPF_LD|BPF_B|BPF_IND:
 >		    k = X + pc->k;
 >		    if (pc->k >= buflen || X >= buflen - k) {
 >	
 >	The conditional can be rewritten with "k" expanded:
 >
 >		    if (pc->k >= buflen || X >= buflen - (X + pc->k)) {
 >
 >	which is the same as:
 >
 >		    if (pc->k >= buflen || X + X + pc->k >= buflen) {
 >	
 >	and is clearly wrong.
 
 Oops.  This should have been:
 
 		if (pc->k >= buflen || X >= buflen - p->k) {
 
 which is the same modulo possible truncation mod 2^32 as each of the
 following:
 
 		if (pc->k >= buflen || X + p->k >= buflen) {
 		if (pc->k >= buflen || k >= buflen) {
 		if (k >= buflen) {
 
 The latter is the conditinal in rev.1.11.
 
 >	Other cases where "k" is initialized to "X + pc->k" appear to
 >	either be broken or at least contain unnecessary checks.
 
 The other cases seem to be correct.  The extra checks relative to 1.11
 are to detect truncation for weird values of X and/or pc->k, e.g., X =
 4, pc->k = (u_int32_t)-5 gives X + pc->k = 3 if u_int32_t is u_int.
 I don't know if this much overflow checking is justified.
 
 >	The appended context changes are against 1.13 (it looks like
 >	3.2-RELEASE shipped with 1.12).
 >
 >RCS file: RCS/bpf_filter.c,v
 >retrieving revision 1.3
 >diff -c -r1.3 bpf_filter.c
 >*** /tmp/,RCSt1z29845	Thu Jul  1 19:43:31 1999
 >- --- bpf_filter.c	Thu Jul  1 19:42:40 1999
 >***************
 >*** 217,223 ****
 >  
 >  		case BPF_LD|BPF_W|BPF_ABS:
 >  			k = pc->k;
 >! 			if (k > buflen || sizeof(int32_t) > buflen - k) {
 >  #ifdef KERNEL
 >  				int merr;
 >  
 >- --- 217,223 ----
 >  
 >  		case BPF_LD|BPF_W|BPF_ABS:
 >  			k = pc->k;
 >! 			if (sizeof(int32_t) > buflen - k) {
 >  #ifdef KERNEL
 >  				int merr;
 >  
 
 If you reduce the amount of overflow checking back to 1.11 levels, then
 change the checks back to the ones in 1.11. e.g.,
 
  			if (k + sizeof(int32_t) > buflen) {
 
 The check:
 
 			if (sizeof(int32_t) > buflen - k) {
 
 has fatal overflow problems if k > buflen and u_int32_t is u_int.
 
 Bruce
 
State-Changed-From-To: open->feedback 
State-Changed-By: mike 
State-Changed-When: Fri Jul 20 16:11:34 PDT 2001 
State-Changed-Why:  

Does this problem still occur in newer versions of FreeBSD, 
such as 4.3-RELEASE? 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=12484 

From: Mike Barcroft <mike@FreeBSD.org>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/12484: [PATCH] bpf_filter() broken
Date: Sat, 21 Jul 2001 13:18:45 -0400

 Adding this to the Audit-Trail.
 
 On Sat, Jul 21, 2001 at 10:40:39PM +1000, Bruce Evans wrote:
 > I kept the following private mail about this:
 > 
 > > From bde@zeta.org.au Wed Aug 16 03:34:22 2000 +1000
 > > Date: Wed, 16 Aug 2000 03:34:20 +1000 (EST)
 > > From: Bruce Evans <bde@zeta.org.au>
 > > X-Sender: bde@besplex.bde.org
 > > To: Johan Karlsson <k@numeri.campus.luth.se>
 > > Subject: Re: PR 12484 and your commit rev 1.14 of src/sys/net/bpf_filter.c
 > > In-Reply-To: <200008150757.JAA13997@numeri.campus.luth.se>
 > > Message-ID: <Pine.BSF.4.21.0008160316500.2104-100000@besplex.bde.org>
 > > MIME-Version: 1.0
 > > Content-Type: TEXT/PLAIN; charset=US-ASCII
 > > Status: O
 > > X-Status: 
 > > X-Keywords:                  
 > > X-UID: 859
 > > 
 > > On Tue, 15 Aug 2000, Johan Karlsson wrote:
 > > 
 > > > Hi Bruce
 > > > It seems you commited a fix for PR 12484 in rev 1.14 of 
 > > > src/sys/net/bpf_filter.c.
 > > > 
 > > > Can the PR be closed or should the 
 > > > "inconsistent and probably unnecessarily pessimal" checks
 > > > be fixed first?
 > > 
 > > I don't know bpf well enough to be sure of more than the formal
 > > correctness of the fix.  The people on the Cc line of the PR
 > > should know :-).  Craig Leres didn't seem to have any objections.
 > > 
 > > The efficiency issues were more interesting on old (slow) hardware.
 > > 
 > > PR 16644 is also about this.  Its author is also at LBL, but seems
 > > to be as confused as usual.
 > > 
 > > Bruce
 > 
 > Bruce
 > 
State-Changed-From-To: feedback->closed 
State-Changed-By: mike 
State-Changed-When: Sat Jul 21 10:29:25 PDT 2001 
State-Changed-Why:  

I'm satisfied the originator's problem has been solved. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=12484 
>Unformatted:
 -----BEGIN PGP SIGNED MESSAGE-----
 
