From: Aohan Mei <ljp1205831794@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,
Aohan Mei <henrymei@tencent.com>,
TencentOS Corvus AI <corvus@tencent.com>,
stable@vger.kernel.org
Subject: [PATCH] perf: Fix mmap_count accounting on the perf_mmap_close() race path
Date: Sun, 30 Aug 2026 22:55:05 +0800 [thread overview]
Message-ID: <20260830145512.2583689-1-ljp1205831794@gmail.com> (raw)
From: Aohan Mei <henrymei@tencent.com>
perf_mmap_rb()'s raced path (a concurrent perf_mmap_close() has dropped
rb->mmap_count to 0 but is still blocked on event->mmap_mutex inside
refcount_dec_and_mutex_lock()) installs a fresh ring buffer and then
does refcount_set(&event->mmap_count, 1).
That is wrong: the blocked closer still holds a pending decrement and
the count is 1 at this point. The refcount_set() leaves the count at 1,
so once perf_mmap() drops the mutex the closer observes a 1->0
transition, detaches the *new* buffer via ring_buffer_attach(event,
NULL) and drops its last reference, freeing pages that the racing
mmap() is about to map. A later munmap() of that mapping then finds
event->rb == NULL and crashes the kernel in perf_mmap_close().
Restore the pre-59741451b49c accounting on the raced path: the count is
guaranteed non-zero there, because the closer's decrement of
event->mmap_count only happens while holding mmap_mutex, which the
mapper holds. Use refcount_inc(). Keep refcount_set(..., 1) for the
genuine first mmap, where the 0->1 transition is required and
refcount_inc() would WARN.
Fixes: 59741451b49c ("perf: Identify the 0->1 transition for event::mmap_count")
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Cc: stable@vger.kernel.org
Assisted-by: CodeBuddy:Kimi-K3
Signed-off-by: Aohan Mei <henrymei@tencent.com>
---
kernel/events/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 4638544205f2..adcc04ca05f8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7273,6 +7273,7 @@ static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
long extra = 0, user_extra = nr_pages;
struct perf_buffer *rb;
int rb_flags = 0;
+ bool raced = false;
nr_pages -= 1;
@@ -7314,6 +7315,7 @@ static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
* event and continue as if !event->rb
*/
ring_buffer_attach(event, NULL);
+ raced = true;
}
if (!perf_mmap_calc_limits(vma, &user_extra, &extra))
@@ -7338,7 +7340,21 @@ static int perf_mmap_rb(struct vm_area_struct *vma, struct perf_event *event,
perf_event_update_userpage(event);
perf_mmap_account(vma, user_extra, extra);
- refcount_set(&event->mmap_count, 1);
+
+ /*
+ * On the raced path above, a concurrent perf_mmap_close() can
+ * still have a pending decrement of event->mmap_count: it sits
+ * blocked inside refcount_dec_and_mutex_lock() on event->mmap_mutex
+ * (which we hold) with the count still at 1. Using
+ * refcount_set(..., 1) here would make that closer observe a 1->0
+ * transition once we drop the mutex, causing it to detach and free
+ * the buffer we just installed, while this mmap() still maps it.
+ * The count is guaranteed non-zero on the raced path, so increment.
+ */
+ if (raced)
+ refcount_inc(&event->mmap_count);
+ else
+ refcount_set(&event->mmap_count, 1);
return 0;
}
--
2.43.7
next reply other threads:[~2026-08-30 14:55 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 14:55 Aohan Mei [this message]
2026-08-30 15:13 ` [PATCH] perf: Fix mmap_count accounting on the perf_mmap_close() race path sashiko-bot
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=20260830145512.2583689-1-ljp1205831794@gmail.com \
--to=ljp1205831794@gmail.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=corvus@tencent.com \
--cc=henrymei@tencent.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.