diff options
author | Peng Du <pdu@nvidia.com> | 2014-07-23 11:40:33 -0700 |
---|---|---|
committer | Matthew Pedro <mapedro@nvidia.com> | 2014-07-28 12:19:36 -0700 |
commit | f5091b9678a8a00cf8bb0181e08e1ccdb81fce9b (patch) | |
tree | d1c95c1b7826a04480d6107aeb648161ecd6509b /arch/arm64 | |
parent | 18aa7b3f4a96ea569d9d9797fd2ad152a403f5a2 (diff) |
arm64: kernel: check mode for get_user in undefinstr
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>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/kernel/traps.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index ab9f1ec73933..d23f9341c58e 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -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) |