From: Hui Peng <benquike@gmail.com>
To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
namhyung@kernel.org, mark.rutland@arm.com,
alexander.shishkin@linux.intel.com, jolsa@kernel.org,
irogers@google.com
Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] perf/core: fix locked_vm leak on alias mmap() and cross-MM pinned_vm underflow
Date: Sat, 19 Sep 2026 22:17:28 +0000 [thread overview]
Message-ID: <20260919221728.3707189-1-benquike@gmail.com> (raw)
In perf_mmap(), mapping an output ring buffer onto an event via
PERF_EVENT_IOC_SET_OUTPUT / alias mmap() increments user->locked_vm and
mm->pinned_vm without recording the accounting MM on the ring_buffer or
releasing user_extra onperf_mmap_close(), causing a permanent locked_vm
leak and a cross-MM pinned_vm underflow when the mapping is closed in a
different process. Store the accounted mm_struct on struct perf_buffer
and unaccount against the original mm_struct on close.
Fixes: fae85b7c8bcc ("perf: Start the restructuring")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fe33fe15689d..2be9301dcd7c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7050,7 +7050,11 @@ static void perf_mmap_close(struct vm_area_struct *vma)
/* now it's safe to free the pages */
atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->locked_vm);
- atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
+ if (rb->aux_mmap_mm) {
+ atomic64_sub(rb->aux_mmap_locked, &rb->aux_mmap_mm->pinned_vm);
+ mmdrop(rb->aux_mmap_mm);
+ rb->aux_mmap_mm = NULL;
+ }
/* this has to be the last one */
rb_free_aux(rb);
@@ -7272,7 +7276,7 @@ static void perf_mmap_unaccount(struct vm_area_struct *vma, struct perf_buffer *
atomic_long_sub((perf_data_size(rb) >> PAGE_SHIFT) + 1 - rb->mmap_locked,
&user->locked_vm);
- atomic64_sub(rb->mmap_locked, &vma->vm_mm->pinned_vm);
+ atomic64_sub(rb->mmap_locked, &rb->mmap_mm->pinned_vm);
}
static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
@@ -7311,7 +7315,6 @@ static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
* Success -- managed to mmap() the same buffer
* multiple times.
*/
- perf_mmap_account(vma, user_extra, extra);
refcount_inc(&event->mmap_count);
return 0;
}
@@ -7338,6 +7341,8 @@ static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
return -ENOMEM;
rb->mmap_locked = extra;
+ rb->mmap_mm = vma->vm_mm;
+ mmgrab(rb->mmap_mm);
ring_buffer_attach(event, rb);
@@ -7399,7 +7404,8 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event,
if (rb_has_aux(rb)) {
refcount_inc(&rb->aux_mmap_count);
-
+ user_extra = 0;
+ extra = 0;
} else {
if (!perf_mmap_calc_limits(vma, &user_extra, &extra)) {
refcount_dec(&rb->mmap_count);
@@ -7420,6 +7426,8 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event,
refcount_set(&rb->aux_mmap_count, 1);
rb->aux_mmap_locked = extra;
+ rb->aux_mmap_mm = vma->vm_mm;
+ mmgrab(rb->aux_mmap_mm);
}
perf_mmap_account(vma, user_extra, extra);
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index c03c4f2eea57..f10eacd8b590 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -5,6 +5,7 @@
#include <linux/hardirq.h>
#include <linux/uaccess.h>
#include <linux/refcount.h>
+#include <linux/sched/mm.h>
/* Buffer handling */
@@ -38,6 +39,8 @@ struct perf_buffer {
refcount_t mmap_count;
unsigned long mmap_locked;
struct user_struct *mmap_user;
+ struct mm_struct *mmap_mm;
+ struct mm_struct *aux_mmap_mm;
/* AUX area */
struct mutex aux_mutex;
@@ -67,6 +70,10 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head)
struct perf_buffer *rb;
rb = container_of(rcu_head, struct perf_buffer, rcu_head);
+ if (rb->aux_mmap_mm)
+ mmdrop(rb->aux_mmap_mm);
+ if (rb->mmap_mm)
+ mmdrop(rb->mmap_mm);
free_uid(rb->mmap_user);
rb_free(rb);
}
reply other threads:[~2026-09-19 22:17 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260919221728.3707189-1-benquike@gmail.com \
--to=benquike@gmail.com \
--cc=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®