Skip to content

Commit b56e644

Browse files
davidhildenbrandakpm00
authored andcommitted
kernel/events/uprobes: pass VMA instead of MM to remove_breakpoint()
Patch series "kernel/events/uprobes: uprobe_write_opcode() rewrite", v3. Currently, uprobe_write_opcode() implements COW-breaking manually, which is really far from ideal. Further, there is interest in supporting uprobes on hugetlb pages [1], and leaving at least the COW-breaking to the core will make this much easier. Also, I think the current code doesn't really handle some things properly (see patch #3) when replacing/zapping pages. Let's rewrite it, to leave COW-breaking to the fault handler, and handle registration/unregistration by temporarily unmapping the anonymous page, modifying it, and mapping it again. We still have to implement zapping of anonymous pages ourselves, unfortunately. We could look into not performing the temporary unmapping if we can perform the write atomically, which would likely also make adding hugetlb support a lot easier. But, limited (e.g., only PMD/PUD) hugetlb support could be added on top of this with some tweaking. Note that we now won't have to allocate another anonymous folio when unregistering (which will be beneficial for hugetlb as well), we can simply modify the already-mapped one from the registration (if any). When registering a uprobe, we'll first trigger a ptrace-like write fault to break COW, to then modify the already-mapped page. Briefly sanity tested with perf probes and with the bpf uprobes selftest. This patch (of 3): Pass VMA instead of MM to remove_breakpoint() and remove the "MM" argument from install_breakpoint(), because it can easily be derived from the VMA. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: David Hildenbrand <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: "Masami Hiramatsu (Google)" <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Namhyung kim <[email protected]> Cc: Russel King <[email protected]> Cc: tongtiangen <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 79049bb commit b56e644

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

kernel/events/uprobes.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,10 +1134,10 @@ static bool filter_chain(struct uprobe *uprobe, struct mm_struct *mm)
11341134
return ret;
11351135
}
11361136

1137-
static int
1138-
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
1139-
struct vm_area_struct *vma, unsigned long vaddr)
1137+
static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
1138+
unsigned long vaddr)
11401139
{
1140+
struct mm_struct *mm = vma->vm_mm;
11411141
bool first_uprobe;
11421142
int ret;
11431143

@@ -1162,9 +1162,11 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
11621162
return ret;
11631163
}
11641164

1165-
static int
1166-
remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
1165+
static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
1166+
unsigned long vaddr)
11671167
{
1168+
struct mm_struct *mm = vma->vm_mm;
1169+
11681170
set_bit(MMF_RECALC_UPROBES, &mm->flags);
11691171
return set_orig_insn(&uprobe->arch, mm, vaddr);
11701172
}
@@ -1296,10 +1298,10 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
12961298
if (is_register) {
12971299
/* consult only the "caller", new consumer. */
12981300
if (consumer_filter(new, mm))
1299-
err = install_breakpoint(uprobe, mm, vma, info->vaddr);
1301+
err = install_breakpoint(uprobe, vma, info->vaddr);
13001302
} else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
13011303
if (!filter_chain(uprobe, mm))
1302-
err |= remove_breakpoint(uprobe, mm, info->vaddr);
1304+
err |= remove_breakpoint(uprobe, vma, info->vaddr);
13031305
}
13041306

13051307
unlock:
@@ -1472,7 +1474,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
14721474
continue;
14731475

14741476
vaddr = offset_to_vaddr(vma, uprobe->offset);
1475-
err |= remove_breakpoint(uprobe, mm, vaddr);
1477+
err |= remove_breakpoint(uprobe, vma, vaddr);
14761478
}
14771479
mmap_read_unlock(mm);
14781480

@@ -1610,7 +1612,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
16101612
if (!fatal_signal_pending(current) &&
16111613
filter_chain(uprobe, vma->vm_mm)) {
16121614
unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
1613-
install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
1615+
install_breakpoint(uprobe, vma, vaddr);
16141616
}
16151617
put_uprobe(uprobe);
16161618
}

0 commit comments

Comments
 (0)