public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
To: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>,
	Ingo Molnar <mingo@redhat.com>,
	linux-kernel@vger.kernel.org, jolsa@redhat.com,
	dvyukov@google.com, namhyung@kernel.org, xiexiuqi@huawei.com,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com
Subject: [RFC PATCH] perf: Paper over the hw.target problems
Date: Thu, 28 Feb 2019 16:01:09 +0200	[thread overview]
Message-ID: <20190228140109.64238-1-alexander.shishkin@linux.intel.com> (raw)
In-Reply-To: <278ac311-d8f3-2832-5fa1-522471c8c31c@huawei.com>

First, we have a race between perf_event_release_kernel() and
perf_free_event(), which happens when parent's event is released while the
child's fork fails (because of a fatal signal, for example), that looks
like this:

cpu X                            cpu Y
-----                            -----
                                 copy_process() error path
perf_release(parent)             +->perf_event_free_task()
+-> lock(child_ctx->mutex)       |  |
+-> remove_from_context(child)   |  |
+-> unlock(child_ctx->mutex)     |  |
|                                |  +-> lock(child_ctx->mutex)
|                                |  +-> unlock(child_ctx->mutex)
|                                +-> free_task(child_task)
+-> put_task_struct(child_task)

Technically, we're still holding a reference to the task via
parent->hw.target, that's not stopping free_task(), so we end up poking at
free'd memory, as is pointed out by KASAN in the syzkaller report (see Link
below). The straightforward fix is to drop the hw.target reference while
the task is still around.

Therein lies the second problem: the users of hw.target (uprobe) assume
that it's around at ->destroy() callback time, where they use it for
context. So, in order to not break the uprobe teardown and avoid leaking
stuff, we need to call ->destroy() at the same time.

This patch fixes the race and the subsequent fallout by doing both these
things at remove_from_context time.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Link: https://syzkaller.appspot.com/bug?extid=a24c397a29ad22d86c98
Reported-by: syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com
---
 kernel/events/core.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 36b8320590e8..640695d114f8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2105,6 +2105,27 @@ static void perf_remove_from_context(struct perf_event *event, unsigned long fla
 
 	event_function_call(event, __perf_remove_from_context, (void *)flags);
 
+	/*
+	 * This is as passable as any hw.target handling out there;
+	 * hw.target implies task context, therefore, no migration.
+	 * Which means that we can only get here at the teardown.
+	 */
+	if (event->hw.target) {
+		/*
+		 * Now, the problem with, say uprobes, is that they
+		 * use hw.target for context in their ->destroy()
+		 * callbacks. Supposedly, they may need to poke at
+		 * its contents, so better call it while we still
+		 * have the task.
+		 */
+		if (event->destroy) {
+			event->destroy(event);
+			event->destroy = NULL;
+		}
+		put_task_struct(event->hw.target);
+		event->hw.target = NULL;
+	}
+
 	/*
 	 * The above event_function_call() can NO-OP when it hits
 	 * TASK_TOMBSTONE. In that case we must already have been detached
-- 
2.20.1


  reply	other threads:[~2019-02-28 14:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-09  5:52 KASAN: use-after-free Write in _free_event syzbot
2018-07-09 10:11 ` Alexander Shishkin
2018-07-09 11:02   ` Dmitry Vyukov
2019-02-16 10:43   ` Xie XiuQi
2019-02-28 14:01     ` Alexander Shishkin [this message]
     [not found]       ` <c174549c-d169-7773-2f47-5863ba0b8056@huawei.com>
2019-03-08 12:38         ` [RFC PATCH] perf: Paper over the hw.target problems Alexander Shishkin
2019-03-11 13:32           ` chengjian (D)
2019-03-08 15:54       ` Mark Rutland
2019-06-24 12:19         ` Peter Zijlstra
2019-06-25  8:49           ` Peter Zijlstra
2019-06-25 10:43             ` [PATCH] perf: Fix race between close() and fork() Peter Zijlstra
2019-06-25 12:20               ` Alexander Shishkin
2019-06-28 16:50               ` Mark Rutland
2019-06-28 20:46                 ` Peter Zijlstra
2019-07-01  9:24                   ` Mark Rutland
2018-07-10  2:16 ` KASAN: use-after-free Write in _free_event syzbot

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=20190228140109.64238-1-alexander.shishkin@linux.intel.com \
    --to=alexander.shishkin@linux.intel.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@redhat.com \
    --cc=dvyukov@google.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com \
    --cc=xiexiuqi@huawei.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