mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Hui Peng <benquike@gmail.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	James Clark <james.clark@linaro.org>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	Hui Peng <benquike@gmail.com>,
	stable@vger.kernel.org
Subject: [PATCH v2] perf/core: fix user->locked_vm leak on secondary mmap()
Date: Mon, 21 Sep 2026 00:33:06 +0000	[thread overview]
Message-ID: <20260921003306.426050-1-benquike@gmail.com> (raw)
In-Reply-To: <20260919221728.3707189-1-benquike@gmail.com>

Commit 0c8a4e4139ad ("perf/core: Further simplify perf_mmap()") hoisted
`user_extra = nr_pages` ahead of the existing-buffer checks (`if
(event->rb)` and `if (rb_has_aux(rb))`), and subsequently
commit 5d299897f1e3 ("perf: Split out the RB allocation") and
commit 2aee37682391 ("perf: Split out the AUX buffer allocation")
carried `long extra = 0, user_extra = nr_pages` into perf_mmap_rb() and
perf_mmap_aux().

As a result, when an already-allocated ring buffer (`event->rb`) or AUX
buffer (`rb_has_aux(rb)`) is mapped again via mmap(), perf_mmap_account()
is called with `user_extra = nr_pages` instead of `0`, charging `nr_pages`
to `current_user()->locked_vm` on every additional mapping. However,
perf_mmap_unaccount() and perf_mmap_close() only subtract the ring buffer's
and AUX buffer's pages once when the final `rb->mmap_count` /
`rb->aux_mmap_count` reference drops to zero. Consequently, every secondary
mmap() + munmap() cycle on a perf event permanently leaks `nr_pages` in
`user->locked_vm`, eventually exhausting `perf_event_mlock_kb` and
`RLIMIT_MEMLOCK` (-EPERM) for that user.

Fix this by only calling perf_mmap_account() when allocating a new ring
buffer in perf_mmap_rb() or a new AUX buffer in perf_mmap_aux().

Tested in QEMU against Linux 7.3.0-rc3 with a standalone C reproducer
running as an unprivileged user (UID 1000, RLIMIT_MEMLOCK=0,
perf_event_paranoid=1) that opens a software perf event, maps a 65-page
ring buffer, performs 10 secondary mmap() + munmap() cycles on the same
event fd, and then unmaps and closes the event. On the unfixed kernel,
subsequent perf_mmap() calls by UID 1000 permanently fail with -EPERM due
to the leaked `user->locked_vm` (650 pages leaked), whereas with the fix
applied `user->locked_vm` returns to 0 and subsequent perf_mmap() calls
succeed.

Fixes: 0c8a4e4139ad ("perf/core: Further simplify perf_mmap()")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
Changes in v2:
- Dropped the cross-MM `pinned_vm` / `rb->mmap_mm` (`mmgrab`/`mmdrop`)
  changes (which caused an RCU softirq context violation in `rb_free_rcu()`
  in v1, flagged by sashiko-bot) to keep this patch focused on the
  `user->locked_vm` leak on secondary `mmap()`.
- Updated the `Fixes:` tag to `0c8a4e4139ad ("perf/core: Further simplify
  perf_mmap()")` and added QEMU reproducer test details to the commit
  message.

 kernel/events/core.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index fe33fe15689d..8fc15239bd7e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7311,7 +7311,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;
 		}
@@ -7399,7 +7398,6 @@ 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);
-
 	} else {
 		if (!perf_mmap_calc_limits(vma, &user_extra, &extra)) {
 			refcount_dec(&rb->mmap_count);
@@ -7420,9 +7418,9 @@ 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;
+		perf_mmap_account(vma, user_extra, extra);
 	}
 
-	perf_mmap_account(vma, user_extra, extra);
 	refcount_inc(&event->mmap_count);
 
 	return 0;
-- 
2.47.3

  reply	other threads:[~2026-09-21  0:33 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19 22:17 [PATCH] perf/core: fix locked_vm leak on alias mmap() and cross-MM pinned_vm underflow Hui Peng
2026-09-21  0:33 ` Hui Peng [this message]
2026-09-21 15:10   ` [PATCH v2] perf/core: fix user->locked_vm leak on secondary mmap() krzk
2026-09-21 15:13   ` krzk

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=20260921003306.426050-1-benquike@gmail.com \
    --to=benquike@gmail.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --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 \
    --cc=stable@vger.kernel.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®