aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/events/uprobes.c73
1 files changed, 24 insertions, 49 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 9248ee76b4bb..6136854da6c6 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -282,32 +282,6 @@ put_old:
282 return ret; 282 return ret;
283} 283}
284 284
285static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
286{
287 struct page *page;
288 uprobe_opcode_t opcode;
289 int result;
290
291 if (current->mm == mm) {
292 pagefault_disable();
293 result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
294 sizeof(opcode));
295 pagefault_enable();
296
297 if (likely(result == 0))
298 goto out;
299 }
300
301 result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
302 if (result < 0)
303 return result;
304
305 copy_opcode(page, vaddr, &opcode);
306 put_page(page);
307 out:
308 return is_swbp_insn(&opcode);
309}
310
311/** 285/**
312 * set_swbp - store breakpoint at a given address. 286 * set_swbp - store breakpoint at a given address.
313 * @auprobe: arch specific probepoint information. 287 * @auprobe: arch specific probepoint information.
@@ -589,29 +563,6 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
589 return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); 563 return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
590} 564}
591 565
592/*
593 * How mm->uprobes_state.count gets updated
594 * uprobe_mmap() increments the count if
595 * - it successfully adds a breakpoint.
596 * - it cannot add a breakpoint, but sees that there is a underlying
597 * breakpoint (via a is_swbp_at_addr()).
598 *
599 * uprobe_munmap() decrements the count if
600 * - it sees a underlying breakpoint, (via is_swbp_at_addr)
601 * (Subsequent uprobe_unregister wouldnt find the breakpoint
602 * unless a uprobe_mmap kicks in, since the old vma would be
603 * dropped just after uprobe_munmap.)
604 *
605 * uprobe_register increments the count if:
606 * - it successfully adds a breakpoint.
607 *
608 * uprobe_unregister decrements the count if:
609 * - it sees a underlying breakpoint and removes successfully.
610 * (via is_swbp_at_addr)
611 * (Subsequent uprobe_munmap wouldnt find the breakpoint
612 * since there is no underlying breakpoint after the
613 * breakpoint removal.)
614 */
615static int 566static int
616install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, 567install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
617 struct vm_area_struct *vma, unsigned long vaddr) 568 struct vm_area_struct *vma, unsigned long vaddr)
@@ -1389,6 +1340,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
1389 clear_bit(MMF_HAS_UPROBES, &mm->flags); 1340 clear_bit(MMF_HAS_UPROBES, &mm->flags);
1390} 1341}
1391 1342
1343static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
1344{
1345 struct page *page;
1346 uprobe_opcode_t opcode;
1347 int result;
1348
1349 pagefault_disable();
1350 result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
1351 sizeof(opcode));
1352 pagefault_enable();
1353
1354 if (likely(result == 0))
1355 goto out;
1356
1357 result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
1358 if (result < 0)
1359 return result;
1360
1361 copy_opcode(page, vaddr, &opcode);
1362 put_page(page);
1363 out:
1364 return is_swbp_insn(&opcode);
1365}
1366
1392static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) 1367static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
1393{ 1368{
1394 struct mm_struct *mm = current->mm; 1369 struct mm_struct *mm = current->mm;