crypto: crypto_xor - use helpers for unaligned accesses
PATCH v2 1/1 crypto: crypto_xor - use helpers for unaligned accesses
Dereferencing a misaligned pointer is undefined behavior in C, and may result in codegen on architectures such as ARM that trigger alignments traps and expensive fixups in software.
Instead, use the get_aligned()/put_aligned() accessors, which are cheap or even completely free when CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y.
In the converse case, the prior alignment checks ensure that the casts are safe, and so no unaligned accessors are necessary.
---
v2: fix issue in crypto_xor_cpy()
crypto/algapi.c | 24 +++++++++++++++++--- include/crypto/algapi.h | 10 ++++++-- 2 files changed, 29 insertions(+), 5 deletions(-)
crypto/algapi.c +21 -3
@@ -1008,7 +1008,13 @@ void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len) }while (IS_ENABLED (CONFIG_64BIT ) && len >=8 && !(relalign &7 )) { - *(u64 *)dst = *(u64 *)src1 ^ *(u64 *)src2; +if (IS_ENABLED (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS )) { +u64 l =get_unaligned ((u64 *)src1) ^ +get_unaligned ((u64 *)src2); +put_unaligned (l, (u64 *)dst); + }else { + *(u64 *)dst = *(u64 *)src1 ^ *(u64 *)src2; + } dst +=8 ; src1 +=8 ; src2 +=8 ;
@@ -1016,7 +1022,13 @@ void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len) }while (len >=4 && !(relalign &3 )) { - *(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2; +if (IS_ENABLED (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS )) { +u32 l =get_unaligned ((u32 *)src1) ^ +get_unaligned ((u32 *)src2); +put_unaligned (l, (u32 *)dst); + }else { + *(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2; + } dst +=4 ; src1 +=4 ; src2 +=4 ;
@@ -1024,7 +1036,13 @@ void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len) }while (len >=2 && !(relalign &1 )) { - *(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2; +if (IS_ENABLED (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS )) { +u16 l =get_unaligned ((u16 *)src1) ^ +get_unaligned ((u16 *)src2); +put_unaligned (l, (u16 *)dst); + }else { + *(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2; + } dst +=2 ; src1 +=2 ; src2 +=2 ;
include/crypto/algapi.h +8 -2
@@ -13,6 +13,8 @@#include <linux/list.h> #include <linux/types.h> +#include <asm/unaligned.h> +/* * Maximum values for blocksize and alignmask, used to allocate * static buffers that are big enough for any combination of
@@ -154,9 +156,11 @@ static inline void crypto_xor(u8 *dst, const u8 *src, unsigned int size) (size % sizeof(unsigned long)) == 0) {unsigned long *d = (unsigned long *)dst;unsigned long *s = (unsigned long *)src; +unsigned long l;while (size >0 ) { - *d++ ^= *s++; + l =get_unaligned (d) ^get_unaligned (s++); +put_unaligned (l, d++); size -=sizeof (unsigned long ); } } else {
@@ -173,9 +177,11 @@ static inline void crypto_xor_cpy(u8 *dst, const u8 *src1, const u8 *src2,unsigned long *d = (unsigned long *)dst;unsigned long *s1 = (unsigned long *)src1;unsigned long *s2 = (unsigned long *)src2; +unsigned long l;while (size >0 ) { - *d++ = *s1++ ^ *s2++; + l =get_unaligned (s1++) ^get_unaligned (s2++); +put_unaligned (l, d++); size -=sizeof (unsigned long ); } }else {
Signature · 1 line
2.30.2
Herbert Xu
maintainerQuoted 10 lines · Ard Biesheuvel
Dereferencing a misaligned pointer is undefined behavior in C, and may result in codegen on architectures such as ARM that trigger alignments traps and expensive fixups in software.
Instead, use the get_aligned()/put_aligned() accessors, which are cheap or even completely free when
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y.In the converse case, the prior alignment checks ensure that the casts are safe, and so no unaligned accessors are necessary.
Quoted 7 lines
Signed-off-by Ard Biesheuvel <[email protected]>---
v2: fix issue incrypto_xor_cpy()crypto/algapi.c | 24 +++++++++++++++++--- include/crypto/algapi.h | 10 ++++++-- 2 files changed, 29 insertions(+), 5 deletions(-)
Patch applied. Thanks.
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt