From edwin@mavetju.org  Thu Oct 16 01:07:47 2008
Return-Path: <edwin@mavetju.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 6228D1065698
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Oct 2008 01:07:47 +0000 (UTC)
	(envelope-from edwin@mavetju.org)
Received: from k7.mavetju.org (ppp121-44-151-188.lns10.syd7.internode.on.net [121.44.151.188])
	by mx1.freebsd.org (Postfix) with ESMTP id 127E48FC15
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Oct 2008 01:07:47 +0000 (UTC)
	(envelope-from edwin@mavetju.org)
Received: by k7.mavetju.org (Postfix, from userid 1001)
	id 2B29945039; Thu, 16 Oct 2008 11:49:35 +1100 (EST)
Message-Id: <20081016004935.2B29945039@k7.mavetju.org>
Date: Thu, 16 Oct 2008 11:49:35 +1100 (EST)
From: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
Reply-To: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: src/sys/netinet - crc32c calculation at sctp_crc32.c
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         128134
>Category:       kern
>Synopsis:       [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    rrs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 16 01:10:01 UTC 2008
>Closed-Date:    Tue Mar 10 03:45:01 UTC 2009
>Last-Modified:  Tue Mar 10 03:45:01 UTC 2009
>Originator:     Yehuda Sadeh Weinraub
>Release:        FreeBSD 7.1-BETA i386
>Organization:
-
>Environment:


>Description:

It looks like there is some bug in the crc32c calculation at sctp_crc32.c.
The update_crc32() does the following:
   
    ...
    offset = ((uintptr_t) buffer) & 0x3;
    return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, offset));
   
Now, note that it passes the 'offset' parameter. However, the
sctp_crc32c_sb8_64_bit() treats the 4th parameter as init_bytes. This is
wrong. Also it does the following:
   
   running_length = ((length - init_bytes) / 8) * 8;
   
Now, if init_bytes is 3 and length is 1, running_length will overlap.
   
The following patch seems to fix it.
   
Yehuda

>How-To-Repeat:
>Fix:

--- a/src/common/sctp_crc32.c
+++ b/src/common/sctp_crc32.c
@@ -518,12 +518,18 @@ static uint32_t sctp_crc32c_sb8_64_bit(uint32_t crc,
     unsigned char const *p_buf,
     uint32_t length,
-    uint32_t init_bytes)
+    uint32_t offset)
 {
        uint32_t li;
        uint32_t term1, term2;
        uint32_t running_length;
        uint32_t end_bytes;
+       uint32_t init_bytes;
+
+       init_bytes = (4-offset) & 0x3;
+
+       if (init_bytes > length)
+               init_bytes = length;

        running_length = ((length - init_bytes) / 8) * 8;
        end_bytes = length - init_bytes - running_length;

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->rrs 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Thu Oct 16 01:15:33 UTC 2008 
Responsible-Changed-Why:  
Over to Randall for his comments on it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=128134 

From: Randall Stewart <rrs@lakerest.net>
To: bug-followup@FreeBSD.org, yehudasa@gmail.com
Cc:  
Subject: Re: kern/128134: [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
Date: Sat, 18 Oct 2008 07:26:26 -0400

 Yehuda:
 
 I agree its a problem, interesting it has
 not surfaced yet.
 
 I will fix this later this AM when I get to my office.. I have
 another couple of small bug fixes with respect to the socket API
 that need to go into 8.
 
 Note I will not use your patch... since I would like
 to keep the code from Intel intact as much as possible.
 Instead I will take a slightly different approach... i.e.
 making the changes to the calling function to properly
 convert offset into an init_bytes... i.e. the number of
 bytes to an even word boundary...
 
 I guess this tells you that pretty much we always are
 are hitting crc32c aligned on a 4 byte boundary which
 makes sense when you think about the way SCTP requires
 4 byte alignment..
 
 
 R
 ------------------------------
 Randall Stewart
 803-317-4952 (cell)
 803-345-0391(direct)
 

From: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
To: "Randall Stewart" <rrs@lakerest.net>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128134: [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
Date: Sun, 19 Oct 2008 23:58:54 -0700

 ------=_Part_56651_6346307.1224485934091
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 Hi,
 
 
 > I agree its a problem, interesting it has
 > not surfaced yet.
 >
 > I will fix this later this AM when I get to my office.. I have
 > another couple of small bug fixes with respect to the socket API
 > that need to go into 8.
 
 
    I looked at your fix and I haven't really tried this out, but it looks
 like it only fixes half of the problem. Whenever to_even_words greater than
 length, you'd get a buffer overflow after that:
     end_bytes = length - init_bytes - running_length;
 
 maybe doing the following will do the trick:
 
 to_even_word = min(4 - (((uintptr_t) buffer) & 0x3), length);
 
 
 Yehuda
 
 ------=_Part_56651_6346307.1224485934091
 Content-Type: text/html; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 <div dir="ltr"><br>Hi,<br><div class="gmail_quote"><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
 I agree its a problem, interesting it has<br>
 not surfaced yet.<br>
 <br>
 I will fix this later this AM when I get to my office.. I have<br>
 another couple of small bug fixes with respect to the socket API<br>
 that need to go into 8.</blockquote><div><br>&nbsp;&nbsp; I looked at your fix and I haven&#39;t really tried this out, but it
 looks like it only fixes half of the problem. Whenever to_even_words
 greater than length, you&#39;d get a buffer overflow after that:<br>&nbsp;&nbsp;&nbsp; end_bytes = length - init_bytes - running_length;<br><br>
 
 maybe doing the following will do the trick:<br><br>
 
 to_even_word = min(4 - (((uintptr_t) buffer) &amp; 0x3), length);<br><br><br>Yehuda<br></div></div><br></div>
 
 ------=_Part_56651_6346307.1224485934091--

From: Randall Stewart <rrs@lakerest.net>
To: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128134: [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
Date: Mon, 20 Oct 2008 03:46:00 -0400

 Yehuda:
 
 
 The sliceing 8's algo needs the number of bytes to get to a
 4 byte boundary.
 
 So some observations:
 
 1) First of all most all of our offsets are always adjusted to even word
     boundaries.. thats why in FreeBSD we have not seen this. Other  
 platforms (such
     as some of the user space stuff that is going on) may well see this.
 
 2) Consider the 4 posibilites:
 
 Address NNNNN0 <----Even word
          NNNNN1
          NNNNN2
          NNNNN3
          NNNNN4 <----Even word
          NNNNN5
          NNNNN6
          NNNNN7
          NNNNN8 <----Even word
 
 First as I said the mbuf routines we use will IMO almost always return  
 NNNNN0/4 or 8.. thus
 the bug is rather obtuse. But lets consider the change I made:
 
 to_even_word= 4 - (((uintptr_t) buffer) & 0x03)
 
 Lets take NNNNN1 plug it in:
     we get to_even_word = 4 - 1 i.e. 3.
     taking NNNNN1 adding 3 to its gets us to NNNN4 which is an even  
 word  boundar.
 
 Lets take NNNNN2 plug it in..
        result 2
        yes it gets us to an even word
 
 Lets take NNNN3 plug it in..
        result 1
        yes it gets us to an even word ...
 
 Conclusion:
 
 a) Yes it fixes the bug.
 b) meta-comment, it would be hard for me to imagine finding this bug  
 since most
     of the mbuf macro's place you on even word boundaries for  
 beginnings of
     mbufs i.e. we use M_ALIGN which does
        (m)->m_data += (MLEN - (len)) & ~(sizeof (long) -1)
     which ALWAYS puts you on an even word boundary if long == 4 or 8...
     And SCTP itself REQUIRES padding to even word boundaries for ALL  
 data
     chunks. Basically unless you are doing using the CRC algorithm in  
 other
     than kernel space, I think you would be HARD PRESSED to show me that
     this is really happening...
 
     In fact if you could show me that it is happening in a FreeBSD 7.0  
 kernel I would
     be very surprised... can you show me this?
 
 
 R
 
 On Oct 20, 2008, at 2:58 AM, Yehuda Sadeh Weinraub wrote:
 
 >
 > Hi,
 >
 >
 > I agree its a problem, interesting it has
 > not surfaced yet.
 >
 > I will fix this later this AM when I get to my office.. I have
 > another couple of small bug fixes with respect to the socket API
 > that need to go into 8.
 >
 >    I looked at your fix and I haven't really tried this out, but it  
 > looks like it only fixes half of the problem. Whenever to_even_words  
 > greater than length, you'd get a buffer overflow after that:
 >     end_bytes = length - init_bytes - running_length;
 >
 > maybe doing the following will do the trick:
 >
 > to_even_word = min(4 - (((uintptr_t) buffer) & 0x3), length);
 >
 >
 > Yehuda
 >
 
 ------------------------------
 Randall Stewart
 803-317-4952 (cell)
 803-345-0391(direct)
 

From: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
To: "Randall Stewart" <rrs@lakerest.net>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128134: [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
Date: Mon, 20 Oct 2008 06:43:44 -0700

 ------=_Part_60697_11995402.1224510224205
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 I agree with everything you said. However, consider the following scenario
 (even if not possible currently in FreeBSD):
 
 to_even_word <- 3 (or something greater than length)
 length <- 1
 
 Now, at the sctp_crc32c_sb8_64_bit:
 
 running_length = ((length - init_bytes) / 8) * 8;
 end_bytes = length - init_bytes - running_length;
 
 since init_bytes is actually to_even_words, end_bytes will overlap, and the
 following will happen, reading outside the table's boundaries (for almost
 4GB):
 
 for (li = 0; li < end_bytes; li++)
         crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^
             (crc >> 8);
 
 
 Regards,
 Yehuda
 
 ------=_Part_60697_11995402.1224510224205
 Content-Type: text/html; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 <div dir="ltr">I agree with everything you said. However, consider the following scenario (even if not possible currently in FreeBSD):<br><br>to_even_word &lt;- 3 (or something greater than length)<br>length &lt;- 1<br><br>
 Now, at the sctp_crc32c_sb8_64_bit:<br><br>running_length = ((length - init_bytes) / 8) * 8;<br>end_bytes = length - init_bytes - running_length;<br><br>since init_bytes is actually to_even_words, end_bytes will overlap, and the following will happen, reading outside the table&#39;s boundaries (for almost 4GB):<br>
 <br>for (li = 0; li &lt; end_bytes; li++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) &amp; 0x000000FF] ^<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (crc &gt;&gt; 8);<br><br><br>Regards,<br>Yehuda<br></div>
 
 ------=_Part_60697_11995402.1224510224205--

From: Randall Stewart <rrs@lakerest.net>
To: "Yehuda Sadeh Weinraub" <yehudasa@gmail.com>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128134: [netinet] [patch] src/sys/netinet - crc32c calculation at sctp_crc32.c
Date: Mon, 20 Oct 2008 12:14:46 -0400

 Yehuda:
 
 Please name me ONE SCTP packet that can be smaller than 4 bytes?
 
 What you are pointing out is a basic assumption in the
 slicing 8 algorithm.. i.e the length is always >=4bytes.
 
 For SCTP the SMALLEST you could possibly EVER EVER EVER EVER
 have length is a common header + a single chunk... a cookie-ack
 is often this... and that would come out at 16 bytes.
 
 I will not make changes for this type of condition since it is
 completely fabricated and not valid.
 
 R
 
 On Oct 20, 2008, at 9:43 AM, Yehuda Sadeh Weinraub wrote:
 
 > I agree with everything you said. However, consider the following  
 > scenario (even if not possible currently in FreeBSD):
 >
 > to_even_word <- 3 (or something greater than length)
 > length <- 1
 >
 > Now, at the sctp_crc32c_sb8_64_bit:
 >
 > running_length = ((length - init_bytes) / 8) * 8;
 > end_bytes = length - init_bytes - running_length;
 >
 > since init_bytes is actually to_even_words, end_bytes will overlap,  
 > and the following will happen, reading outside the table's  
 > boundaries (for almost 4GB):
 >
 > for (li = 0; li < end_bytes; li++)
 >         crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^
 >             (crc >> 8);
 >
 >
 > Regards,
 > Yehuda
 
 ------------------------------
 Randall Stewart
 803-317-4952 (cell)
 803-345-0391(direct)
 
State-Changed-From-To: open->patched  
State-Changed-By: brucec 
State-Changed-When: Thu Jan 29 18:05:35 UTC 2009 
State-Changed-Why:  
Patched in HEAD, rev 1.9 of sctp_crc32.c. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=128134 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/128134: commit references a PR
Date: Thu, 12 Feb 2009 18:03:06 +0000 (UTC)

 Author: rrs
 Date: Thu Feb 12 18:02:46 2009
 New Revision: 188525
 URL: http://svn.freebsd.org/changeset/base/188525
 
 Log:
   MFC of 184027:
   
   Reported by Yehuda Weinraub (yehudasa@gamil.com) - CRC32C algorithm
   uses incorrect init_bytes value. It SHOULD have the number
   of bytes to get to a 4 byte boundary.
   
   PR:		128134
 
 Modified:
   stable/7/sys/   (props changed)
   stable/7/sys/netinet/sctp_crc32.c
 
 Modified: stable/7/sys/netinet/sctp_crc32.c
 ==============================================================================
 --- stable/7/sys/netinet/sctp_crc32.c	Thu Feb 12 17:57:28 2009	(r188524)
 +++ stable/7/sys/netinet/sctp_crc32.c	Thu Feb 12 18:02:46 2009	(r188525)
 @@ -583,13 +583,13 @@ update_crc32(uint32_t crc32c,
      unsigned char *buffer,
      unsigned int length)
  {
 -	uint32_t offset;
 +	uint32_t to_even_word;
  
  	if (length == 0) {
  		return (crc32c);
  	}
 -	offset = ((uintptr_t) buffer) & 0x3;
 -	return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, offset));
 +	to_even_word = (4 - (((uintptr_t) buffer) & 0x3));
 +	return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, to_even_word));
  }
  
  uint32_t sctp_crc_c[256] = {
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->Closed  
State-Changed-By: rrs 
State-Changed-When: Mon Feb 16 11:38:02 UTC 2009 
State-Changed-Why:  
MFC'd into stable. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=128134 
State-Changed-From-To: Closed->closed 
State-Changed-By: linimon 
State-Changed-When: Tue Mar 10 03:44:43 UTC 2009 
State-Changed-Why:  
correct spelling of state. 

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