]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
arm64: kernel: check mode for get_user in undefinstr
authorPeng Du <pdu@nvidia.com>
Wed, 23 Jul 2014 18:40:33 +0000 (11:40 -0700)
committerMatthew Pedro <mapedro@nvidia.com>
Mon, 28 Jul 2014 19:19:36 +0000 (12:19 -0700)
get_user() should be called only for user_mode undef instruction.

Bug 1536343

Change-Id: Ia654783de0cf72abac6847ac9630236f9f0d6ebb
Signed-off-by: Peng Du <pdu@nvidia.com>
Reviewed-on: http://git-master/r/441348
(cherry picked from commit 518317f3e09c794e14de49f1afe47a93f92787ab)
Reviewed-on: http://git-master/r/448179
Reviewed-by: Matthew Pedro <mapedro@nvidia.com>
Tested-by: Matthew Pedro <mapedro@nvidia.com>
arch/arm64/kernel/traps.c

index ab9f1ec739339482ebfe32cab54b95fbf50843b2..d23f9341c58e164865e0dcef624dcfa44fea4bbd 100644 (file)
@@ -287,19 +287,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
        /* check for AArch32 breakpoint instructions */
        if (!aarch32_break_handler(regs))
                return;
-       if (compat_thumb_mode(regs)) {
-               if (get_user(instr, (u16 __user *)pc))
-                       goto die_sig;
-               if (is_wide_instruction(instr)) {
-                       u32 instr2;
-                       if (get_user(instr2, (u16 __user *)pc+1))
+       if (user_mode(regs)) {
+               if (compat_thumb_mode(regs)) {
+                       if (get_user(instr, (u16 __user *)pc))
                                goto die_sig;
-                       instr <<= 16;
-                       instr |= instr2;
+                       if (is_wide_instruction(instr)) {
+                               u32 instr2;
+                               if (get_user(instr2, (u16 __user *)pc+1))
+                                       goto die_sig;
+                               instr <<= 16;
+                               instr |= instr2;
+                       }
+               } else if (get_user(instr, (u32 __user *)pc)) {
+                       goto die_sig;
                }
-
-       } else if ((get_user(instr, (u32 __user *)pc))) {
-               goto die_sig;
+       } else {
+               /* kernel mode */
+               instr = *((u32 *)pc);
        }
 
        if (call_undef_hook(regs, instr) == 0)