[tip: perf/urgent] perf: Reject exited events as group leaders

From: tip-bot2 for Kyle Zeng

Date: Mon Aug 10 2026 - 06:30:52 EST


The following commit has been merged into the perf/urgent branch of tip:

Commit-ID: fa091f46c3833fb22384f10eade2b4e1e1d0b278
Gitweb: https://git.kernel.org/tip/fa091f46c3833fb22384f10eade2b4e1e1d0b278
Author: Kyle Zeng <kylebot@xxxxxxxxxx>
AuthorDate: Thu, 06 Aug 2026 13:56:55 -07:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Fri, 07 Aug 2026 18:27:04 +02:00

perf: Reject exited events as group leaders

perf_event_remove_on_exec() sets remove-on-exec events to the EXIT state
and detaches their group relationships. The event's file descriptor can
remain open, however, and perf_event_open() currently accepts that event
as a group leader because its early validation rejects only REVOKED and
DEAD events.

A new sibling can consequently be linked to the detached leader. When
the leader is closed, perf_group_detach() observes that its
PERF_ATTACH_GROUP bit is already clear and skips the new sibling. The
sibling then retains a group_leader pointer to the freed event.

Reject group leaders in the EXIT state. Perform the check while holding
the shared context mutex so that an exec in the target task cannot detach
the leader between validation and group attachment.

[peterz: make the earlier test fully consistent]
Fixes: 037a3c43edfb ("perf/core: Detach event groups during remove_on_exec")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Kyle Zeng <kylebot@xxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Link: https://patch.msgid.link/20260806205655.75722-1-kylebot@xxxxxxxxxx
---
kernel/events/core.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index ba5bd6a..bd25e19 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -13972,7 +13972,7 @@ SYSCALL_DEFINE5(perf_event_open,
goto err_fd;
}
group_leader = fd_file(group)->private_data;
- if (group_leader->state <= PERF_EVENT_STATE_REVOKED) {
+ if (group_leader->state <= PERF_EVENT_STATE_EXIT) {
err = -ENODEV;
goto err_fd;
}
@@ -14103,6 +14103,12 @@ SYSCALL_DEFINE5(perf_event_open,
if (group_leader->ctx != ctx)
goto err_locked;

+ /* Recheck under ctx::mutex to serialize against remove-on-exec. */
+ if (group_leader->state <= PERF_EVENT_STATE_EXIT) {
+ err = -ENODEV;
+ goto err_locked;
+ }
+
/*
* Only a group leader can be exclusive or pinned
*/