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

Configure Feed

Select the types of activity you want to include in your feed.

crypto: memneq - avoid implicit unaligned accesses

The C standard does not support dereferencing pointers that are not
aligned with respect to the pointed-to type, and doing so is technically
undefined behavior, even if the underlying hardware supports it.

This means that conditionally dereferencing such pointers based on
whether CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y is not the right thing
to do, and actually results in alignment faults on ARM, which are fixed
up on a slow path. Instead, we should use the unaligned accessors in
such cases: on architectures that don't care about alignment, they will
result in identical codegen whereas, e.g., codegen on ARM will avoid
doubleword loads and stores but use ordinary ones, which are able to
tolerate misalignment.

Link: https://lore.kernel.org/linux-crypto/CAHk-=wiKkdYLY0bv+nXrcJz3NH9mAqPAafX7PpW5EwVtxsEu7Q@mail.gmail.com/
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ard Biesheuvel and committed by
Herbert Xu
1c16dfbe 66eae850

+15 -7
+15 -7
crypto/memneq.c
··· 60 60 */ 61 61 62 62 #include <crypto/algapi.h> 63 + #include <asm/unaligned.h> 63 64 64 65 #ifndef __HAVE_ARCH_CRYPTO_MEMNEQ 65 66 ··· 72 71 73 72 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 74 73 while (size >= sizeof(unsigned long)) { 75 - neq |= *(unsigned long *)a ^ *(unsigned long *)b; 74 + neq |= get_unaligned((unsigned long *)a) ^ 75 + get_unaligned((unsigned long *)b); 76 76 OPTIMIZER_HIDE_VAR(neq); 77 77 a += sizeof(unsigned long); 78 78 b += sizeof(unsigned long); ··· 97 95 98 96 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 99 97 if (sizeof(unsigned long) == 8) { 100 - neq |= *(unsigned long *)(a) ^ *(unsigned long *)(b); 98 + neq |= get_unaligned((unsigned long *)a) ^ 99 + get_unaligned((unsigned long *)b); 101 100 OPTIMIZER_HIDE_VAR(neq); 102 - neq |= *(unsigned long *)(a+8) ^ *(unsigned long *)(b+8); 101 + neq |= get_unaligned((unsigned long *)(a + 8)) ^ 102 + get_unaligned((unsigned long *)(b + 8)); 103 103 OPTIMIZER_HIDE_VAR(neq); 104 104 } else if (sizeof(unsigned int) == 4) { 105 - neq |= *(unsigned int *)(a) ^ *(unsigned int *)(b); 105 + neq |= get_unaligned((unsigned int *)a) ^ 106 + get_unaligned((unsigned int *)b); 106 107 OPTIMIZER_HIDE_VAR(neq); 107 - neq |= *(unsigned int *)(a+4) ^ *(unsigned int *)(b+4); 108 + neq |= get_unaligned((unsigned int *)(a + 4)) ^ 109 + get_unaligned((unsigned int *)(b + 4)); 108 110 OPTIMIZER_HIDE_VAR(neq); 109 - neq |= *(unsigned int *)(a+8) ^ *(unsigned int *)(b+8); 111 + neq |= get_unaligned((unsigned int *)(a + 8)) ^ 112 + get_unaligned((unsigned int *)(b + 8)); 110 113 OPTIMIZER_HIDE_VAR(neq); 111 - neq |= *(unsigned int *)(a+12) ^ *(unsigned int *)(b+12); 114 + neq |= get_unaligned((unsigned int *)(a + 12)) ^ 115 + get_unaligned((unsigned int *)(b + 12)); 112 116 OPTIMIZER_HIDE_VAR(neq); 113 117 } else 114 118 #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */