aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/uprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r--kernel/events/uprobes.c22
1 files changed, 3 insertions, 19 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1f02e3bbfc1d..8c5e043cd309 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -38,7 +38,6 @@
38#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) 38#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
39#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE 39#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE
40 40
41static struct srcu_struct uprobes_srcu;
42static struct rb_root uprobes_tree = RB_ROOT; 41static struct rb_root uprobes_tree = RB_ROOT;
43 42
44static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ 43static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */
@@ -738,20 +737,14 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
738} 737}
739 738
740/* 739/*
741 * There could be threads that have hit the breakpoint and are entering the 740 * There could be threads that have already hit the breakpoint. They
742 * notifier code and trying to acquire the uprobes_treelock. The thread 741 * will recheck the current insn and restart if find_uprobe() fails.
743 * calling delete_uprobe() that is removing the uprobe from the rb_tree can 742 * See find_active_uprobe().
744 * race with these threads and might acquire the uprobes_treelock compared
745 * to some of the breakpoint hit threads. In such a case, the breakpoint
746 * hit threads will not find the uprobe. The current unregistering thread
747 * waits till all other threads have hit a breakpoint, to acquire the
748 * uprobes_treelock before the uprobe is removed from the rbtree.
749 */ 743 */
750static void delete_uprobe(struct uprobe *uprobe) 744static void delete_uprobe(struct uprobe *uprobe)
751{ 745{
752 unsigned long flags; 746 unsigned long flags;
753 747
754 synchronize_srcu(&uprobes_srcu);
755 spin_lock_irqsave(&uprobes_treelock, flags); 748 spin_lock_irqsave(&uprobes_treelock, flags);
756 rb_erase(&uprobe->rb_node, &uprobes_tree); 749 rb_erase(&uprobe->rb_node, &uprobes_tree);
757 spin_unlock_irqrestore(&uprobes_treelock, flags); 750 spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -1388,9 +1381,6 @@ void uprobe_free_utask(struct task_struct *t)
1388{ 1381{
1389 struct uprobe_task *utask = t->utask; 1382 struct uprobe_task *utask = t->utask;
1390 1383
1391 if (t->uprobe_srcu_id != -1)
1392 srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
1393
1394 if (!utask) 1384 if (!utask)
1395 return; 1385 return;
1396 1386
@@ -1408,7 +1398,6 @@ void uprobe_free_utask(struct task_struct *t)
1408void uprobe_copy_process(struct task_struct *t) 1398void uprobe_copy_process(struct task_struct *t)
1409{ 1399{
1410 t->utask = NULL; 1400 t->utask = NULL;
1411 t->uprobe_srcu_id = -1;
1412} 1401}
1413 1402
1414/* 1403/*
@@ -1513,9 +1502,6 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
1513 } else { 1502 } else {
1514 *is_swbp = -EFAULT; 1503 *is_swbp = -EFAULT;
1515 } 1504 }
1516
1517 srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
1518 current->uprobe_srcu_id = -1;
1519 up_read(&mm->mmap_sem); 1505 up_read(&mm->mmap_sem);
1520 1506
1521 return uprobe; 1507 return uprobe;
@@ -1656,7 +1642,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
1656 utask->state = UTASK_BP_HIT; 1642 utask->state = UTASK_BP_HIT;
1657 1643
1658 set_thread_flag(TIF_UPROBE); 1644 set_thread_flag(TIF_UPROBE);
1659 current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
1660 1645
1661 return 1; 1646 return 1;
1662} 1647}
@@ -1691,7 +1676,6 @@ static int __init init_uprobes(void)
1691 mutex_init(&uprobes_mutex[i]); 1676 mutex_init(&uprobes_mutex[i]);
1692 mutex_init(&uprobes_mmap_mutex[i]); 1677 mutex_init(&uprobes_mmap_mutex[i]);
1693 } 1678 }
1694 init_srcu_struct(&uprobes_srcu);
1695 1679
1696 return register_die_notifier(&uprobe_exception_nb); 1680 return register_die_notifier(&uprobe_exception_nb);
1697} 1681}