kernel/events/uprobes: pass VMA to set_swbp(), set_orig_insn() and uprobe_write_opcode()
authorDavid Hildenbrand <david@redhat.com>
Fri, 21 Mar 2025 11:37:12 +0000 (12:37 +0100)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 12 May 2025 00:48:18 +0000 (17:48 -0700)
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: David Hildenbrand <david@redhat.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Peter 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: Andrew Morton <akpm@linux-foundation.org>
arch/arm/probes/uprobes/core.c
include/linux/uprobes.h
kernel/events/uprobes.c

index f5f790c6e5f896590b8394c7d6e0fa54c85d3879..885e0c5e8c20dfd70f67b82ff8523bb128454715 100644 (file)
@@ -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));
 }
 
index 2e46b69ff0a6f044ddf7aaa0fe45b92af20d359c..516217c390946cf70bb8568893508623dfa4380d 100644 (file)
@@ -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);
index 8dc23ca9f66ff0347f2c14e064ec0ecf9da14b8d..c33d710e8db7f95e1f7751fa9e3f96413b30e0f5 100644 (file)
@@ -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,
-                       unsigned long vaddr, uprobe_opcode_t opcode)
+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 @@ retry:
        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 @@ put_old:
 /**
  * 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 {