Commit 37b6cb47 authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'uprobes/core' of...

Merge branch 'uprobes/core' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg/misc into perf/core

Pull uprobes fixes and cleanups from Oleg Nesterov:

  "Any probed jmp/call can kill the application, see the changelog in 11/15."
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b3d5fc3c 6cc5e7ff
...@@ -33,15 +33,27 @@ typedef u8 uprobe_opcode_t; ...@@ -33,15 +33,27 @@ typedef u8 uprobe_opcode_t;
#define UPROBE_SWBP_INSN 0xcc #define UPROBE_SWBP_INSN 0xcc
#define UPROBE_SWBP_INSN_SIZE 1 #define UPROBE_SWBP_INSN_SIZE 1
struct uprobe_xol_ops;
struct arch_uprobe { struct arch_uprobe {
u16 fixups;
union { union {
u8 insn[MAX_UINSN_BYTES]; u8 insn[MAX_UINSN_BYTES];
u8 ixol[MAX_UINSN_BYTES]; u8 ixol[MAX_UINSN_BYTES];
}; };
u16 fixups;
const struct uprobe_xol_ops *ops;
union {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
unsigned long rip_rela_target_address; unsigned long rip_rela_target_address;
#endif #endif
struct {
s32 offs;
u8 ilen;
u8 opc1;
} branch;
};
}; };
struct arch_uprobe_task { struct arch_uprobe_task {
......
This diff is collapsed.
...@@ -60,8 +60,6 @@ static struct percpu_rw_semaphore dup_mmap_sem; ...@@ -60,8 +60,6 @@ static struct percpu_rw_semaphore dup_mmap_sem;
/* Have a copy of original instruction */ /* Have a copy of original instruction */
#define UPROBE_COPY_INSN 0 #define UPROBE_COPY_INSN 0
/* Can skip singlestep */
#define UPROBE_SKIP_SSTEP 1
struct uprobe { struct uprobe {
struct rb_node rb_node; /* node in the rb tree */ struct rb_node rb_node; /* node in the rb tree */
...@@ -491,12 +489,9 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) ...@@ -491,12 +489,9 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
uprobe->offset = offset; uprobe->offset = offset;
init_rwsem(&uprobe->register_rwsem); init_rwsem(&uprobe->register_rwsem);
init_rwsem(&uprobe->consumer_rwsem); init_rwsem(&uprobe->consumer_rwsem);
/* For now assume that the instruction need not be single-stepped */
__set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
/* add to uprobes_tree, sorted on inode:offset */ /* add to uprobes_tree, sorted on inode:offset */
cur_uprobe = insert_uprobe(uprobe); cur_uprobe = insert_uprobe(uprobe);
/* a uprobe exists for this inode:offset combination */ /* a uprobe exists for this inode:offset combination */
if (cur_uprobe) { if (cur_uprobe) {
kfree(uprobe); kfree(uprobe);
...@@ -1628,20 +1623,6 @@ bool uprobe_deny_signal(void) ...@@ -1628,20 +1623,6 @@ bool uprobe_deny_signal(void)
return true; return true;
} }
/*
* Avoid singlestepping the original instruction if the original instruction
* is a NOP or can be emulated.
*/
static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
{
if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) {
if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
return true;
clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
}
return false;
}
static void mmf_recalc_uprobes(struct mm_struct *mm) static void mmf_recalc_uprobes(struct mm_struct *mm)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
...@@ -1868,13 +1849,13 @@ static void handle_swbp(struct pt_regs *regs) ...@@ -1868,13 +1849,13 @@ static void handle_swbp(struct pt_regs *regs)
handler_chain(uprobe, regs); handler_chain(uprobe, regs);
if (can_skip_sstep(uprobe, regs)) if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
goto out; goto out;
if (!pre_ssout(uprobe, regs, bp_vaddr)) if (!pre_ssout(uprobe, regs, bp_vaddr))
return; return;
/* can_skip_sstep() succeeded, or restart if can't singlestep */ /* arch_uprobe_skip_sstep() succeeded, or restart if can't singlestep */
out: out:
put_uprobe(uprobe); put_uprobe(uprobe);
} }
...@@ -1886,10 +1867,11 @@ static void handle_swbp(struct pt_regs *regs) ...@@ -1886,10 +1867,11 @@ static void handle_swbp(struct pt_regs *regs)
static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
{ {
struct uprobe *uprobe; struct uprobe *uprobe;
int err = 0;
uprobe = utask->active_uprobe; uprobe = utask->active_uprobe;
if (utask->state == UTASK_SSTEP_ACK) if (utask->state == UTASK_SSTEP_ACK)
arch_uprobe_post_xol(&uprobe->arch, regs); err = arch_uprobe_post_xol(&uprobe->arch, regs);
else if (utask->state == UTASK_SSTEP_TRAPPED) else if (utask->state == UTASK_SSTEP_TRAPPED)
arch_uprobe_abort_xol(&uprobe->arch, regs); arch_uprobe_abort_xol(&uprobe->arch, regs);
else else
...@@ -1903,6 +1885,11 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) ...@@ -1903,6 +1885,11 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
recalc_sigpending(); /* see uprobe_deny_signal() */ recalc_sigpending(); /* see uprobe_deny_signal() */
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (unlikely(err)) {
uprobe_warn(current, "execute the probed insn, sending SIGILL.");
force_sig_info(SIGILL, SEND_SIG_FORCED, current);
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment