[PATCH v3 3/3] kernel/uprobes: Fix check for active uprobe

From: Naveen N. Rao
Date: Fri Sep 22 2017 - 05:14:12 EST


If we try to install a uprobe on a breakpoint instruction when the
binary has not yet been mmap'ed, we register the probe but delay
installing the breakpoint for when the binary is actually mmap'ed. On
mmap, uprobe_mmap() calls prepare_uprobe() which then refuses to install
the breakpoint. In this case however, when the breakpoint hits, we
incorrectly assume that the probe hit and end up looping.

This happens because find_active_uprobe() does not check if we
successfully installed the breakpoint or not. Fix this by checking if
UPROBE_COPY_INSN is set in uprobe->flags in find_active_uprobe().
Since handle_swbp() calls find_active_uprobe(), we can remove the
redundant check there.

Reported-by: Anton Blanchard <anton@xxxxxxxxx>
Signed-off-by: Naveen N. Rao <naveen.n.rao@xxxxxxxxxxxxxxxxxx>
---
kernel/events/uprobes.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8da6570b4467..4c5dc6fb2abf 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1751,6 +1751,19 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
uprobe = find_uprobe(inode, offset);
}

+ /* Ensure that the breakpoint was actually installed */
+ if (uprobe) {
+ /*
+ * TODO: move copy_insn/etc into _register and remove
+ * this hack. After we hit the bp, _unregister +
+ * _register can install the new and not-yet-analyzed
+ * uprobe at the same address, restart.
+ */
+ smp_rmb(); /* pairs with wmb() in prepare_uprobe() */
+ if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
+ uprobe = NULL;
+ }
+
if (!uprobe)
*is_swbp = is_trap_at_addr(mm, bp_vaddr);
} else {
@@ -1911,15 +1924,6 @@ static void handle_swbp(struct pt_regs *regs)
/* change it in advance for ->handler() and restart */
instruction_pointer_set(regs, bp_vaddr);

- /*
- * TODO: move copy_insn/etc into _register and remove this hack.
- * After we hit the bp, _unregister + _register can install the
- * new and not-yet-analyzed uprobe at the same address, restart.
- */
- smp_rmb(); /* pairs with wmb() in install_breakpoint() */
- if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
- goto out;
-
/* Tracing handlers use ->utask to communicate with fetch methods */
if (!get_utask())
goto out;
--
2.14.1