diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-19 11:03:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-19 11:03:07 -0400 |
commit | d0616c1775035496fb355248d296fb16ea7fb235 (patch) | |
tree | 7a6cbefa1ba8ed3fd1e03d3267b196d074c47279 /kernel | |
parent | bea8f35421628266658c14ea990d18b0969c4c0b (diff) | |
parent | baedbf02b1912225d60dd7403acb4b4e003088b5 (diff) |
Merge branch 'uprobes/core' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg/misc into perf/core
Pull uprobes fixes + cleanups from Oleg Nesterov.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/events/uprobes.c | 99 |
1 files changed, 79 insertions, 20 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 1666632e6edf..912ef48d28ab 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -411,11 +411,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) | |||
411 | static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) | 411 | static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) |
412 | { | 412 | { |
413 | struct uprobe *uprobe; | 413 | struct uprobe *uprobe; |
414 | unsigned long flags; | ||
415 | 414 | ||
416 | spin_lock_irqsave(&uprobes_treelock, flags); | 415 | spin_lock(&uprobes_treelock); |
417 | uprobe = __find_uprobe(inode, offset); | 416 | uprobe = __find_uprobe(inode, offset); |
418 | spin_unlock_irqrestore(&uprobes_treelock, flags); | 417 | spin_unlock(&uprobes_treelock); |
419 | 418 | ||
420 | return uprobe; | 419 | return uprobe; |
421 | } | 420 | } |
@@ -462,12 +461,11 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) | |||
462 | */ | 461 | */ |
463 | static struct uprobe *insert_uprobe(struct uprobe *uprobe) | 462 | static struct uprobe *insert_uprobe(struct uprobe *uprobe) |
464 | { | 463 | { |
465 | unsigned long flags; | ||
466 | struct uprobe *u; | 464 | struct uprobe *u; |
467 | 465 | ||
468 | spin_lock_irqsave(&uprobes_treelock, flags); | 466 | spin_lock(&uprobes_treelock); |
469 | u = __insert_uprobe(uprobe); | 467 | u = __insert_uprobe(uprobe); |
470 | spin_unlock_irqrestore(&uprobes_treelock, flags); | 468 | spin_unlock(&uprobes_treelock); |
471 | 469 | ||
472 | /* For now assume that the instruction need not be single-stepped */ | 470 | /* For now assume that the instruction need not be single-stepped */ |
473 | uprobe->flags |= UPROBE_SKIP_SSTEP; | 471 | uprobe->flags |= UPROBE_SKIP_SSTEP; |
@@ -686,7 +684,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, | |||
686 | set_bit(MMF_HAS_UPROBES, &mm->flags); | 684 | set_bit(MMF_HAS_UPROBES, &mm->flags); |
687 | 685 | ||
688 | ret = set_swbp(&uprobe->arch, mm, vaddr); | 686 | ret = set_swbp(&uprobe->arch, mm, vaddr); |
689 | if (ret && first_uprobe) | 687 | if (!ret) |
688 | clear_bit(MMF_RECALC_UPROBES, &mm->flags); | ||
689 | else if (first_uprobe) | ||
690 | clear_bit(MMF_HAS_UPROBES, &mm->flags); | 690 | clear_bit(MMF_HAS_UPROBES, &mm->flags); |
691 | 691 | ||
692 | return ret; | 692 | return ret; |
@@ -695,6 +695,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, | |||
695 | static void | 695 | static void |
696 | remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) | 696 | remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) |
697 | { | 697 | { |
698 | /* can happen if uprobe_register() fails */ | ||
699 | if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) | ||
700 | return; | ||
701 | |||
702 | set_bit(MMF_RECALC_UPROBES, &mm->flags); | ||
698 | set_orig_insn(&uprobe->arch, mm, vaddr); | 703 | set_orig_insn(&uprobe->arch, mm, vaddr); |
699 | } | 704 | } |
700 | 705 | ||
@@ -705,11 +710,9 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad | |||
705 | */ | 710 | */ |
706 | static void delete_uprobe(struct uprobe *uprobe) | 711 | static void delete_uprobe(struct uprobe *uprobe) |
707 | { | 712 | { |
708 | unsigned long flags; | 713 | spin_lock(&uprobes_treelock); |
709 | |||
710 | spin_lock_irqsave(&uprobes_treelock, flags); | ||
711 | rb_erase(&uprobe->rb_node, &uprobes_tree); | 714 | rb_erase(&uprobe->rb_node, &uprobes_tree); |
712 | spin_unlock_irqrestore(&uprobes_treelock, flags); | 715 | spin_unlock(&uprobes_treelock); |
713 | iput(uprobe->inode); | 716 | iput(uprobe->inode); |
714 | put_uprobe(uprobe); | 717 | put_uprobe(uprobe); |
715 | atomic_dec(&uprobe_events); | 718 | atomic_dec(&uprobe_events); |
@@ -897,7 +900,8 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * | |||
897 | } | 900 | } |
898 | 901 | ||
899 | mutex_unlock(uprobes_hash(inode)); | 902 | mutex_unlock(uprobes_hash(inode)); |
900 | put_uprobe(uprobe); | 903 | if (uprobe) |
904 | put_uprobe(uprobe); | ||
901 | 905 | ||
902 | return ret; | 906 | return ret; |
903 | } | 907 | } |
@@ -967,7 +971,6 @@ static void build_probe_list(struct inode *inode, | |||
967 | struct list_head *head) | 971 | struct list_head *head) |
968 | { | 972 | { |
969 | loff_t min, max; | 973 | loff_t min, max; |
970 | unsigned long flags; | ||
971 | struct rb_node *n, *t; | 974 | struct rb_node *n, *t; |
972 | struct uprobe *u; | 975 | struct uprobe *u; |
973 | 976 | ||
@@ -975,7 +978,7 @@ static void build_probe_list(struct inode *inode, | |||
975 | min = vaddr_to_offset(vma, start); | 978 | min = vaddr_to_offset(vma, start); |
976 | max = min + (end - start) - 1; | 979 | max = min + (end - start) - 1; |
977 | 980 | ||
978 | spin_lock_irqsave(&uprobes_treelock, flags); | 981 | spin_lock(&uprobes_treelock); |
979 | n = find_node_in_range(inode, min, max); | 982 | n = find_node_in_range(inode, min, max); |
980 | if (n) { | 983 | if (n) { |
981 | for (t = n; t; t = rb_prev(t)) { | 984 | for (t = n; t; t = rb_prev(t)) { |
@@ -993,7 +996,7 @@ static void build_probe_list(struct inode *inode, | |||
993 | atomic_inc(&u->ref); | 996 | atomic_inc(&u->ref); |
994 | } | 997 | } |
995 | } | 998 | } |
996 | spin_unlock_irqrestore(&uprobes_treelock, flags); | 999 | spin_unlock(&uprobes_treelock); |
997 | } | 1000 | } |
998 | 1001 | ||
999 | /* | 1002 | /* |
@@ -1030,6 +1033,25 @@ int uprobe_mmap(struct vm_area_struct *vma) | |||
1030 | return 0; | 1033 | return 0; |
1031 | } | 1034 | } |
1032 | 1035 | ||
1036 | static bool | ||
1037 | vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) | ||
1038 | { | ||
1039 | loff_t min, max; | ||
1040 | struct inode *inode; | ||
1041 | struct rb_node *n; | ||
1042 | |||
1043 | inode = vma->vm_file->f_mapping->host; | ||
1044 | |||
1045 | min = vaddr_to_offset(vma, start); | ||
1046 | max = min + (end - start) - 1; | ||
1047 | |||
1048 | spin_lock(&uprobes_treelock); | ||
1049 | n = find_node_in_range(inode, min, max); | ||
1050 | spin_unlock(&uprobes_treelock); | ||
1051 | |||
1052 | return !!n; | ||
1053 | } | ||
1054 | |||
1033 | /* | 1055 | /* |
1034 | * Called in context of a munmap of a vma. | 1056 | * Called in context of a munmap of a vma. |
1035 | */ | 1057 | */ |
@@ -1041,10 +1063,12 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon | |||
1041 | if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ | 1063 | if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ |
1042 | return; | 1064 | return; |
1043 | 1065 | ||
1044 | if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags)) | 1066 | if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || |
1067 | test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) | ||
1045 | return; | 1068 | return; |
1046 | 1069 | ||
1047 | /* TODO: unmapping uprobe(s) will need more work */ | 1070 | if (vma_has_uprobes(vma, start, end)) |
1071 | set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); | ||
1048 | } | 1072 | } |
1049 | 1073 | ||
1050 | /* Slot allocation for XOL */ | 1074 | /* Slot allocation for XOL */ |
@@ -1150,8 +1174,11 @@ void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) | |||
1150 | { | 1174 | { |
1151 | newmm->uprobes_state.xol_area = NULL; | 1175 | newmm->uprobes_state.xol_area = NULL; |
1152 | 1176 | ||
1153 | if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) | 1177 | if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { |
1154 | set_bit(MMF_HAS_UPROBES, &newmm->flags); | 1178 | set_bit(MMF_HAS_UPROBES, &newmm->flags); |
1179 | /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ | ||
1180 | set_bit(MMF_RECALC_UPROBES, &newmm->flags); | ||
1181 | } | ||
1155 | } | 1182 | } |
1156 | 1183 | ||
1157 | /* | 1184 | /* |
@@ -1369,6 +1396,25 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) | |||
1369 | return false; | 1396 | return false; |
1370 | } | 1397 | } |
1371 | 1398 | ||
1399 | static void mmf_recalc_uprobes(struct mm_struct *mm) | ||
1400 | { | ||
1401 | struct vm_area_struct *vma; | ||
1402 | |||
1403 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
1404 | if (!valid_vma(vma, false)) | ||
1405 | continue; | ||
1406 | /* | ||
1407 | * This is not strictly accurate, we can race with | ||
1408 | * uprobe_unregister() and see the already removed | ||
1409 | * uprobe if delete_uprobe() was not yet called. | ||
1410 | */ | ||
1411 | if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) | ||
1412 | return; | ||
1413 | } | ||
1414 | |||
1415 | clear_bit(MMF_HAS_UPROBES, &mm->flags); | ||
1416 | } | ||
1417 | |||
1372 | static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) | 1418 | static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) |
1373 | { | 1419 | { |
1374 | struct mm_struct *mm = current->mm; | 1420 | struct mm_struct *mm = current->mm; |
@@ -1390,11 +1436,24 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) | |||
1390 | } else { | 1436 | } else { |
1391 | *is_swbp = -EFAULT; | 1437 | *is_swbp = -EFAULT; |
1392 | } | 1438 | } |
1439 | |||
1440 | if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) | ||
1441 | mmf_recalc_uprobes(mm); | ||
1393 | up_read(&mm->mmap_sem); | 1442 | up_read(&mm->mmap_sem); |
1394 | 1443 | ||
1395 | return uprobe; | 1444 | return uprobe; |
1396 | } | 1445 | } |
1397 | 1446 | ||
1447 | void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) | ||
1448 | { | ||
1449 | user_enable_single_step(current); | ||
1450 | } | ||
1451 | |||
1452 | void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) | ||
1453 | { | ||
1454 | user_disable_single_step(current); | ||
1455 | } | ||
1456 | |||
1398 | /* | 1457 | /* |
1399 | * Run handler and ask thread to singlestep. | 1458 | * Run handler and ask thread to singlestep. |
1400 | * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. | 1459 | * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. |
@@ -1441,7 +1500,7 @@ static void handle_swbp(struct pt_regs *regs) | |||
1441 | 1500 | ||
1442 | utask->state = UTASK_SSTEP; | 1501 | utask->state = UTASK_SSTEP; |
1443 | if (!pre_ssout(uprobe, regs, bp_vaddr)) { | 1502 | if (!pre_ssout(uprobe, regs, bp_vaddr)) { |
1444 | user_enable_single_step(current); | 1503 | arch_uprobe_enable_step(&uprobe->arch); |
1445 | return; | 1504 | return; |
1446 | } | 1505 | } |
1447 | 1506 | ||
@@ -1477,10 +1536,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) | |||
1477 | else | 1536 | else |
1478 | WARN_ON_ONCE(1); | 1537 | WARN_ON_ONCE(1); |
1479 | 1538 | ||
1539 | arch_uprobe_disable_step(&uprobe->arch); | ||
1480 | put_uprobe(uprobe); | 1540 | put_uprobe(uprobe); |
1481 | utask->active_uprobe = NULL; | 1541 | utask->active_uprobe = NULL; |
1482 | utask->state = UTASK_RUNNING; | 1542 | utask->state = UTASK_RUNNING; |
1483 | user_disable_single_step(current); | ||
1484 | xol_free_insn_slot(current); | 1543 | xol_free_insn_slot(current); |
1485 | 1544 | ||
1486 | spin_lock_irq(¤t->sighand->siglock); | 1545 | spin_lock_irq(¤t->sighand->siglock); |