i386/69257: in_cksum_hdr is non-functional without -O compiler flag
Qing Li
qing.li at bluecoat.com
Sun Jul 18 16:10:10 PDT 2004
>Number: 69257
>Category: i386
>Synopsis: in_cksum_hdr is non-functional without -O compiler flag
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-i386
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Jul 18 23:10:10 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator: Qing Li
>Release: 5.2.1
>Organization:
Blue Coat Systems, Inc.
>Environment:
FreeBSD heavygear.bluecoat.com 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #0: Tue Jun8 20:16:31 GMT 2004 root at heavygear.bluecoat.com:/usr/src/sys/i386/compile/QING i386
>Description:
The "in_cksum_hdr" function does not work when compiled without any optimization flags on i386.
The original inline __asm code was written as
#define ADD(n) __asm __volatile ("addl %1, %0" : "+r" (sum) : \
"g" (((const u_int32_t *)ip)[n]))
#define ADDC(n) __asm __volatile ("adcl %1, %0" : "+r" (sum) : \
"g" (((const u_int32_t *)ip)[n]))
ADD(0)
ADDC(4)
ADDC(8) etc.
The C code assumes that the carry bit is always kept from the
previous operation. However, the pointer indexing requires another
add operation, here is the gcc generated code
#1 3784 2ef0 0310 addl (%eax), %edx
3786 2ef2 8955FC movl %edx, -4(%ebp)
3787 2ef5 8B4508 movl 8(%ebp), %eax
#2 3788 2ef8 83C004 addl $4, %eax
3789 2efb 8B55FC movl -4(%ebp), %edx
#3 3791 2efe 1310 adcl (%eax), %edx
The bug is, the carry bit from #1 is tromped over by the
"addl" operation on line #2, so the "adcl" on #3 has no effect
because the carry bit is cleard by #2. The result is checksum
failure on received packets.
>How-To-Repeat:
Compile any file that calls the in_cksum_hdr function, such as
ip_input.c, without any optimization flags.
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-i386
mailing list