diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/events/uprobes.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index a2ed82b4808c..1f02e3bbfc1d 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1530,14 +1530,26 @@ static void handle_swbp(struct pt_regs *regs) | |||
1530 | struct uprobe_task *utask; | 1530 | struct uprobe_task *utask; |
1531 | struct uprobe *uprobe; | 1531 | struct uprobe *uprobe; |
1532 | unsigned long bp_vaddr; | 1532 | unsigned long bp_vaddr; |
1533 | int is_swbp; | 1533 | int uninitialized_var(is_swbp); |
1534 | 1534 | ||
1535 | bp_vaddr = uprobe_get_swbp_addr(regs); | 1535 | bp_vaddr = uprobe_get_swbp_addr(regs); |
1536 | uprobe = find_active_uprobe(bp_vaddr, &is_swbp); | 1536 | uprobe = find_active_uprobe(bp_vaddr, &is_swbp); |
1537 | 1537 | ||
1538 | if (!uprobe) { | 1538 | if (!uprobe) { |
1539 | /* No matching uprobe; signal SIGTRAP. */ | 1539 | if (is_swbp > 0) { |
1540 | send_sig(SIGTRAP, current, 0); | 1540 | /* No matching uprobe; signal SIGTRAP. */ |
1541 | send_sig(SIGTRAP, current, 0); | ||
1542 | } else { | ||
1543 | /* | ||
1544 | * Either we raced with uprobe_unregister() or we can't | ||
1545 | * access this memory. The latter is only possible if | ||
1546 | * another thread plays with our ->mm. In both cases | ||
1547 | * we can simply restart. If this vma was unmapped we | ||
1548 | * can pretend this insn was not executed yet and get | ||
1549 | * the (correct) SIGSEGV after restart. | ||
1550 | */ | ||
1551 | instruction_pointer_set(regs, bp_vaddr); | ||
1552 | } | ||
1541 | return; | 1553 | return; |
1542 | } | 1554 | } |
1543 | 1555 | ||