|
@@ -1396,6 +1396,25 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static void mmf_recalc_uprobes(struct mm_struct *mm)
|
|
|
+{
|
|
|
+ struct vm_area_struct *vma;
|
|
|
+
|
|
|
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
|
|
+ if (!valid_vma(vma, false))
|
|
|
+ continue;
|
|
|
+ /*
|
|
|
+ * This is not strictly accurate, we can race with
|
|
|
+ * uprobe_unregister() and see the already removed
|
|
|
+ * uprobe if delete_uprobe() was not yet called.
|
|
|
+ */
|
|
|
+ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end))
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ clear_bit(MMF_HAS_UPROBES, &mm->flags);
|
|
|
+}
|
|
|
+
|
|
|
static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
|
|
|
{
|
|
|
struct mm_struct *mm = current->mm;
|
|
@@ -1417,6 +1436,9 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
|
|
|
} else {
|
|
|
*is_swbp = -EFAULT;
|
|
|
}
|
|
|
+
|
|
|
+ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags))
|
|
|
+ mmf_recalc_uprobes(mm);
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
|
return uprobe;
|