ARM: 9179/1: uaccess: avoid alignment faults in copy_[from|to]_kernel_nofault
The helpers that are used to implement copy_from_kernel_nofault() and copy_to_kernel_nofault() cast a void* to a pointer to a wider type, which may result in alignment faults on ARM if the compiler decides to use double-word or multiple-word load/store instructions. Only configurations that define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y are affected, given that commit2423de2e6f
("ARM: 9115/1: mm/maccess: fix unaligned copy_{from,to}_kernel_nofault") ensures that dst and src are sufficiently aligned otherwise. So use the unaligned accessors for accessing dst and src in cases where they may be misaligned. Cc: <stable@vger.kernel.org> # depends on2423de2e6f
Fixes:2df4c9a741
("ARM: 9112/1: uaccess: add __{get,put}_kernel_nofault") Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
8b59b0a53c
commit
15420269b0
@ -11,6 +11,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/domain.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/unified.h>
|
||||
#include <asm/compiler.h>
|
||||
|
||||
@ -497,7 +498,10 @@ do { \
|
||||
} \
|
||||
default: __err = __get_user_bad(); break; \
|
||||
} \
|
||||
*(type *)(dst) = __val; \
|
||||
if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) \
|
||||
put_unaligned(__val, (type *)(dst)); \
|
||||
else \
|
||||
*(type *)(dst) = __val; /* aligned by caller */ \
|
||||
if (__err) \
|
||||
goto err_label; \
|
||||
} while (0)
|
||||
@ -507,7 +511,9 @@ do { \
|
||||
const type *__pk_ptr = (dst); \
|
||||
unsigned long __dst = (unsigned long)__pk_ptr; \
|
||||
int __err = 0; \
|
||||
type __val = *(type *)src; \
|
||||
type __val = IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \
|
||||
? get_unaligned((type *)(src)) \
|
||||
: *(type *)(src); /* aligned by caller */ \
|
||||
switch (sizeof(type)) { \
|
||||
case 1: __put_user_asm_byte(__val, __dst, __err, ""); break; \
|
||||
case 2: __put_user_asm_half(__val, __dst, __err, ""); break; \
|
||||
|
Loading…
Reference in New Issue
Block a user