diff options
| author | Jiri Olsa <jolsa@kernel.org> | 2026-07-03 13:49:07 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-07-03 16:30:35 +0200 |
| commit | 07c308eb2bcfe4727ba669e1ba6f5b0ba7d2696e (patch) | |
| tree | 5d5a18e6ed2252b9e5e79ac7f2faef27396e6bdf | |
| parent | 38af0dd6a266057002eacb170c08298ea912fb0a (diff) | |
| download | linux-07c308eb2bcfe4727ba669e1ba6f5b0ba7d2696e.tar.gz linux-07c308eb2bcfe4727ba669e1ba6f5b0ba7d2696e.zip | |
uprobes/x86: Do not leak trampoline vma mapping on optimization failure
In case the optimization fails, we leak new-ly created trampoline
vma mapping (in case we just created it), let's unmap it.
Fixes: ba2bfc97b462 ("uprobes/x86: Add support to optimize uprobes")
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Link: https://patch.msgid.link/20260703114917.238144-4-jolsa@kernel.org
| -rw-r--r-- | arch/x86/kernel/uprobes.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index a76203a33a7b..7f820560e6f8 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -677,11 +677,14 @@ static unsigned long find_nearest_trampoline(unsigned long vaddr) return high_tramp; } -static struct vm_area_struct *get_uprobe_trampoline(struct mm_struct *mm, unsigned long vaddr) +static struct vm_area_struct *get_uprobe_trampoline(struct mm_struct *mm, unsigned long vaddr, + bool *new_mapping) { VMA_ITERATOR(vmi, mm, 0); struct vm_area_struct *vma; + *new_mapping = false; + if (vaddr > TASK_SIZE || vaddr < PAGE_SIZE) return ERR_PTR(-EINVAL); @@ -696,6 +699,7 @@ static struct vm_area_struct *get_uprobe_trampoline(struct mm_struct *mm, unsign if (IS_ERR_VALUE(vaddr)) return ERR_PTR(vaddr); + *new_mapping = true; return _install_special_mapping(mm, vaddr, PAGE_SIZE, VM_READ|VM_EXEC|VM_MAYEXEC|VM_MAYREAD|VM_DONTCOPY|VM_IO, &tramp_mapping); @@ -1053,6 +1057,7 @@ static int __arch_uprobe_optimize(struct arch_uprobe *auprobe, struct mm_struct { struct pt_regs *regs = task_pt_regs(current); struct vm_area_struct *vma, *tramp; + bool new_mapping; int ret; if (!user_64bit_mode(regs)) @@ -1060,10 +1065,13 @@ static int __arch_uprobe_optimize(struct arch_uprobe *auprobe, struct mm_struct vma = find_vma(mm, vaddr); if (!vma) return -EINVAL; - tramp = get_uprobe_trampoline(mm, vaddr); + tramp = get_uprobe_trampoline(mm, vaddr, &new_mapping); if (IS_ERR(tramp)) return PTR_ERR(tramp); - return WARN_ON_ONCE(swbp_optimize(auprobe, vma, vaddr, tramp->vm_start)); + ret = swbp_optimize(auprobe, vma, vaddr, tramp->vm_start); + if (WARN_ON_ONCE(ret) && new_mapping) + WARN_ON_ONCE(do_munmap(mm, tramp->vm_start, PAGE_SIZE, NULL)); + return ret; } void arch_uprobe_optimize(struct arch_uprobe *auprobe, unsigned long vaddr) |
