aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2017-02-28 11:23:24 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:17 -0400
commit1eae95d4bc031553562c970b49e895bfc60860f5 (patch)
tree9c9cfc159f562b5d6696bc91aeaa90cd82181867
parentc9f6172239042b3fcc8239aee4f67172c91c7681 (diff)
kprobes/x86: Fix kernel panic when certain exception-handling addresses are probed
commit 75013fb16f8484898eaa8d0b08fed942d790f029 upstream. Fix to the exception table entry check by using probed address instead of the address of copied instruction. This bug may cause unexpected kernel panic if user probe an address where an exception can happen which should be fixup by __ex_table (e.g. copy_from_user.) Unless user puts a kprobe on such address, this doesn't cause any problem. This bug has been introduced years ago, by commit: 464846888d9a ("x86/kprobes: Fix a bug which can modify kernel code permanently"). Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes: 464846888d9a ("x86/kprobes: Fix a bug which can modify kernel code permanently") Link: http://lkml.kernel.org/r/148829899399.28855.12581062400757221722.stgit@devbox Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/x86/kernel/kprobes/common.h2
-rw-r--r--arch/x86/kernel/kprobes/core.c6
-rw-r--r--arch/x86/kernel/kprobes/opt.c2
3 files changed, 5 insertions, 5 deletions
diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h
index c6ee63f927ab..d688826e5736 100644
--- a/arch/x86/kernel/kprobes/common.h
+++ b/arch/x86/kernel/kprobes/common.h
@@ -67,7 +67,7 @@
67#endif 67#endif
68 68
69/* Ensure if the instruction can be boostable */ 69/* Ensure if the instruction can be boostable */
70extern int can_boost(kprobe_opcode_t *instruction); 70extern int can_boost(kprobe_opcode_t *instruction, void *addr);
71/* Recover instruction if given address is probed */ 71/* Recover instruction if given address is probed */
72extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, 72extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
73 unsigned long addr); 73 unsigned long addr);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index d9d8d16b69db..b55d07b9d530 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -166,12 +166,12 @@ NOKPROBE_SYMBOL(skip_prefixes);
166 * Returns non-zero if opcode is boostable. 166 * Returns non-zero if opcode is boostable.
167 * RIP relative instructions are adjusted at copying time in 64 bits mode 167 * RIP relative instructions are adjusted at copying time in 64 bits mode
168 */ 168 */
169int can_boost(kprobe_opcode_t *opcodes) 169int can_boost(kprobe_opcode_t *opcodes, void *addr)
170{ 170{
171 kprobe_opcode_t opcode; 171 kprobe_opcode_t opcode;
172 kprobe_opcode_t *orig_opcodes = opcodes; 172 kprobe_opcode_t *orig_opcodes = opcodes;
173 173
174 if (search_exception_tables((unsigned long)opcodes)) 174 if (search_exception_tables((unsigned long)addr))
175 return 0; /* Page fault may occur on this address. */ 175 return 0; /* Page fault may occur on this address. */
176 176
177retry: 177retry:
@@ -416,7 +416,7 @@ static int arch_copy_kprobe(struct kprobe *p)
416 * __copy_instruction can modify the displacement of the instruction, 416 * __copy_instruction can modify the displacement of the instruction,
417 * but it doesn't affect boostable check. 417 * but it doesn't affect boostable check.
418 */ 418 */
419 if (can_boost(p->ainsn.insn)) 419 if (can_boost(p->ainsn.insn, p->addr))
420 p->ainsn.boostable = 0; 420 p->ainsn.boostable = 0;
421 else 421 else
422 p->ainsn.boostable = -1; 422 p->ainsn.boostable = -1;
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
index 3bb4c5f021f6..4d74f7386a61 100644
--- a/arch/x86/kernel/kprobes/opt.c
+++ b/arch/x86/kernel/kprobes/opt.c
@@ -178,7 +178,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src)
178 178
179 while (len < RELATIVEJUMP_SIZE) { 179 while (len < RELATIVEJUMP_SIZE) {
180 ret = __copy_instruction(dest + len, src + len); 180 ret = __copy_instruction(dest + len, src + len);
181 if (!ret || !can_boost(dest + len)) 181 if (!ret || !can_boost(dest + len, src + len))
182 return -EINVAL; 182 return -EINVAL;
183 len += ret; 183 len += ret;
184 } 184 }