stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org,
	syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Jiri Olsa <jolsa@redhat.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Stephane Eranian <eranian@google.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Vince Weaver <vincent.weaver@maine.edu>,
	Ingo Molnar <mingo@kernel.org>
Subject: [PATCH 5.2 55/66] perf/core: Fix race between close() and fork()
Date: Fri, 26 Jul 2019 17:24:54 +0200	[thread overview]
Message-ID: <20190726152307.847797843@linuxfoundation.org> (raw)
In-Reply-To: <20190726152301.936055394@linuxfoundation.org>

From: Peter Zijlstra <peterz@infradead.org>

commit 1cf8dfe8a661f0462925df943140e9f6d1ea5233 upstream.

Syzcaller reported the following Use-after-Free bug:

	close()						clone()

							  copy_process()
							    perf_event_init_task()
							      perf_event_init_context()
							        mutex_lock(parent_ctx->mutex)
								inherit_task_group()
								  inherit_group()
								    inherit_event()
								      mutex_lock(event->child_mutex)
								      // expose event on child list
								      list_add_tail()
								      mutex_unlock(event->child_mutex)
							        mutex_unlock(parent_ctx->mutex)

							    ...
							    goto bad_fork_*

							  bad_fork_cleanup_perf:
							    perf_event_free_task()

	  perf_release()
	    perf_event_release_kernel()
	      list_for_each_entry()
		mutex_lock(ctx->mutex)
		mutex_lock(event->child_mutex)
		// event is from the failing inherit
		// on the other CPU
		perf_remove_from_context()
		list_move()
		mutex_unlock(event->child_mutex)
		mutex_unlock(ctx->mutex)

							      mutex_lock(ctx->mutex)
							      list_for_each_entry_safe()
							        // event already stolen
							      mutex_unlock(ctx->mutex)

							    delayed_free_task()
							      free_task()

	     list_for_each_entry_safe()
	       list_del()
	       free_event()
	         _free_event()
		   // and so event->hw.target
		   // is the already freed failed clone()
		   if (event->hw.target)
		     put_task_struct(event->hw.target)
		       // WHOOPSIE, already quite dead

Which puts the lie to the the comment on perf_event_free_task():
'unexposed, unused context' not so much.

Which is a 'fun' confluence of fail; copy_process() doing an
unconditional free_task() and not respecting refcounts, and perf having
creative locking. In particular:

  82d94856fa22 ("perf/core: Fix lock inversion between perf,trace,cpuhp")

seems to have overlooked this 'fun' parade.

Solve it by using the fact that detached events still have a reference
count on their (previous) context. With this perf_event_free_task()
can detect when events have escaped and wait for their destruction.

Debugged-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Reported-by: syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: <stable@vger.kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Fixes: 82d94856fa22 ("perf/core: Fix lock inversion between perf,trace,cpuhp")
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 kernel/events/core.c |   49 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 8 deletions(-)

--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4469,12 +4469,20 @@ static void _free_event(struct perf_even
 	if (event->destroy)
 		event->destroy(event);
 
-	if (event->ctx)
-		put_ctx(event->ctx);
-
+	/*
+	 * Must be after ->destroy(), due to uprobe_perf_close() using
+	 * hw.target.
+	 */
 	if (event->hw.target)
 		put_task_struct(event->hw.target);
 
+	/*
+	 * perf_event_free_task() relies on put_ctx() being 'last', in particular
+	 * all task references must be cleaned up.
+	 */
+	if (event->ctx)
+		put_ctx(event->ctx);
+
 	exclusive_event_destroy(event);
 	module_put(event->pmu->module);
 
@@ -4654,8 +4662,17 @@ again:
 	mutex_unlock(&event->child_mutex);
 
 	list_for_each_entry_safe(child, tmp, &free_list, child_list) {
+		void *var = &child->ctx->refcount;
+
 		list_del(&child->child_list);
 		free_event(child);
+
+		/*
+		 * Wake any perf_event_free_task() waiting for this event to be
+		 * freed.
+		 */
+		smp_mb(); /* pairs with wait_var_event() */
+		wake_up_var(var);
 	}
 
 no_ctx:
@@ -11529,11 +11546,11 @@ static void perf_free_event(struct perf_
 }
 
 /*
- * Free an unexposed, unused context as created by inheritance by
- * perf_event_init_task below, used by fork() in case of fail.
+ * Free a context as created by inheritance by perf_event_init_task() below,
+ * used by fork() in case of fail.
  *
- * Not all locks are strictly required, but take them anyway to be nice and
- * help out with the lockdep assertions.
+ * Even though the task has never lived, the context and events have been
+ * exposed through the child_list, so we must take care tearing it all down.
  */
 void perf_event_free_task(struct task_struct *task)
 {
@@ -11563,7 +11580,23 @@ void perf_event_free_task(struct task_st
 			perf_free_event(event, ctx);
 
 		mutex_unlock(&ctx->mutex);
-		put_ctx(ctx);
+
+		/*
+		 * perf_event_release_kernel() could've stolen some of our
+		 * child events and still have them on its free_list. In that
+		 * case we must wait for these events to have been freed (in
+		 * particular all their references to this task must've been
+		 * dropped).
+		 *
+		 * Without this copy_process() will unconditionally free this
+		 * task (irrespective of its reference count) and
+		 * _free_event()'s put_task_struct(event->hw.target) will be a
+		 * use-after-free.
+		 *
+		 * Wait for all events to drop their context reference.
+		 */
+		wait_var_event(&ctx->refcount, refcount_read(&ctx->refcount) == 1);
+		put_ctx(ctx); /* must be last */
 	}
 }
 



  parent reply	other threads:[~2019-07-26 15:38 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-26 15:23 [PATCH 5.2 00/66] 5.2.4-stable review Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 01/66] bnx2x: Prevent load reordering in tx completion processing Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 02/66] caif-hsi: fix possible deadlock in cfhsi_exit_module() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 03/66] hv_netvsc: Fix extra rcu_read_unlock in netvsc_recv_callback() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 04/66] igmp: fix memory leak in igmpv3_del_delrec() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 05/66] ipv4: dont set IPv6 only flags to IPv4 addresses Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 06/66] ipv6: rt6_check should return NULL if from is NULL Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 07/66] ipv6: Unlink sibling route in case of failure Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 08/66] net: bcmgenet: use promisc for unsupported filters Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 09/66] net: dsa: mv88e6xxx: wait after reset deactivation Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 10/66] net: make skb_dst_force return true when dst is refcounted Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 11/66] net: neigh: fix multiple neigh timer scheduling Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 12/66] net: openvswitch: fix csum updates for MPLS actions Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 13/66] net: phy: sfp: hwmon: Fix scaling of RX power Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 14/66] net_sched: unset TCQ_F_CAN_BYPASS when adding filters Greg Kroah-Hartman
2019-07-27 21:24   ` Sasha Levin
2019-07-28  6:21     ` Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 15/66] net: stmmac: Re-work the queue selection for TSO packets Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 16/66] net/tls: make sure offload also gets the keys wiped Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 17/66] nfc: fix potential illegal memory access Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 18/66] r8169: fix issue with confused RX unit after PHY power-down on RTL8411b Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 19/66] rxrpc: Fix send on a connected, but unbound socket Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 20/66] sctp: fix error handling on stream scheduler initialization Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 21/66] sctp: not bind the socket in sctp_connect Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 22/66] sky2: Disable MSI on ASUS P6T Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 23/66] tcp: be more careful in tcp_fragment() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 24/66] tcp: fix tcp_set_congestion_control() use from bpf hook Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 25/66] tcp: Reset bytes_acked and bytes_received when disconnecting Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 26/66] vrf: make sure skb->data contains ip header to make routing Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 27/66] net/mlx5e: IPoIB, Add error path in mlx5_rdma_setup_rn Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 28/66] net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 29/66] net: bridge: mcast: fix stale ipv6 hdr pointer when handling v6 query Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 30/66] net: bridge: dont cache ether dest pointer on input Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 31/66] net: bridge: stp: dont cache eth dest pointer before skb pull Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 32/66] macsec: fix use-after-free of skb during RX Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 33/66] macsec: fix checksumming after decryption Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 34/66] netrom: fix a memory leak in nr_rx_frame() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 35/66] netrom: hold sock when setting skb->destructor Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 36/66] selftests: txring_overwrite: fix incorrect test of mmap() return value Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 37/66] net/tls: fix poll ignoring partially copied records Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 38/66] net/tls: reject offload of TLS 1.3 Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 39/66] net/mlx5e: Fix port tunnel GRE entropy control Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 40/66] net/mlx5e: Rx, Fix checksum calculation for new hardware Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 41/66] net/mlx5e: Fix return value from timeout recover function Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 42/66] net/mlx5e: Fix error flow in tx reporter diagnose Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 43/66] bnxt_en: Fix VNIC accounting when enabling aRFS on 57500 chips Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 44/66] mlxsw: spectrum_dcb: Configure DSCP map as the last rule is removed Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 45/66] net/mlx5: E-Switch, Fix default encap mode Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 46/66] mlxsw: spectrum: Do not process learned records with a dummy FID Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 47/66] dma-buf: balance refcount inbalance Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 48/66] dma-buf: Discard old fence_excl on retrying get_fences_rcu for realloc Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 49/66] Revert "gpio/spi: Fix spi-gpio regression on active high CS" Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 50/66] gpiolib: of: fix a memory leak in of_gpio_flags_quirks() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 51/66] gpio: davinci: silence error prints in case of EPROBE_DEFER Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 52/66] MIPS: lb60: Fix pin mappings Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 53/66] perf script: Assume native_arch for pipe mode Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 54/66] perf/core: Fix exclusive events grouping Greg Kroah-Hartman
2019-07-26 15:24 ` Greg Kroah-Hartman [this message]
2019-07-26 15:24 ` [PATCH 5.2 56/66] ext4: dont allow any modifications to an immutable file Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 57/66] ext4: enforce the immutable flag on open files Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 58/66] mm: add filemap_fdatawait_range_keep_errors() Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 59/66] jbd2: introduce jbd2_inode dirty range scoping Greg Kroah-Hartman
2019-07-26 15:24 ` [PATCH 5.2 60/66] ext4: use " Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 61/66] ext4: allow directory holes Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 62/66] KVM: nVMX: do not use dangling shadow VMCS after guest reset Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 63/66] KVM: nVMX: Clear pending KVM_REQ_GET_VMCS12_PAGES when leaving nested Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 64/66] Revert "kvm: x86: Use task structs fpu field for user" Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 65/66] sd_zbc: Fix report zones buffer allocation Greg Kroah-Hartman
2019-07-26 15:25 ` [PATCH 5.2 66/66] block: Limit zone array allocation size Greg Kroah-Hartman
2019-07-27  2:14 ` [PATCH 5.2 00/66] 5.2.4-stable review kernelci.org bot
2019-07-27  2:33 ` shuah
2019-07-27 10:50   ` Greg Kroah-Hartman
2019-07-27  5:35 ` Naresh Kamboju
2019-07-27 10:49   ` Greg Kroah-Hartman
2019-07-27 16:07 ` Guenter Roeck
2019-07-28  6:22   ` Greg Kroah-Hartman
2019-07-29  9:03 ` Jon Hunter
2019-07-29 15:12   ` Greg Kroah-Hartman

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=20190726152307.847797843@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=acme@redhat.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=eranian@google.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=stable@vger.kernel.org \
    --cc=syzbot+a24c397a29ad22d86c98@syzkaller.appspotmail.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=vincent.weaver@maine.edu \
    /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;
as well as URLs for NNTP newsgroup(s).