arm64: fix endianness annotation in call_undef_hook()
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>
Wed, 28 Jun 2017 14:55:55 +0000 (16:55 +0200)
committerWill Deacon <will.deacon@arm.com>
Thu, 29 Jun 2017 10:02:42 +0000 (11:02 +0100)
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>
arch/arm64/kernel/traps.c

index 3ebfb1d00b53ea801baa2fe4f82748eb8e0b8ded..c7c7088097be0c1b8e80d594c3d02f715c03abfa 100644 (file)
@@ -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);