diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-08-07 12:12:28 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2012-09-15 11:37:28 -0400 |
commit | 9d778782266f95e5c6ec43ed8195ba331c821018 (patch) | |
tree | 99872945803a76d1ff9e438cf48864cd0a5d9bf4 | |
parent | 499a4f3ec057a0f79636cc3c1e581bb6e977a30f (diff) |
uprobes: Introduce arch_uprobe_enable/disable_step()
As Oleg pointed out in [0] uprobe should not use the ptrace interface
for enabling/disabling single stepping.
[0] http://lkml.kernel.org/r/20120730141638.GA5306@redhat.com
Add the new "__weak arch" helpers which simply call user_*_single_step()
as a preparation. This is only needed to not break the powerpc port, we
will fold this logic into arch_uprobe_pre/post_xol() hooks later.
We should also change handle_singlestep(), _disable_step(&uprobe->arch)
should be called before put_uprobe().
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
-rw-r--r-- | include/linux/uprobes.h | 2 | ||||
-rw-r--r-- | kernel/events/uprobes.c | 14 |
2 files changed, 14 insertions, 2 deletions
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index 6d4fe79a1a6a..e6f0331e3d45 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h | |||
@@ -112,6 +112,8 @@ extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); | |||
112 | extern void uprobe_free_utask(struct task_struct *t); | 112 | extern void uprobe_free_utask(struct task_struct *t); |
113 | extern void uprobe_copy_process(struct task_struct *t); | 113 | extern void uprobe_copy_process(struct task_struct *t); |
114 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); | 114 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); |
115 | extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); | ||
116 | extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); | ||
115 | extern int uprobe_post_sstep_notifier(struct pt_regs *regs); | 117 | extern int uprobe_post_sstep_notifier(struct pt_regs *regs); |
116 | extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); | 118 | extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); |
117 | extern void uprobe_notify_resume(struct pt_regs *regs); | 119 | extern void uprobe_notify_resume(struct pt_regs *regs); |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index e4a906ce2e1d..912ef48d28ab 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1444,6 +1444,16 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) | |||
1444 | return uprobe; | 1444 | return uprobe; |
1445 | } | 1445 | } |
1446 | 1446 | ||
1447 | void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) | ||
1448 | { | ||
1449 | user_enable_single_step(current); | ||
1450 | } | ||
1451 | |||
1452 | void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) | ||
1453 | { | ||
1454 | user_disable_single_step(current); | ||
1455 | } | ||
1456 | |||
1447 | /* | 1457 | /* |
1448 | * Run handler and ask thread to singlestep. | 1458 | * Run handler and ask thread to singlestep. |
1449 | * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. | 1459 | * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. |
@@ -1490,7 +1500,7 @@ static void handle_swbp(struct pt_regs *regs) | |||
1490 | 1500 | ||
1491 | utask->state = UTASK_SSTEP; | 1501 | utask->state = UTASK_SSTEP; |
1492 | if (!pre_ssout(uprobe, regs, bp_vaddr)) { | 1502 | if (!pre_ssout(uprobe, regs, bp_vaddr)) { |
1493 | user_enable_single_step(current); | 1503 | arch_uprobe_enable_step(&uprobe->arch); |
1494 | return; | 1504 | return; |
1495 | } | 1505 | } |
1496 | 1506 | ||
@@ -1526,10 +1536,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) | |||
1526 | else | 1536 | else |
1527 | WARN_ON_ONCE(1); | 1537 | WARN_ON_ONCE(1); |
1528 | 1538 | ||
1539 | arch_uprobe_disable_step(&uprobe->arch); | ||
1529 | put_uprobe(uprobe); | 1540 | put_uprobe(uprobe); |
1530 | utask->active_uprobe = NULL; | 1541 | utask->active_uprobe = NULL; |
1531 | utask->state = UTASK_RUNNING; | 1542 | utask->state = UTASK_RUNNING; |
1532 | user_disable_single_step(current); | ||
1533 | xol_free_insn_slot(current); | 1543 | xol_free_insn_slot(current); |
1534 | 1544 | ||
1535 | spin_lock_irq(¤t->sighand->siglock); | 1545 | spin_lock_irq(¤t->sighand->siglock); |