Linux Perf Users
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: vineash <vineash30640@gmail.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH] perf/core: Fix double put of the system-wide perf_ctx_data reference
Date: Sat, 03 Oct 2026 20:30:40 +0000	[thread overview]
Message-ID: <20261003203040.EE6631F0089B@smtp.kernel.org> (raw)
In-Reply-To: <179105852659.1844849.16381123619267169417@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] perf/core: memory leak of perf_ctx_data due to TOCTOU race in attach_global_ctx_data()
- [Medium] perf/core: data race on cd->global leading to undefined behavior
--

commit 6c40093668f0aa28205d435b7cecaca312682e03
Author: vineash <vineash30640@gmail.com>

perf/core: Fix double put of the system-wide perf_ctx_data reference

The reference on a task's perf_ctx_data that belongs to the system-wide
events (cd->global) can be put twice. __detach_global_ctx_data() puts it
when the last system-wide event goes away, and perf_event_exit_task()
puts it again when the task exits.

> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index a34ff4cb410da..63122c3b872ef 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5498,8 +5498,9 @@ attach_global_ctx_data(struct kmem_cache *ctx_cache)
>  				continue;
>  			cd = rcu_dereference(p->perf_ctx_data);
>  			if (cd && !cd->global) {
> -				cd->global = 1;
> -				if (!refcount_inc_not_zero(&cd->refcount))
> +				if (refcount_inc_not_zero(&cd->refcount))
> +					cd->global = 1;

[Severity: High]
Does this introduce a TOCTOU race condition that can leak the perf_ctx_data
reference?

Earlier in attach_global_ctx_data(), the code checks if the task is exiting
without holding locks that exclude do_exit():

    if (p->flags & PF_EXITING)
        continue;

Could a task concurrently set PF_EXITING and call perf_event_exit_task(),
which then calls detach_task_global_ctx_data()?

If so, the exiting task would observe cd->global == 0 via xchg(), miss the
cleanup, and return. Then this code continues, increments cd->refcount, and
sets cd->global = 1. Because the exiting task has already bypassed the
cleanup phase, it will never drop this reference. Once the task is unhashed,
__detach_global_ctx_data() will not find it, resulting in a permanent
memory leak of the perf_ctx_data structure.

A local user with perf_event_paranoid=2 might trigger this by racing
CPU-wide perf event creation with task exits.

[Severity: Medium]
Does this plain store to cd->global race with the atomic xchg() operation in
detach_task_global_ctx_data() from an exiting task?

Because perf_event_exit_task() executes without holding global_ctx_data_rwsem,
these accesses appear unsynchronized, which violates the Linux Kernel Memory
Model and can lead to undefined behavior.

> +				else
>  					cd = NULL;
>  			}
>  			if (!cd) {

[ ... ]

> @@ -5569,19 +5570,33 @@ detach_task_ctx_data(struct task_struct *p)
>  		perf_free_ctx_data_rcu(cd);
>  }
>  
> +/*
> + * Drop the reference owned by the system-wide events, if @p still holds one.
> + *
> + * Both __detach_global_ctx_data() and perf_event_exit_task() may try to drop
> + * it concurrently; claiming ->global with xchg() makes sure only one of them
> + * does, otherwise the refcount is decremented twice.
> + */
> +static void detach_task_global_ctx_data(struct task_struct *p)
> +{
> +	struct perf_ctx_data *cd;
> +
> +	scoped_guard (rcu) {
> +		cd = rcu_dereference(p->perf_ctx_data);
> +		if (!cd || !xchg(&cd->global, 0))
> +			return;
> +	}
> +
> +	detach_task_ctx_data(p);
> +}

[ ... ]

> @@ -9459,8 +9474,8 @@ perf_event_alloc_task_data(struct task_struct *child,
>  		}
>  
>  		if (!cd->global) {
> -			cd->global = 1;
>  			refcount_inc(&cd->refcount);
> +			cd->global = 1;

[Severity: Medium]
Similar to the concern in attach_global_ctx_data(), does this plain store
to cd->global race with the atomic xchg() operation from an exiting task in
detach_task_global_ctx_data()?

>  		}
>  	}
>  

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/179105852659.1844849.16381123619267169417@gmail.com?part=1

      reply	other threads:[~2026-10-03 20:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-03 20:15 [PATCH] perf/core: Fix double put of the system-wide perf_ctx_data reference vineash
2026-10-03 20:30 ` sashiko-bot [this message]

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=20261003203040.EE6631F0089B@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vineash30640@gmail.com \
    /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