lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20080930.002856.93205794.anemo@mba.ocn.ne.jp>
Date:	Tue, 30 Sep 2008 00:28:56 +0900 (JST)
From:	Atsushi Nemoto <anemo@....ocn.ne.jp>
To:	u1@...ran.org
Cc:	ralf@...ux-mips.org, macro@...ux-mips.org,
	linux-mips@...ux-mips.org, netdev@...r.kernel.org
Subject: Re: [PATCH] MIPS checksum fix

On Tue, 23 Sep 2008 14:52:24 -0700, Bryan Phillippe <u1@...ran.org> wrote:
> 
> I tried this patch (with and without Atsushi's addition, shown below)  
> on a MIPS64 today and the checksums were all bad (i.e. worse than the  
> original problem).
> 
> Note that I had to manually create the diff, because of "malformed  
> patch" errors at line 21 (second hunk).
> 
> If anyone would like to send me an updated unified diff for this  
> issue, I can re-test today within the next day.

I suppose your problem is still not fixed, right?

If so, could you try this patch?  With this patch, checksums is always
compared with a result of "reference" implementation.  If any mismatch
was found, please report the log.

 arch/mips/lib/Makefile            |    1 +
 arch/mips/lib/csum_partial.S      |    4 +-
 arch/mips/lib/csum_partial_test.c |  109 +++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 8810dfb..cb56e19 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
 obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += csum_partial_test.o
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index edac989..22e9767 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -101,7 +101,7 @@
 	.text
 	.set	noreorder
 	.align	5
-LEAF(csum_partial)
+LEAF(asm_csum_partial)
 	move	sum, zero
 	move	t7, zero
 
@@ -296,7 +296,7 @@ LEAF(csum_partial)
 	ADDC32(sum, a2)
 	jr	ra
 	.set	noreorder
-	END(csum_partial)
+	END(asm_csum_partial)
 
 
 /*
diff --git a/arch/mips/lib/csum_partial_test.c b/arch/mips/lib/csum_partial_test.c
new file mode 100644
index 0000000..4a4887e
--- /dev/null
+++ b/arch/mips/lib/csum_partial_test.c
@@ -0,0 +1,109 @@
+#include <net/checksum.h>
+
+static inline __sum16 ref_csum_fold(__wsum csum)
+{
+	u32 sum = (__force u32)csum;
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (__force __sum16)~sum;
+}
+
+static inline unsigned short from32to16(unsigned int x)
+{
+	/* add up 16-bit and 16-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static unsigned int do_csum(const unsigned char * buff, int len)
+{
+	int odd, count;
+	unsigned int result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+#ifdef __BIG_ENDIAN
+		result = *buff;
+#else
+		result = *buff << 8;
+#endif
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+		        unsigned int carry = 0;
+			do {
+				unsigned int w = *(unsigned int *) buff;
+				count--;
+				buff += 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1) {
+#ifdef __BIG_ENDIAN
+		result += (*buff << 8);
+#else
+		result += *buff;
+#endif
+	}
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+static __wsum ref_csum_partial(const void *buff, int len, __wsum sum)
+{
+	unsigned int result = do_csum(buff, len);
+
+	/* add in old sum, and carry.. */
+	result += (__force u32)sum;
+	if ((__force u32)sum > result)
+		result += 1;
+	return (__force __wsum)result;
+}
+
+__wsum asm_csum_partial(const void *buff, int len, __wsum sum);
+
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+	__wsum ref_wsum = ref_csum_partial(buff, len, sum);
+	__sum16 ref_sum = ref_csum_fold(ref_wsum);
+	__wsum cal_wsum = asm_csum_partial(buff, len, sum);
+	__sum16 cal_sum = csum_fold(cal_wsum);
+	if (ref_sum != cal_sum) {
+		int i;
+		printk("csum_partial error."
+		       " %#04x(%#08x) != %#04x(%#08x)\n",
+		       ref_sum, ref_wsum, cal_sum, cal_wsum);
+		printk("len %#04x, sum %#08x\n", len, sum);
+		printk("buf");
+		for (i = 0; i < len; i++)
+			printk(" %#02x", *((const u8 *)buff + i));
+		printk("\n");
+	}
+	return ref_wsum;
+}
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ