aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2015-07-21 09:40:08 -0400
committerIngo Molnar <mingo@kernel.org>2015-07-31 04:38:03 -0400
commit0b5256c7f173258b19d98364adb57f707dda22f3 (patch)
treeabc5d9b982f73c133235fd7e955e29780f8c8c69 /kernel/events
parent2bb5e840e873f8778a41801141771f54f547fa65 (diff)
uprobes: Send SIGILL if handle_trampoline() fails
1. It doesn't make sense to continue if handle_trampoline() fails, change handle_swbp() to always return after this call. 2. Turn pr_warn() into uprobe_warn(), and change handle_trampoline() to send SIGILL on failure. It is pointless to return to user mode with the corrupted instruction_pointer() which we can't restore. Tested-by: Pratyush Anand <panand@redhat.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Acked-by: Anton Arapov <arapov@gmail.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20150721134008.GA4745@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/uprobes.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d8c702fc836f..eabdc21366ee 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1770,7 +1770,7 @@ handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs)
1770 up_read(&uprobe->register_rwsem); 1770 up_read(&uprobe->register_rwsem);
1771} 1771}
1772 1772
1773static bool handle_trampoline(struct pt_regs *regs) 1773static void handle_trampoline(struct pt_regs *regs)
1774{ 1774{
1775 struct uprobe_task *utask; 1775 struct uprobe_task *utask;
1776 struct return_instance *ri; 1776 struct return_instance *ri;
@@ -1778,11 +1778,11 @@ static bool handle_trampoline(struct pt_regs *regs)
1778 1778
1779 utask = current->utask; 1779 utask = current->utask;
1780 if (!utask) 1780 if (!utask)
1781 return false; 1781 goto sigill;
1782 1782
1783 ri = utask->return_instances; 1783 ri = utask->return_instances;
1784 if (!ri) 1784 if (!ri)
1785 return false; 1785 goto sigill;
1786 1786
1787 /* 1787 /*
1788 * TODO: we should throw out return_instance's invalidated by 1788 * TODO: we should throw out return_instance's invalidated by
@@ -1804,8 +1804,12 @@ static bool handle_trampoline(struct pt_regs *regs)
1804 } 1804 }
1805 1805
1806 utask->return_instances = ri; 1806 utask->return_instances = ri;
1807 return;
1808
1809 sigill:
1810 uprobe_warn(current, "handle uretprobe, sending SIGILL.");
1811 force_sig_info(SIGILL, SEND_SIG_FORCED, current);
1807 1812
1808 return true;
1809} 1813}
1810 1814
1811bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs) 1815bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs)
@@ -1824,13 +1828,8 @@ static void handle_swbp(struct pt_regs *regs)
1824 int uninitialized_var(is_swbp); 1828 int uninitialized_var(is_swbp);
1825 1829
1826 bp_vaddr = uprobe_get_swbp_addr(regs); 1830 bp_vaddr = uprobe_get_swbp_addr(regs);
1827 if (bp_vaddr == get_trampoline_vaddr()) { 1831 if (bp_vaddr == get_trampoline_vaddr())
1828 if (handle_trampoline(regs)) 1832 return handle_trampoline(regs);
1829 return;
1830
1831 pr_warn("uprobe: unable to handle uretprobe pid/tgid=%d/%d\n",
1832 current->pid, current->tgid);
1833 }
1834 1833
1835 uprobe = find_active_uprobe(bp_vaddr, &is_swbp); 1834 uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
1836 if (!uprobe) { 1835 if (!uprobe) {