diff options
| author | Jiri Olsa <jolsa@kernel.org> | 2025-07-20 13:21:11 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2025-08-21 20:09:18 +0200 |
| commit | 7769cb177b23142b83f22abd06e492cc25157893 (patch) | |
| tree | 8114d12dc3ba333eeaba472285514a8774d019bd /kernel/events | |
| parent | 448f97fba9013ffa13f5dd82febd18836b189499 (diff) | |
uprobes: Remove breakpoint in unapply_uprobe under mmap_write_lock
Currently unapply_uprobe takes mmap_read_lock, but it might call
remove_breakpoint which eventually changes user pages.
Current code writes either breakpoint or original instruction, so it can
go away with read lock as explained in here [1]. But with the upcoming
change that writes multiple instructions on the probed address we need
to ensure that any update to mm's pages is exclusive.
[1] https://lore.kernel.org/all/20240710140045.GA1084@redhat.com/
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Link: https://lore.kernel.org/r/20250720112133.244369-2-jolsa@kernel.org
Diffstat (limited to 'kernel/events')
| -rw-r--r-- | kernel/events/uprobes.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 7ca1940607bd..1cbfe3cfe573 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -482,7 +482,7 @@ remap: * @opcode_vaddr: the virtual address to store the opcode. * @opcode: opcode to be written at @opcode_vaddr. * - * Called with mm->mmap_lock held for read or write. + * Called with mm->mmap_lock held for write. * Return 0 (success) or a negative errno. */ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, @@ -1463,7 +1463,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) struct vm_area_struct *vma; int err = 0; - mmap_read_lock(mm); + mmap_write_lock(mm); for_each_vma(vmi, vma) { unsigned long vaddr; loff_t offset; @@ -1480,7 +1480,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm) vaddr = offset_to_vaddr(vma, uprobe->offset); err |= remove_breakpoint(uprobe, vma, vaddr); } - mmap_read_unlock(mm); + mmap_write_unlock(mm); return err; } |
