perf events fix
Linus,
Please pull the latest perf/urgent git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf-urgent-2023-10-21
# HEAD: 32671e3799ca2e4590773fd0e63aaa4229e50c06 perf: Disallow mis-matched inherited group reads
Fix group event semantics.
Thanks,
Ingo
------------------>
Peter Zijlstra (1):
perf: Disallow mis-matched inherited group reads
include/linux/perf_event.h | 1 + kernel/events/core.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-)
include/linux/perf_event.h +1 -0
@@ -704,6 +704,7 @@ struct perf_event {/* The cumulative AND of all event_caps for events in this group. */ int group_caps; +unsigned int group_generation;struct perf_event *group_leader;/* * event->pmu will always point to pmu in which this event belongs.
kernel/events/core.c +33 -6
@@ -1954,6 +1954,7 @@ static void perf_group_attach(struct perf_event *event)list_add_tail (&event->sibling_list, &group_leader->sibling_list); group_leader->nr_siblings++; + group_leader->group_generation++;perf_event__header_size (group_leader);
@@ -2144,6 +2145,7 @@ static void perf_group_detach(struct perf_event *event)if (leader != event) {list_del_init (&event->sibling_list); event->group_leader->nr_siblings--; + event->group_leader->group_generation++; goto out; }
@@ -5440,7 +5442,7 @@ static int __perf_read_group_add(struct perf_event *leader, u64 read_format, u64 *values) { struct perf_event_context *ctx = leader->ctx; -struct perf_event *sub; +struct perf_event *sub, *parent;unsigned long flags;int n =1 ;/* skip @nr */ int ret;
@@ -5450,6 +5452,33 @@ static int __perf_read_group_add(struct perf_event *leader,return ret;raw_spin_lock_irqsave (&ctx->lock, flags); +/* +* Verify the grouping between the parent and child (inherited) +* events is still in tact. +* +* Specifically: +* - leader->ctx->lock pins leader->sibling_list +* - parent->child_mutex pins parent->child_list +* - parent->ctx->mutex pins parent->sibling_list +* +* Because parent->ctx != leader->ctx (and child_list nests inside +* ctx->mutex), group destruction is not atomic between children, also +* see perf_event_release_kernel(). Additionally, parent can grow the +* group. +* +* Therefore it is possible to have parent and child groups in a +* different configuration and summing over such a beast makes no sense +* what so ever. +* +* Reject this. +*/ + parent = leader->parent; +if (parent && + (parent->group_generation != leader->group_generation || + parent->nr_siblings != leader->nr_siblings)) { + ret = -ECHILD ; + goto unlock; + }/* * Since we co-schedule groups, {enabled,running} times of siblings
@@ -5483,8 +5512,9 @@ static int __perf_read_group_add(struct perf_event *leader, values[n++] =atomic64_read (&sub->lost_samples); } +unlock:raw_spin_unlock_irqrestore (&ctx->lock, flags); -return 0 ; +return ret; } static int perf_read_group(struct perf_event *event,
@@ -5503,10 +5533,6 @@ static int perf_read_group(struct perf_event *event, values[0 ] =1 + leader->nr_siblings; -/* -* By locking the child_mutex of the leader we effectively -* lock the child list of all siblings.. XXX explain how. -*/ mutex_lock (&leader->child_mutex); ret =__perf_read_group_add (leader, read_format, values);
@@ -13346,6 +13372,7 @@ static int inherit_group(struct perf_event *parent_event, !perf_get_aux_event(child_ctr, leader))return -EINVAL ; } + leader->group_generation = parent_event->group_generation;return 0 ; }
The pull request you sent on Sat, 21 Oct 2023 17:22:58 +0200:
The pull request you sent on Sat, 21 Oct 2023 17:22:58 +0200:
Quoted 1 line
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitperf-urgent-2023-10-21
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/94be133fb2b8a36d79b362b3bafbdfd054a4da89
Thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html