Commit 8a557742 authored by David Hildenbrand's avatar David Hildenbrand Committed by Andrew Morton
Browse files

kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and uprobe_write_opcode()

We already have the VMA, no need to look it up using
get_user_page_vma_remote().  We can now switch to get_user_pages_remote().

Link: https://lkml.kernel.org/r/20250321113713.204682-3-david@redhat.com


Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <olsajiri@gmail.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Namhyung kim <namhyung@kernel.org>
Cc: Russel King <linux@armlinux.org.uk>
Cc: tongtiangen <tongtiangen@huawei.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent b56e6446
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
		(UPROBE_SWBP_ARM_INSN & 0x0fffffff);
}

int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
int set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
	     unsigned long vaddr)
{
	return uprobe_write_opcode(auprobe, mm, vaddr,
	return uprobe_write_opcode(auprobe, vma, vaddr,
		   __opcode_to_mem_arm(auprobe->bpinsn));
}

+3 −3
Original line number Diff line number Diff line
@@ -188,13 +188,13 @@ struct uprobes_state {
};

extern void __init uprobes_init(void);
extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
extern int set_swbp(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
extern int set_orig_insn(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
extern bool is_swbp_insn(uprobe_opcode_t *insn);
extern bool is_trap_insn(uprobe_opcode_t *insn);
extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t);
extern struct uprobe *uprobe_register(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
extern int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool);
extern void uprobe_unregister_nosync(struct uprobe *uprobe, struct uprobe_consumer *uc);
+17 −16
Original line number Diff line number Diff line
@@ -474,19 +474,19 @@ static int update_ref_ctr(struct uprobe *uprobe, struct mm_struct *mm,
 *
 * uprobe_write_opcode - write the opcode at a given virtual address.
 * @auprobe: arch specific probepoint information.
 * @mm: the probed process address space.
 * @vma: the probed virtual memory area.
 * @vaddr: the virtual address to store the opcode.
 * @opcode: opcode to be written at @vaddr.
 *
 * Called with mm->mmap_lock held for read or write.
 * Return 0 (success) or a negative errno.
 */
int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
		unsigned long vaddr, uprobe_opcode_t opcode)
{
	struct mm_struct *mm = vma->vm_mm;
	struct uprobe *uprobe;
	struct page *old_page, *new_page;
	struct vm_area_struct *vma;
	int ret, is_register, ref_ctr_updated = 0;
	bool orig_page_huge = false;
	unsigned int gup_flags = FOLL_FORCE;
@@ -498,9 +498,9 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
	if (is_register)
		gup_flags |= FOLL_SPLIT_PMD;
	/* Read the page with vaddr into memory */
	old_page = get_user_page_vma_remote(mm, vaddr, gup_flags, &vma);
	if (IS_ERR(old_page))
		return PTR_ERR(old_page);
	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags, &old_page, NULL);
	if (ret != 1)
		return ret;

	ret = verify_opcode(old_page, vaddr, &opcode);
	if (ret <= 0)
@@ -590,30 +590,31 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
/**
 * set_swbp - store breakpoint at a given address.
 * @auprobe: arch specific probepoint information.
 * @mm: the probed process address space.
 * @vma: the probed virtual memory area.
 * @vaddr: the virtual address to insert the opcode.
 *
 * For mm @mm, store the breakpoint instruction at @vaddr.
 * Return 0 (success) or a negative errno.
 */
int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
int __weak set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
		unsigned long vaddr)
{
	return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
	return uprobe_write_opcode(auprobe, vma, vaddr, UPROBE_SWBP_INSN);
}

/**
 * set_orig_insn - Restore the original instruction.
 * @mm: the probed process address space.
 * @vma: the probed virtual memory area.
 * @auprobe: arch specific probepoint information.
 * @vaddr: the virtual address to insert the opcode.
 *
 * For mm @mm, restore the original opcode (opcode) at @vaddr.
 * Return 0 (success) or a negative errno.
 */
int __weak
set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
int __weak set_orig_insn(struct arch_uprobe *auprobe,
		struct vm_area_struct *vma, unsigned long vaddr)
{
	return uprobe_write_opcode(auprobe, mm, vaddr,
	return uprobe_write_opcode(auprobe, vma, vaddr,
			*(uprobe_opcode_t *)&auprobe->insn);
}

@@ -1153,7 +1154,7 @@ static int install_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
	if (first_uprobe)
		set_bit(MMF_HAS_UPROBES, &mm->flags);

	ret = set_swbp(&uprobe->arch, mm, vaddr);
	ret = set_swbp(&uprobe->arch, vma, vaddr);
	if (!ret)
		clear_bit(MMF_RECALC_UPROBES, &mm->flags);
	else if (first_uprobe)
@@ -1168,7 +1169,7 @@ static int remove_breakpoint(struct uprobe *uprobe, struct vm_area_struct *vma,
	struct mm_struct *mm = vma->vm_mm;

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

struct map_info {