do_csum() over-reads the source buffer and therefore abuses
READ_ONCE_NOCHECK() on a 128-bit type to avoid tripping up KASAN. In
preparation for READ_ONCE_NOCHECK() requiring an atomic access, and
therefore failing to build when fed a '__uint128_t', annotate do_csum()
explicitly with '__no_sanitize_address' and fall back to normal loads.

Acked-by: Robin Murphy <[email protected]>
Acked-by: Mark Rutland <[email protected]>
Signed-off-by: Will Deacon <[email protected]>
---
 arch/arm64/lib/csum.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/lib/csum.c b/arch/arm64/lib/csum.c
index 60eccae2abad..78b87a64ca0a 100644
--- a/arch/arm64/lib/csum.c
+++ b/arch/arm64/lib/csum.c
@@ -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;
        }
        /*
-- 
2.26.2.645.ge9eca65c58-goog

Reply via email to