summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/traps.c
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-06-28 16:55:55 +0200
committerWill Deacon <will.deacon@arm.com>2017-06-29 11:02:42 +0100
commit6cf5d4af83e04f4cfae91bfdefd9d4d6949c09b2 (patch)
treeb12662f89790cdb0e64f9169739a1c40a29e9ef2 /arch/arm64/kernel/traps.c
parenta5018b0e6f036a598e55371e9135e287dc3b25e5 (diff)
arm64: fix endianness annotation in call_undef_hook()
Here we're reading thumb or ARM instructions, which are always stored in memory in little-endian order. These values are thus correctly converted to native order but the intermediate value should be annotated as for little-endian values. Fix this by declaring the intermediate var as __le32 or __le16. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/traps.c')
-rw-r--r--arch/arm64/kernel/traps.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 3ebfb1d00b53..c7c7088097be 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -344,22 +344,24 @@ static int call_undef_hook(struct pt_regs *regs)
if (compat_thumb_mode(regs)) {
/* 16-bit Thumb instruction */
- if (get_user(instr, (u16 __user *)pc))
+ __le16 instr_le;
+ if (get_user(instr_le, (__le16 __user *)pc))
goto exit;
- instr = le16_to_cpu(instr);
+ instr = le16_to_cpu(instr_le);
if (aarch32_insn_is_wide(instr)) {
u32 instr2;
- if (get_user(instr2, (u16 __user *)(pc + 2)))
+ if (get_user(instr_le, (__le16 __user *)(pc + 2)))
goto exit;
- instr2 = le16_to_cpu(instr2);
+ instr2 = le16_to_cpu(instr_le);
instr = (instr << 16) | instr2;
}
} else {
/* 32-bit ARM instruction */
- if (get_user(instr, (u32 __user *)pc))
+ __le32 instr_le;
+ if (get_user(instr_le, (__le32 __user *)pc))
goto exit;
- instr = le32_to_cpu(instr);
+ instr = le32_to_cpu(instr_le);
}
raw_spin_lock_irqsave(&undef_lock, flags);