From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755348AbcAROoR (ORCPT ); Mon, 18 Jan 2016 09:44:17 -0500 Received: from bombadil.infradead.org ([198.137.202.9]:52825 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754972AbcAROoP (ORCPT ); Mon, 18 Jan 2016 09:44:15 -0500 Date: Mon, 18 Jan 2016 15:44:10 +0100 From: Peter Zijlstra To: Alexander Shishkin Cc: Ingo Molnar , linux-kernel@vger.kernel.org, vince@deater.net, eranian@google.com, Arnaldo Carvalho de Melo , Jiri Olsa Subject: Re: [PATCH] perf: Synchronously cleanup child events Message-ID: <20160118144410.GS6357@twins.programming.kicks-ass.net> References: <20160115130932.GL6357@twins.programming.kicks-ass.net> <1452866861-17680-1-git-send-email-alexander.shishkin@linux.intel.com> <20160115175759.GL3421@worktop> <8760yr83nx.fsf@ashishki-desk.ger.corp.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <8760yr83nx.fsf@ashishki-desk.ger.corp.intel.com> User-Agent: Mutt/1.5.21 (2012-12-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Jan 18, 2016 at 02:37:06PM +0200, Alexander Shishkin wrote: > Or how about this instead: In principle better since it doesn't increase the lock hold times etc., but buggy I think: > diff --git a/kernel/events/core.c b/kernel/events/core.c > index 8eb3fee429..cd9f1ac537 100644 > --- a/kernel/events/core.c > +++ b/kernel/events/core.c > @@ -3786,8 +3786,9 @@ int perf_event_release_kernel(struct perf_event *event) > > event->owner = NULL; > > +retry: > /* > - * event::child_mutex nests inside ctx::lock, so move children > + * event::child_mutex nests inside ctx::mutex, so move children > * to a safe place first and avoid inversion > */ > mutex_lock(&event->child_mutex); > @@ -3818,8 +3819,13 @@ int perf_event_release_kernel(struct perf_event *event) > put_event(event); > } > > - /* Must be the last reference */ > + /* Must be the last reference, .. */ > put_event(event); > + > + /* .. unless we raced with inherit_event(), in which case, repeat */ Nothing prevents @event from being freed here, which would make: > + if (atomic_long_inc_not_zero(&event->refcount)) a use-after-free. You'll have to do something like: static bool put_event_last(struct perf_event *event, long value) { if (atomic_long_cmpxchg(&event->refcount, 1, 0)) { __put_event(event); /* normal put_event() body */ return true; } return false; } with which you can do: if (!put_event_last(event)) goto retry;