parisc: Fix csum_ipv6_magic on 64-bit systems
authorGuenter Roeck <linux@roeck-us.net>
Tue, 13 Feb 2024 23:46:31 +0000 (15:46 -0800)
committerHelge Deller <deller@gmx.de>
Tue, 27 Feb 2024 21:51:45 +0000 (22:51 +0100)
hppa 64-bit systems calculates the IPv6 checksum using 64-bit add
operations. The last add folds protocol and length fields into the 64-bit
result. While unlikely, this operation can overflow. The overflow can be
triggered with a code sequence such as the following.

/* try to trigger massive overflows */
memset(tmp_buf, 0xff, sizeof(struct in6_addr));
csum_result = csum_ipv6_magic((struct in6_addr *)tmp_buf,
      (struct in6_addr *)tmp_buf,
      0xffff, 0xff, 0xffffffff);

Fix the problem by adding any overflows from the final add operation into
the calculated checksum. Fortunately, we can do this without additional
cost by replacing the add operation used to fold the checksum into 32 bit
with "add,dc" to add in the missing carry.

Cc: Palmer Dabbelt <palmer@rivosinc.com>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Helge Deller <deller@gmx.de>
arch/parisc/include/asm/checksum.h

index e619e67440db95cdfba9e7dfac044fc6eefb5e97..c949aa20fa1622a59238ed0707a229d52694cac8 100644 (file)
@@ -137,8 +137,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
 "      add,dc          %3, %0, %0\n"  /* fold in proto+len | carry bit */
 "      extrd,u         %0, 31, 32, %4\n"/* copy upper half down */
 "      depdi           0, 31, 32, %0\n"/* clear upper half */
-"      add             %4, %0, %0\n"   /* fold into 32-bits */
-"      addc            0, %0, %0\n"    /* add carry */
+"      add,dc          %4, %0, %0\n"   /* fold into 32-bits, plus carry */
+"      addc            0, %0, %0\n"    /* add final carry */
 
 #else