From jin@iss-p2.lbl.gov  Thu Feb 10 13:18:57 2000
Return-Path: <jin@iss-p2.lbl.gov>
Received: from iss-p2.lbl.gov (iss-p2.lbl.gov [131.243.2.148])
	by builder.freebsd.org (Postfix) with ESMTP id E5646452B
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 10 Feb 2000 13:18:56 -0800 (PST)
Received: (from jin@localhost)
	by iss-p2.lbl.gov (8.9.3/8.9.3) id NAA00545;
	Thu, 10 Feb 2000 13:18:37 -0800 (PST)
	(envelope-from jin)
Message-Id: <200002102118.NAA00545@iss-p2.lbl.gov>
Date: Thu, 10 Feb 2000 13:18:37 -0800 (PST)
From: Jin Guojun (FTG staff) <jin@iss-p2.lbl.gov>
Reply-To: j_guojun@lbl.gov
To: FreeBSD-gnats-submit@freebsd.org
Subject: Bad comparsion expression in bpf_filter.c
X-Send-Pr-Version: 3.2

>Number:         16644
>Category:       kern
>Synopsis:       [bpf] [patch] Bad comparison expression in bpf_filter.c
>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:   Thu Feb 10 13:20:02 PST 2000
>Closed-Date:    
>Last-Modified:  Tue Jul 10 03:41:32 UTC 2012
>Originator:     Jin Guojun (FTG staff)
>Release:        FreeBSD 4.0-CURRENT
>Organization:
>Environment:

	FreeBSD 4.0-CURRENT for release
	It acturally exists in 3.x, but I would not bother for 3.x, but
	really want it to be fix before 4.0-RELEASE in 4.0.

>Description:

I seems to remember there was a discussion about this expression change
from the original one at a point, but since I had not time to look at it,
I always use my original to replace the FreeBSD one here.
Since the original one had a little trouble to compile under 4.0-CURRENT now,
JUST samll thing that KERNEL changed to _KERNEL, I decide to use the FreeBSD
modified one, but got completed failure. The reason will discuss here:

segment of code in /sys/net/bpf_filter.c: (I added two printf to show info.)
...
	case BPF_LD|BPF_H|BPF_ABS:
        	k = pc->k;
        printf("k = %d, buflen = %d, b-k %d : k>b %d, s > b-k %d : reg % d\n",
		 k, buflen, buflen-k, k > buflen,
                 sizeof(short) > buflen - k, k + sizeof(short) > buflen);
        { int   K = k;
        printf("K = %d, buflen = %d, b-K %d : K>b %d, s > b-K %d : reg % d\n",
                K, buflen, buflen-K, K > buflen,
                sizeof(short) > buflen - K, K + sizeof(short) > buflen) ;
        }
	/* real problem is HERE		XXX	*/
        if (k > buflen || sizeof(short) > buflen - k) {

	...
	} else	{
	...
	}

[1] /kernel: k = 6, buflen = 40, b-k 34 : k>b 0, s > b-k 0 : reg 0
[2] /kernel: K = 6, buflen = 40, b-K 34 : K>b 0, s > b-K 0 : reg 0
[3]/kernel: k = -1, buflen = 40, b-k 41 : k>b 1, s > b-k 0 : reg 0
[4]/kernel: K = -1, buflen = 40, b-K 41 : K>b 1, s > b-K 0 : reg 0


Two problems here:
(1)	this expression is not been compiled correctly somehow by compiler.
	in output line [4]; K>b shoud be false 0, but not true 1.

(2)	Critical part:
		This expression broken the original design in two place.

	<1>	Since you defined all variables are u_int##, then you
		mean every var is positive #, then above expression is
		bogus.

		Translate this expression to real #:

			(A > 10 || 2 > 10 - A)
		===	(A > 10 || A > 10 - 2)
		===	(A > 10 || A > 8)
		===	(A > 8)

		Here is go back to the original expression
			(A + 2 > 10)
		===	(k + sizeof(short) > buflen)

	<2>	The negtive k or pc->k was intended to be used n BPF filter.
		This seems too have changed in bpf.h from int to u_int.

	Also, the (k > buflen || sizeof(short) > buflen - k) increasing
	the complexity in brach statement which is very CPU cost.
	BPF is designed for light weight process.

This incorrect expression has replaced every original expression through
the bpf_filter.c. It need to alter back.

>How-To-Repeat:

	

>Fix:
	If whoever make expression change agrees my explaination, please
	reply this PR before the formal release. Make sure we have time
	to change it back. Then I will send the "diff -c" for the patch.


>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: mike 
State-Changed-When: Sat Jul 21 13:01:31 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=16644 

From: Mike Barcroft <mike@FreeBSD.org>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/16644: Bad comparsion expression in bpf_filter.c
Date: Sat, 21 Jul 2001 18:58:35 -0400

 Adding to Audit-Trail.
 
 On Sat, Jul 21, 2001 at 03:19:21PM -0700, Jin Guojun wrote:
 > mike@FreeBSD.org wrote:
 > 
 > > Synopsis: Bad comparsion expression in bpf_filter.c
 > >
 > > State-Changed-From-To: open->feedback
 > > State-Changed-By: mike
 > > State-Changed-When: Sat Jul 21 13:01:31 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=16644
 > 
 > I will make investigate on this one sometime later (probably in a month).
 > 
 >     -Jin
 > 
 > 

From: Bruce Evans <bde@zeta.org.au>
To: "Jin Guojun[ITG]" <j_guojun@lbl.gov>
Cc: <mike@FreeBSD.ORG>, <freebsd-gnats-submit@FreeBSD.ORG>
Subject: Re: kern/16644: Bad comparsion expression in bpf_filter.c
Date: Sat, 1 Sep 2001 19:01:12 +1000 (EST)

 On Fri, 31 Aug 2001, Jin Guojun[ITG] wrote:
 
 > It is still there. I have replied this to the discussion and
 > got no response. For example, in line 220, ">" line is equal to
 > if (k > buflen || k + sizeof(int32_t) > buflen) {
 > or
 > if (k > buflen || k > buflen - sizeof(int32_t)) {
 >
 > if K > BUFLEN then K must > BUFLEN - 4
 
 This doesn't follow.  Example: K = 4U, BUFLEN = 2U, BUFLEN - 4 = UINT_MAX - 2.
 BUFLEN - 4 overflows.  I'm not sure if this overflow can give undefined
 behaviour instead of UINT_MAX - 2.
 
 > so we only want to judge if (k > buflen - sizeof(int32_t)) {
 > which is the "<" of line 220 -- if (k + sizeof(int32_t) > buflen) {
 >
 > Right? rests are ditto. The original design is correct.
 
 No.  Examples:
 
 (1) k = UINT_MAX - 2, buflen = 8U.  Then k + sizeof(int32_t) = 2U, which
     is <= buflen.  But k is much larger than buflen - sizeof(int32_t).
     Here arithmetic overflow occurs in the buffer overflow check and
     the buffer overflow check gives the wrong result.  The overflow
     checks were rewritten in FreeBSD to avoid arithmetic overflow.
 (2) k = -2 (signed int, as in the original design), buflen = 8U.  Then
     k + sizeof(int32_t) = 2U (no change).  This is the same overflow as
     in (1).  k first gets promoted to UINT_MAX - 2, then the addition
     overflows.
 
 > The real problem is at line 550. K is outside 0-BPF_MEMWORDS, not just >.
 > ...
 > 547c550
 > <                   (p->k >= BPF_MEMWORDS || p->k < 0))
 > ---
 > >                   p->k >= BPF_MEMWORDS)
 
 This patch is reversed (it gives the FreeBSD change).  Here FreeBSD
 simplified the check instead of complicating it.  p->k < 0 can't happen
 because p->k is unsigned.  The compiler should optimize away the
 complication and generate identical code, but it migh warn about a
 bogus comparison of an unsigned value with 0.
 
 Bruce
 

From: Jin Guojun <j_guojun@lbl.gov>
To: Bruce Evans <bde@zeta.org.au>
Cc: mike@FreeBSD.ORG, freebsd-gnats-submit@FreeBSD.ORG
Subject: Re: kern/16644: Bad comparsion expression in bpf_filter.c
Date: Tue, 04 Sep 2001 09:47:03 -0700

 Bruce Evans wrote:
 
 > On Fri, 31 Aug 2001, Jin Guojun[ITG] wrote:
 >
 > > It is still there. I have replied this to the discussion and
 > > got no response. For example, in line 220, ">" line is equal to
 > > if (k > buflen || k + sizeof(int32_t) > buflen) {
 > > or
 > > if (k > buflen || k > buflen - sizeof(int32_t)) {
 > >
 > > if K > BUFLEN then K must > BUFLEN - 4
 >
 > This doesn't follow.  Example: K = 4U, BUFLEN = 2U, BUFLEN - 4 = UINT_MAX - 2.
 > BUFLEN - 4 overflows.  I'm not sure if this overflow can give undefined
 > behaviour instead of UINT_MAX - 2.
 >
 > > so we only want to judge if (k > buflen - sizeof(int32_t)) {
 > > which is the "<" of line 220 -- if (k + sizeof(int32_t) > buflen) {
 > >
 > > Right? rests are ditto. The original design is correct.
 >
 > No.  Examples:
 >
 > (1) k = UINT_MAX - 2, buflen = 8U.  Then k + sizeof(int32_t) = 2U, which
 >     is <= buflen.  But k is much larger than buflen - sizeof(int32_t).
 >     Here arithmetic overflow occurs in the buffer overflow check and
 >     the buffer overflow check gives the wrong result.  The overflow
 >     checks were rewritten in FreeBSD to avoid arithmetic overflow.
 > (2) k = -2 (signed int, as in the original design), buflen = 8U.  Then
 >     k + sizeof(int32_t) = 2U (no change).  This is the same overflow as
 >     in (1).  k first gets promoted to UINT_MAX - 2, then the addition
 >     overflows.
 >
 > > The real problem is at line 550. K is outside 0-BPF_MEMWORDS, not just >.
 > > ...
 > > 547c550
 > > <                   (p->k >= BPF_MEMWORDS || p->k < 0))
 > > ---
 > > >                   p->k >= BPF_MEMWORDS)
 >
 > This patch is reversed (it gives the FreeBSD change).  Here FreeBSD
 > simplified the check instead of complicating it.  p->k < 0 can't happen
 > because p->k is unsigned.  The compiler should optimize away the
 > complication and generate identical code, but it migh warn about a
 > bogus comparison of an unsigned value with 0.
 >
 > Bruce
 
 The entire thing is messed up because the k is revised in the lastest BPF
 release.
 k is signed in the lastest release, and all above explanation is beased on signed
 K.
 It fixed the undefined overflow problem. Signed K does not work correctly,
 that is why you had above overflow issue. Overflow is wrong (not intended).
 Below is I explained to someone who asked about is:
 
 -------- original message -----------
 
 Jonathan Lemon wrote:
 
 > Hello -
 >
 >    I'm looking at bpf in FreeBSD, and it appears that our current
 > definition for the bpf_insn structure is:
 >
 >         struct bpf_insn {
 >                 u_short         code;
 >                 u_char          jt;
 >                 u_char          jf;
 >                 bpf_u_int32     k;
 >         };
 >
 > Note the last line has ``k'' being unsigned.  In the LBL releases,
 > it seems that there was a bit of confusion on the definition of
 > this field:
 >
 >         original berkeley release:      long
 >         LBL rev 1.34:                   bpf_u_int32
 >         LBL rev 1.36:                   bpf_int32
 >
 > Not having the RCS logs for the file, its not entirely clear
 > for the differing definitions here.  Is it intended that 'k'
 > may be negative in the bpf_insn structure?
 > --
 > Jonathan
 
 Yes, k may have negtive  value. I cannot recall when FreeBSD changed it,
 but I remember I read the email about it regarding some expression.
 They claimed make k non-negtive can fix their problem, I do not know what.
 
 Later sometime, I checked their expression which is bogus, so I send email
 to the bugs@freebsd.org, and explained that expression has nothing to do
 with int k or uint k. I asked them to change back because uint k breaks the
 kernel BPF functioning. No one was responsed.
 So, I put Kernel BPF patch on my web site in case some encounts problems.
 
     -Jin
 
 
 

From: Jin Guojun <j_guojun@lbl.gov>
To: Bruce Evans <bde@zeta.org.au>, mike@FreeBSD.ORG,
	freebsd-gnats-submit@FreeBSD.ORG
Cc:  
Subject: Re: kern/16644: Bad comparsion expression in bpf_filter.c
Date: Tue, 04 Sep 2001 11:01:44 -0700

 There was a typo in the previous message I sent.
 < It fixed the undefined overflow problem. Signed K does not work correctly,
 
 ^^^^^
 should be
 > It fixed the undefined overflow problem. Unsigned K does not work correctly,
 
 ^^^^^^^
 
     -Jin
 
 Jin Guojun wrote:
 
 > Bruce Evans wrote:
 >
 > > On Fri, 31 Aug 2001, Jin Guojun[ITG] wrote:
 > >
 > > > It is still there. I have replied this to the discussion and
 > > > got no response. For example, in line 220, ">" line is equal to
 > > > if (k > buflen || k + sizeof(int32_t) > buflen) {
 > > > or
 > > > if (k > buflen || k > buflen - sizeof(int32_t)) {
 > > >
 > > > if K > BUFLEN then K must > BUFLEN - 4
 > >
 > > This doesn't follow.  Example: K = 4U, BUFLEN = 2U, BUFLEN - 4 = UINT_MAX - 2.
 > > BUFLEN - 4 overflows.  I'm not sure if this overflow can give undefined
 > > behaviour instead of UINT_MAX - 2.
 > >
 > > > so we only want to judge if (k > buflen - sizeof(int32_t)) {
 > > > which is the "<" of line 220 -- if (k + sizeof(int32_t) > buflen) {
 > > >
 > > > Right? rests are ditto. The original design is correct.
 > >
 > > No.  Examples:
 > >
 > > (1) k = UINT_MAX - 2, buflen = 8U.  Then k + sizeof(int32_t) = 2U, which
 > >     is <= buflen.  But k is much larger than buflen - sizeof(int32_t).
 > >     Here arithmetic overflow occurs in the buffer overflow check and
 > >     the buffer overflow check gives the wrong result.  The overflow
 > >     checks were rewritten in FreeBSD to avoid arithmetic overflow.
 > > (2) k = -2 (signed int, as in the original design), buflen = 8U.  Then
 > >     k + sizeof(int32_t) = 2U (no change).  This is the same overflow as
 > >     in (1).  k first gets promoted to UINT_MAX - 2, then the addition
 > >     overflows.
 > >
 > > > The real problem is at line 550. K is outside 0-BPF_MEMWORDS, not just >.
 > > > ...
 > > > 547c550
 > > > <                   (p->k >= BPF_MEMWORDS || p->k < 0))
 > > > ---
 > > > >                   p->k >= BPF_MEMWORDS)
 > >
 > > This patch is reversed (it gives the FreeBSD change).  Here FreeBSD
 > > simplified the check instead of complicating it.  p->k < 0 can't happen
 > > because p->k is unsigned.  The compiler should optimize away the
 > > complication and generate identical code, but it migh warn about a
 > > bogus comparison of an unsigned value with 0.
 > >
 > > Bruce
 >
 > The entire thing is messed up because the k is revised in the lastest BPF
 > release.
 > k is signed in the lastest release, and all above explanation is beased on signed
 > K.
 > It fixed the undefined overflow problem. Signed K does not work correctly,
 > that is why you had above overflow issue. Overflow is wrong (not intended).
 > Below is I explained to someone who asked about is:
 >
 > -------- original message -----------
 >
 > Jonathan Lemon wrote:
 >
 > > Hello -
 > >
 > >    I'm looking at bpf in FreeBSD, and it appears that our current
 > > definition for the bpf_insn structure is:
 > >
 > >         struct bpf_insn {
 > >                 u_short         code;
 > >                 u_char          jt;
 > >                 u_char          jf;
 > >                 bpf_u_int32     k;
 > >         };
 > >
 > > Note the last line has ``k'' being unsigned.  In the LBL releases,
 > > it seems that there was a bit of confusion on the definition of
 > > this field:
 > >
 > >         original berkeley release:      long
 > >         LBL rev 1.34:                   bpf_u_int32
 > >         LBL rev 1.36:                   bpf_int32
 > >
 > > Not having the RCS logs for the file, its not entirely clear
 > > for the differing definitions here.  Is it intended that 'k'
 > > may be negative in the bpf_insn structure?
 > > --
 > > Jonathan
 >
 > Yes, k may have negtive  value. I cannot recall when FreeBSD changed it,
 > but I remember I read the email about it regarding some expression.
 > They claimed make k non-negtive can fix their problem, I do not know what.
 >
 > Later sometime, I checked their expression which is bogus, so I send email
 > to the bugs@freebsd.org, and explained that expression has nothing to do
 > with int k or uint k. I asked them to change back because uint k breaks the
 > kernel BPF functioning. No one was responsed.
 > So, I put Kernel BPF patch on my web site in case some encounts problems.
 >
 >     -Jin
 
State-Changed-From-To: feedback->closed 
State-Changed-By: sheldonh 
State-Changed-When: Wed Jan 30 01:20:33 PST 2002 
State-Changed-Why:  
Automatic feedback timeout.  This PR remained unchanged in the feedback 
state for more than 4 months. 

If additional feedback that warrants the re-opening of this PR is 
available but not included in the audit trail, please include the 
feedback in a reply to this message (preserving the Subject line) and 
ask that the PR be re-opened. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=16644 
State-Changed-From-To: closed->open 
State-Changed-By: dwmalone 
State-Changed-When: Wed Jan 30 09:21:10 PST 2002 
State-Changed-Why:  
It seems there is still an issue here. We probably need Bruce 
or Jonathan to say what the next step is. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=16644 
Responsible-Changed-From-To: freebsd-bugs->csjp 
Responsible-Changed-By: kmacy 
Responsible-Changed-When: Fri Nov 16 08:40:18 UTC 2007 
Responsible-Changed-Why:  

Please confirm that there is an issue. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=16644 
Responsible-Changed-From-To: csjp->dwmalone 
Responsible-Changed-By: dwmalone 
Responsible-Changed-When: Thu Feb 21 10:14:56 UTC 2008 
Responsible-Changed-Why:  
I'll grab this PR and check what issues remain. I think I have 
enough of a handle on the problem to understand what's going on. 

David. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=16644 
Responsible-Changed-From-To: dwmalone->freebsd-bugs 
Responsible-Changed-By: eadler 
Responsible-Changed-When: Tue Jul 10 03:41:31 UTC 2012 
Responsible-Changed-Why:  
over to the pool (approved by bugmeister) 

http://www.freebsd.org/cgi/query-pr.cgi?pr=16644 
>Unformatted:
