|
@@ -647,6 +647,7 @@ static int
|
|
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
|
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
|
struct vm_area_struct *vma, unsigned long vaddr)
|
|
struct vm_area_struct *vma, unsigned long vaddr)
|
|
{
|
|
{
|
|
|
|
+ bool first_uprobe;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -678,7 +679,17 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
|
uprobe->flags |= UPROBE_COPY_INSN;
|
|
uprobe->flags |= UPROBE_COPY_INSN;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
|
|
|
|
+ * the task can hit this breakpoint right after __replace_page().
|
|
|
|
+ */
|
|
|
|
+ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags);
|
|
|
|
+ if (first_uprobe)
|
|
|
|
+ set_bit(MMF_HAS_UPROBES, &mm->flags);
|
|
|
|
+
|
|
ret = set_swbp(&uprobe->arch, mm, vaddr);
|
|
ret = set_swbp(&uprobe->arch, mm, vaddr);
|
|
|
|
+ if (ret && first_uprobe)
|
|
|
|
+ clear_bit(MMF_HAS_UPROBES, &mm->flags);
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -1032,6 +1043,9 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
|
|
if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
|
|
if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags))
|
|
|
|
+ return;
|
|
|
|
+
|
|
/* TODO: unmapping uprobe(s) will need more work */
|
|
/* TODO: unmapping uprobe(s) will need more work */
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1142,6 +1156,12 @@ void uprobe_reset_state(struct mm_struct *mm)
|
|
mm->uprobes_state.xol_area = NULL;
|
|
mm->uprobes_state.xol_area = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
|
|
|
|
+{
|
|
|
|
+ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags))
|
|
|
|
+ set_bit(MMF_HAS_UPROBES, &newmm->flags);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* - search for a free slot.
|
|
* - search for a free slot.
|
|
*/
|
|
*/
|
|
@@ -1507,7 +1527,7 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
|
|
{
|
|
{
|
|
struct uprobe_task *utask;
|
|
struct uprobe_task *utask;
|
|
|
|
|
|
- if (!current->mm)
|
|
|
|
|
|
+ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
utask = current->utask;
|
|
utask = current->utask;
|