Commit 7769cb17 authored by Jiri Olsa's avatar Jiri Olsa Committed by Peter Zijlstra
Browse files

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: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarMasami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
Link: https://lore.kernel.org/r/20250720112133.244369-2-jolsa@kernel.org
parent 448f97fb
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -482,7 +482,7 @@ static int __uprobe_write_opcode(struct vm_area_struct *vma,
 * @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;
}