ARM: fix csum_tcpudp_magic() miscompilation
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 12 Dec 2013 22:49:14 +0000 (22:49 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 29 Dec 2013 12:32:41 +0000 (12:32 +0000)
commitd46cda12e8b0fa5082cb40eb4bbfcba66b603bb2
treef142b36b885e79b0a09bd87a8217162e1eb93d97
parent70f665fe77c54740d0fa8aaad5de2181d75af15e
ARM: fix csum_tcpudp_magic() miscompilation

There is a miscompilation of csum_tcpudp_magic() due to the way we pass
the asm() operands in.  Fortunately, this doesn't affect the IP code,
but can affect anyone who passes ntohs(udp->len) as the length argument,
or protocols with more than 8 bits.

The problem stems from passing 16-bit operands into an asm() - GCC makes
no guarantees about what may be in the high 16-bits of such a register
passed into assembly which is in the "HI" machine mode.

Address this by changing the way we handle the 16-bit arguments - since
accumulating the protocol and length can never overflow, we can delegate
this to the compiler to perform, and then accumulate it into the
checksum inside the asm(), taking account of the endian-ness via an
appropriate 32-bit rotation.

While we are here, also realise that there's a chance to optimise this
a little: several callers from IP code pass a constant zero as the
initial sum.  This is wasteful - if we detect this condition, we can
optimise away one instruction.

Tested-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/include/asm/checksum.h