|
@@ -1530,14 +1530,26 @@ static void handle_swbp(struct pt_regs *regs)
|
|
struct uprobe_task *utask;
|
|
struct uprobe_task *utask;
|
|
struct uprobe *uprobe;
|
|
struct uprobe *uprobe;
|
|
unsigned long bp_vaddr;
|
|
unsigned long bp_vaddr;
|
|
- int is_swbp;
|
|
|
|
|
|
+ int uninitialized_var(is_swbp);
|
|
|
|
|
|
bp_vaddr = uprobe_get_swbp_addr(regs);
|
|
bp_vaddr = uprobe_get_swbp_addr(regs);
|
|
uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
|
|
uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
|
|
|
|
|
|
if (!uprobe) {
|
|
if (!uprobe) {
|
|
- /* No matching uprobe; signal SIGTRAP. */
|
|
|
|
- send_sig(SIGTRAP, current, 0);
|
|
|
|
|
|
+ if (is_swbp > 0) {
|
|
|
|
+ /* No matching uprobe; signal SIGTRAP. */
|
|
|
|
+ send_sig(SIGTRAP, current, 0);
|
|
|
|
+ } else {
|
|
|
|
+ /*
|
|
|
|
+ * Either we raced with uprobe_unregister() or we can't
|
|
|
|
+ * access this memory. The latter is only possible if
|
|
|
|
+ * another thread plays with our ->mm. In both cases
|
|
|
|
+ * we can simply restart. If this vma was unmapped we
|
|
|
|
+ * can pretend this insn was not executed yet and get
|
|
|
|
+ * the (correct) SIGSEGV after restart.
|
|
|
|
+ */
|
|
|
|
+ instruction_pointer_set(regs, bp_vaddr);
|
|
|
|
+ }
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|