From: Naveen N. Rao <hidden> Date: 2017-09-22 09:10:43
This is v2 of the patches posted at:
http://lkml.kernel.org/r/2bc413d679c563d3ee338c318066777318577ab2.1505336870.git.naveen.n.rao@linux.vnet.ibm.com
Changes:
- No changes in patch 1, 4 and 5.
- Comment updated in patch 2, as suggested by Masami.
- Patch 3 has changes to explicitly call out detection of jprobe in
ftrace_caller() and that this is only for KPROBES_ON_FTRACE.
- Naveen
Naveen N. Rao (6):
powerpc/kprobes: Some cosmetic updates to try_to_emulate()
powerpc/kprobes: Do not suppress instruction emulation if a single run
failed
powerpc/kprobes: Clean up jprobe detection in livepatch handler
powerpc/kprobes: Fix warnings from __this_cpu_read() on preempt
kernels
powerpc/jprobes: Disable preemption when triggered through ftrace
powerpc/jprobes: Validate break handler invocation as being due to a
jprobe_return()
arch/powerpc/include/asm/kprobes.h | 2 +-
arch/powerpc/kernel/kprobes-ftrace.c | 30 ++++++++++++++---
arch/powerpc/kernel/kprobes.c | 45 ++++++++++++++------------
arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 4 +--
4 files changed, 53 insertions(+), 28 deletions(-)
--
2.14.1
From: Naveen N. Rao <hidden> Date: 2017-09-22 09:11:10
1. This is only used in kprobes.c, so make it static.
2. Remove the un-necessary (ret == 0) comparison in the else clause.
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Kamalesh Babulal <redacted>
Signed-off-by: Naveen N. Rao <redacted>
---
arch/powerpc/kernel/kprobes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Naveen N. Rao <hidden> Date: 2017-09-22 09:11:12
Currently, we disable instruction emulation if emulate_step() fails for
any reason. However, such failures could be transient and specific to a
particular run. Instead, only disable instruction emulation if we have
never been able to emulate this. If we had emulated this instruction
successfully at least once, then we single step only this probe hit and
continue to try emulating the instruction in subsequent probe hits.
Signed-off-by: Naveen N. Rao <redacted>
---
arch/powerpc/kernel/kprobes.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
From: Naveen N. Rao <hidden> Date: 2017-09-22 09:11:17
Kamalesh pointed out that we are getting the below call traces with
livepatched functions when we enable CONFIG_PREEMPT:
[ 495.470721] BUG: using __this_cpu_read() in preemptible [00000000] code: cat/8394
[ 495.471167] caller is is_current_kprobe_addr+0x30/0x90
[ 495.471171] CPU: 4 PID: 8394 Comm: cat Tainted: G K 4.13.0-rc7-nnr+ #95
[ 495.471173] Call Trace:
[ 495.471178] [c00000008fd9b960] [c0000000009f039c] dump_stack+0xec/0x160 (unreliable)
[ 495.471184] [c00000008fd9b9a0] [c00000000059169c] check_preemption_disabled+0x15c/0x170
[ 495.471187] [c00000008fd9ba30] [c000000000046460] is_current_kprobe_addr+0x30/0x90
[ 495.471191] [c00000008fd9ba60] [c00000000004e9a0] ftrace_call+0x1c/0xb8
[ 495.471195] [c00000008fd9bc30] [c000000000376fd8] seq_read+0x238/0x5c0
[ 495.471199] [c00000008fd9bcd0] [c0000000003cfd78] proc_reg_read+0x88/0xd0
[ 495.471203] [c00000008fd9bd00] [c00000000033e5d4] __vfs_read+0x44/0x1b0
[ 495.471206] [c00000008fd9bd90] [c0000000003402ec] vfs_read+0xbc/0x1b0
[ 495.471210] [c00000008fd9bde0] [c000000000342138] SyS_read+0x68/0x110
[ 495.471214] [c00000008fd9be30] [c00000000000bc6c] system_call+0x58/0x6c
Commit c05b8c4474c030 ("powerpc/kprobes: Skip livepatch_handler() for
jprobes") introduced a helper is_current_kprobe_addr() to help determine
if the current function has been livepatched or if it has a jprobe
installed, both of which modify the NIP. This was subsequently renamed
to __is_active_jprobe().
In the case of a jprobe, kprobe_ftrace_handler() disables pre-emption
before calling into setjmp_pre_handler() which returns without disabling
pre-emption. This is done to ensure that the jprobe handler won't
disappear beneath us if the jprobe is unregistered between the
setjmp_pre_handler() and the subsequent longjmp_break_handler() called
from the jprobe handler. Due to this, we can use __this_cpu_read() in
__is_active_jprobe() with the pre-emption check as we know that
pre-emption will be disabled.
However, if this function has been livepatched, we are still doing this
check and when we do so, pre-emption won't necessarily be disabled. This
results in the call trace shown above.
Fix this by only invoking __is_active_jprobe() when pre-emption is
disabled. And since we now guard this within a pre-emption check, we can
instead use raw_cpu_read() to get the current_kprobe value skipping the
check done by __this_cpu_read().
Fixes: c05b8c4474c030 ("powerpc/kprobes: Skip livepatch_handler() for jprobes")
Reported-by: Kamalesh Babulal <redacted>
Tested-by: Kamalesh Babulal <redacted>
Signed-off-by: Naveen N. Rao <redacted>
---
arch/powerpc/kernel/kprobes-ftrace.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
From: Naveen N. Rao <hidden> Date: 2017-09-22 09:11:17
In commit c05b8c4474c03 ("powerpc/kprobes: Skip livepatch_handler() for
jprobes"), we added a helper is_current_kprobe_addr() to help detect if
the modified regs->nip was due to a jprobe or livepatch. Masami felt
that the function name was not quite clear. To that end, this patch
renames is_current_kprobe_addr() to __is_active_jprobe() and adds a
comment to (hopefully) better clarify the purpose of this helper. The
helper has also now been moved to kprobes-ftrace.c so that it is only
available for KPROBES_ON_FTRACE.
Signed-off-by: Naveen N. Rao <redacted>
---
arch/powerpc/include/asm/kprobes.h | 2 +-
arch/powerpc/kernel/kprobes-ftrace.c | 11 +++++++++++
arch/powerpc/kernel/kprobes.c | 6 ------
arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 4 ++--
4 files changed, 14 insertions(+), 9 deletions(-)
@@ -80,6 +80,7 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,/* Disable irq for emulating a breakpoint and avoiding preempt */local_irq_save(flags);hard_irq_disable();+preempt_disable();p=get_kprobe((kprobe_opcode_t*)nip);if(unlikely(!p)||kprobe_disabled(p))
@@ -101,12 +102,18 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,kcb->kprobe_status=KPROBE_HIT_ACTIVE;if(!p->pre_handler||!p->pre_handler(p,regs))__skip_singlestep(p,regs,kcb,orig_nip);-/*-*Ifpre_handlerreturns!0,itsetsregs->nipand-*resetscurrentkprobe.-*/+else{+/*+*Ifpre_handlerreturns!0,itsetsregs->nipand+*resetscurrentkprobe.Inthiscase,westillneed+*torestoreirq,butnotpreemption.+*/+local_irq_restore(flags);+return;+}}end:+preempt_enable_no_resched();local_irq_restore(flags);}NOKPROBE_SYMBOL(kprobe_ftrace_handler);
From: Naveen N. Rao <hidden> Date: 2017-09-22 09:11:25
Fix a circa 2005 FIXME by implementing a check to ensure that we
actually got into the jprobe break handler() due to the trap in
jprobe_return().
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Naveen N. Rao <redacted>
---
arch/powerpc/kernel/kprobes.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
@@ -639,24 +639,22 @@ NOKPROBE_SYMBOL(setjmp_pre_handler);void__usedjprobe_return(void){-asmvolatile("trap":::"memory");+asmvolatile("jprobe_return_trap:\n"+"trap\n"+:::"memory");}NOKPROBE_SYMBOL(jprobe_return);-staticvoid__usedjprobe_return_end(void)-{-}-NOKPROBE_SYMBOL(jprobe_return_end);-intlongjmp_break_handler(structkprobe*p,structpt_regs*regs){structkprobe_ctlblk*kcb=get_kprobe_ctlblk();-/*-*FIXME-weshouldideallybevalidatingthatwegothere'cos-*ofthe"trap"injprobe_return()above,beforerestoringthe-*savedregs...-*/+if(regs->nip!=ppc_kallsyms_lookup_name("jprobe_return_trap")){+pr_debug("longjmp_break_handler NIP (0x%lx) does not match jprobe_return_trap (0x%lx)\n",+regs->nip,ppc_kallsyms_lookup_name("jprobe_return_trap"));+return0;+}+memcpy(regs,&kcb->jprobe_saved_regs,sizeof(structpt_regs));/* It's OK to start function graph tracing again */unpause_graph_tracing();
From: Michael Ellerman <hidden> Date: 2017-10-08 08:43:36
On Fri, 2017-09-22 at 09:10:43 UTC, "Naveen N. Rao" wrote:
1. This is only used in kprobes.c, so make it static.
2. Remove the un-necessary (ret == 0) comparison in the else clause.
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Kamalesh Babulal <redacted>
Signed-off-by: Naveen N. Rao <redacted>