arm64: csum: Disable KASAN for do_csum()
authorWill Deacon <will@kernel.org>
Tue, 14 Apr 2020 21:22:47 +0000 (22:22 +0100)
committerWill Deacon <will@kernel.org>
Wed, 15 Apr 2020 20:36:41 +0000 (21:36 +0100)
do_csum() over-reads the source buffer and therefore abuses
READ_ONCE_NOCHECK() to avoid tripping up KASAN. In preparation for
READ_ONCE_NOCHECK() becoming a macro, and therefore losing its
'__no_sanitize_address' annotation, just annotate do_csum() explicitly
and fall back to normal loads.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/lib/csum.c

index 60eccae2abad243cbfedb4e72839d97e98ae75db..78b87a64ca0a38286fc1390acc20bfc55f49e16f 100644 (file)
@@ -14,7 +14,11 @@ static u64 accumulate(u64 sum, u64 data)
        return tmp + (tmp >> 64);
 }
 
-unsigned int do_csum(const unsigned char *buff, int len)
+/*
+ * We over-read the buffer and this makes KASAN unhappy. Instead, disable
+ * instrumentation and call kasan explicitly.
+ */
+unsigned int __no_sanitize_address do_csum(const unsigned char *buff, int len)
 {
        unsigned int offset, shift, sum;
        const u64 *ptr;
@@ -42,7 +46,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
         * odd/even alignment, and means we can ignore it until the very end.
         */
        shift = offset * 8;
-       data = READ_ONCE_NOCHECK(*ptr++);
+       data = *ptr++;
 #ifdef __LITTLE_ENDIAN
        data = (data >> shift) << shift;
 #else
@@ -58,10 +62,10 @@ unsigned int do_csum(const unsigned char *buff, int len)
        while (unlikely(len > 64)) {
                __uint128_t tmp1, tmp2, tmp3, tmp4;
 
-               tmp1 = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
-               tmp2 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 2));
-               tmp3 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 4));
-               tmp4 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 6));
+               tmp1 = *(__uint128_t *)ptr;
+               tmp2 = *(__uint128_t *)(ptr + 2);
+               tmp3 = *(__uint128_t *)(ptr + 4);
+               tmp4 = *(__uint128_t *)(ptr + 6);
 
                len -= 64;
                ptr += 8;
@@ -85,7 +89,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
                __uint128_t tmp;
 
                sum64 = accumulate(sum64, data);
-               tmp = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
+               tmp = *(__uint128_t *)ptr;
 
                len -= 16;
                ptr += 2;
@@ -100,7 +104,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
        }
        if (len > 0) {
                sum64 = accumulate(sum64, data);
-               data = READ_ONCE_NOCHECK(*ptr);
+               data = *ptr;
                len -= 8;
        }
        /*