[BUG] perf: cross-mm mmap teardown unaccounts pinned memory from the wrong mm
From: Rafael B. Dias
Date: Wed Jul 22 2026 - 02:06:55 EST
Hello,
perf can unaccount a data-ring pinned_vm charge from a different mm than the
one it charged. An unprivileged user can repeat this to create negative
pinned_vm credit and allocate perf ring pages past RLIMIT_MEMLOCK.
The first VMA that allocates a perf data ring charges the excess pages to
vma->vm_mm->pinned_vm and stores the amount in rb->mmap_locked, but not the
charged mm. If another process maps the perf event fd and closes the final
VMA, perf_mmap_close() subtracts the charge from that process's mm. The
allocating mm remains charged while the final closer gets a negative balance.
I reproduced this as UID 1000 with CapEff=0, NoNewPrivs=1,
perf_event_paranoid=2, and self-owned PERF_TYPE_SOFTWARE events. On a
two-CPU Linux 6.12.94 guest with perf_event_mlock_kb=516, the reproducer kept
270 perf pages live, used 23 short-lived address spaces to create 16,385 pages
of credit, and mapped 65,540 KiB in a receiver with RLIMIT_MEMLOCK=0.
The vulnerable result was:
RESULT mode=vulnerable mmap_errno=0
LIMIT receiver_memlock_kb=0 perf_mlock_kb=516 cpus=2
BASE allowance_pages=258 filler_pages=270
CREDIT pages=16385 requested_pages=16385 requested_kb=65540
With only the accounting owner corrected, the same binary returned EPERM:
RESULT mode=fixed mmap_errno=1
LIMIT receiver_memlock_kb=0 perf_mlock_kb=516 cpus=2
BASE allowance_pages=258 filler_pages=270
CREDIT pages=16385 requested_pages=16385 requested_kb=65540
Commit 26cb63ad11e0 ("perf: Fix perf mmap bugs") introduced the data-ring
accounting pattern. It remains in Linux 6.12.96 and mainline commit
248951ddc14d. AUX teardown has the same final-VMA assumption and also uses the
data ring's mmap_user when a different user allocated AUX.
The proposed patch retains the charged data-ring mm and AUX user/mm, then uses
those owners during final unaccounting. It passes checkpatch and builds
kernel/events/core.o against mainline 248951ddc14d. On a patched 6.12.94 KASAN
kernel, the same reproducer returns EPERM. This runtime test covers the data
ring; the AUX change was reviewed and build-tested.
The source reproducer is available privately on request.
Until a fix is available, workloads can block untrusted perf_event_open()
calls with seccomp or an LSM.
Regards,
Rafael B. Dias