Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/checksum: always use cksm instruction

Commit dfe843dce775 ("s390/checksum: support GENERIC_CSUM, enable it for
KASAN") switched s390 to use the generic checksum functions, so that KASAN
instrumentation also works checksum functions by avoiding architecture
specific inline assemblies.

There is however the problem that the generic csum_partial() function
returns a 32 bit value with a 16 bit folded checksum, while the original
s390 variant does not fold to 16 bit. This in turn causes that the
ipib_checksum in lowcore contains different values depending on kernel
config options.

The ipib_checksum is used by system dumpers to verify if pointers in
lowcore point to valid data. Verification is done by comparing checksum
values. The system dumpers still use 32 bit checksum values which are not
folded, and therefore the checksum verification fails (incorrectly).

Symptom is that reboot after dump does not work anymore when a KASAN
instrumented kernel is dumped.

Fix this by not using the generic checksum implementation. Instead add an
explicit kasan_check_read() so that KASAN knows about the read access from
within the inline assembly.

Reported-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Fixes: dfe843dce775 ("s390/checksum: support GENERIC_CSUM, enable it for KASAN")
Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Heiko Carstens and committed by
Vasily Gorbik
e42ac778 b94c0ebb

+2 -11
-4
arch/s390/Kconfig
··· 26 26 config GENERIC_BUG_RELATIVE_POINTERS 27 27 def_bool y 28 28 29 - config GENERIC_CSUM 30 - bool 31 - default y if KASAN 32 - 33 29 config GENERIC_LOCKBREAK 34 30 def_bool y if PREEMPTION 35 31
+2 -7
arch/s390/include/asm/checksum.h
··· 12 12 #ifndef _S390_CHECKSUM_H 13 13 #define _S390_CHECKSUM_H 14 14 15 - #ifdef CONFIG_GENERIC_CSUM 16 - 17 - #include <asm-generic/checksum.h> 18 - 19 - #else /* CONFIG_GENERIC_CSUM */ 20 - 15 + #include <linux/kasan-checks.h> 21 16 #include <linux/uaccess.h> 22 17 #include <linux/in6.h> 23 18 ··· 35 40 .odd = (unsigned long) len, 36 41 }; 37 42 43 + kasan_check_read(buff, len); 38 44 asm volatile( 39 45 "0: cksm %[sum],%[rp]\n" 40 46 " jo 0b\n" ··· 131 135 return csum_fold((__force __wsum)(sum >> 32)); 132 136 } 133 137 134 - #endif /* CONFIG_GENERIC_CSUM */ 135 138 #endif /* _S390_CHECKSUM_H */