aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2025-07-20 13:21:14 +0200
committerPeter Zijlstra <peterz@infradead.org>2025-08-21 20:09:19 +0200
commit33d7b2beaf34a3c0f6406bc76f6e1b1755150ad9 (patch)
treef1819b080373540bc5c68352b5d22eba9d108d17 /kernel
parentuprobes: Make copy_from_page global (diff)
downloadlinux-33d7b2beaf34a3c0f6406bc76f6e1b1755150ad9.tar.gz
linux-33d7b2beaf34a3c0f6406bc76f6e1b1755150ad9.zip
uprobes: Add uprobe_write function
Adding uprobe_write function that does what uprobe_write_opcode did so far, but allows to pass verify callback function that checks the memory location before writing the opcode. It will be used in following changes to implement specific checking logic for instruction update. The uprobe_write_opcode now calls uprobe_write with verify_opcode as the verify callback. 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-5-jolsa@kernel.org
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/uprobes.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index f993a3422083..838ac40e91e6 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -399,7 +399,7 @@ static bool orig_page_is_identical(struct vm_area_struct *vma,
return identical;
}
-static int __uprobe_write_opcode(struct vm_area_struct *vma,
+static int __uprobe_write(struct vm_area_struct *vma,
struct folio_walk *fw, struct folio *folio,
unsigned long opcode_vaddr, uprobe_opcode_t opcode)
{
@@ -488,6 +488,12 @@ remap:
int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
const unsigned long opcode_vaddr, uprobe_opcode_t opcode)
{
+ return uprobe_write(auprobe, vma, opcode_vaddr, opcode, verify_opcode);
+}
+
+int uprobe_write(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
+ const unsigned long opcode_vaddr, uprobe_opcode_t opcode, uprobe_write_verify_t verify)
+{
const unsigned long vaddr = opcode_vaddr & PAGE_MASK;
struct mm_struct *mm = vma->vm_mm;
struct uprobe *uprobe;
@@ -509,7 +515,7 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
* page that we can safely modify. Use FOLL_WRITE to trigger a write
* fault if required. When unregistering, we might be lucky and the
* anon page is already gone. So defer write faults until really
- * required. Use FOLL_SPLIT_PMD, because __uprobe_write_opcode()
+ * required. Use FOLL_SPLIT_PMD, because __uprobe_write()
* cannot deal with PMDs yet.
*/
if (is_register)
@@ -521,7 +527,7 @@ retry:
goto out;
folio = page_folio(page);
- ret = verify_opcode(page, opcode_vaddr, &opcode);
+ ret = verify(page, opcode_vaddr, &opcode);
if (ret <= 0) {
folio_put(folio);
goto out;
@@ -560,7 +566,7 @@ retry:
/* Walk the page tables again, to perform the actual update. */
if (folio_walk_start(&fw, vma, vaddr, 0)) {
if (fw.page == page)
- ret = __uprobe_write_opcode(vma, &fw, folio, opcode_vaddr, opcode);
+ ret = __uprobe_write(vma, &fw, folio, opcode_vaddr, opcode);
folio_walk_end(&fw, vma);
}