Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323845
b: refs/heads/master
c: 9f68f67
h: refs/heads/master
i:
  323843: 95e22e9
v: v3
  • Loading branch information
Oleg Nesterov committed Sep 15, 2012
1 parent 063d113 commit c74784f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6f47caa0e1e4887aa2ddca8388d058d35725d815
refs/heads/master: 9f68f672c47b9bd4cfe0a667ecb0b1382c61e2de
3 changes: 2 additions & 1 deletion trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ extern int get_dumpable(struct mm_struct *mm);
#define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */
#define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */

#define MMF_HAS_UPROBES 19 /* might have uprobes */
#define MMF_HAS_UPROBES 19 /* has uprobes */
#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */

#define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK)

Expand Down
39 changes: 35 additions & 4 deletions trunk/kernel/events/uprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
set_bit(MMF_HAS_UPROBES, &mm->flags);

ret = set_swbp(&uprobe->arch, mm, vaddr);
if (ret && first_uprobe)
if (!ret)
clear_bit(MMF_RECALC_UPROBES, &mm->flags);
else if (first_uprobe)
clear_bit(MMF_HAS_UPROBES, &mm->flags);

return ret;
Expand All @@ -693,6 +695,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
static void
remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
{
/* can happen if uprobe_register() fails */
if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
return;

set_bit(MMF_RECALC_UPROBES, &mm->flags);
set_orig_insn(&uprobe->arch, mm, vaddr);
}

Expand Down Expand Up @@ -1026,6 +1033,25 @@ int uprobe_mmap(struct vm_area_struct *vma)
return 0;
}

static bool
vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end)
{
loff_t min, max;
struct inode *inode;
struct rb_node *n;

inode = vma->vm_file->f_mapping->host;

min = vaddr_to_offset(vma, start);
max = min + (end - start) - 1;

spin_lock(&uprobes_treelock);
n = find_node_in_range(inode, min, max);
spin_unlock(&uprobes_treelock);

return !!n;
}

/*
* Called in context of a munmap of a vma.
*/
Expand All @@ -1037,10 +1063,12 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
return;

if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags))
if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) ||
test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags))
return;

/* TODO: unmapping uprobe(s) will need more work */
if (vma_has_uprobes(vma, start, end))
set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags);
}

/* Slot allocation for XOL */
Expand Down Expand Up @@ -1146,8 +1174,11 @@ void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
{
newmm->uprobes_state.xol_area = NULL;

if (test_bit(MMF_HAS_UPROBES, &oldmm->flags))
if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) {
set_bit(MMF_HAS_UPROBES, &newmm->flags);
/* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */
set_bit(MMF_RECALC_UPROBES, &newmm->flags);
}
}

/*
Expand Down

0 comments on commit c74784f

Please sign in to comment.