]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Nov 2017 07:49:19 +0000 (08:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Nov 2017 07:49:19 +0000 (08:49 +0100)
added patches:
futex-fix-more-put_pi_state-vs.-exit_pi_state_list-races.patch
perf-cgroup-fix-perf-cgroup-hierarchy-support.patch

queue-4.13/futex-fix-more-put_pi_state-vs.-exit_pi_state_list-races.patch [new file with mode: 0644]
queue-4.13/perf-cgroup-fix-perf-cgroup-hierarchy-support.patch [new file with mode: 0644]
queue-4.13/series

diff --git a/queue-4.13/futex-fix-more-put_pi_state-vs.-exit_pi_state_list-races.patch b/queue-4.13/futex-fix-more-put_pi_state-vs.-exit_pi_state_list-races.patch
new file mode 100644 (file)
index 0000000..a942229
--- /dev/null
@@ -0,0 +1,111 @@
+From 153fbd1226fb30b8630802aa5047b8af5ef53c9f Mon Sep 17 00:00:00 2001
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Tue, 31 Oct 2017 11:18:53 +0100
+Subject: futex: Fix more put_pi_state() vs. exit_pi_state_list() races
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+commit 153fbd1226fb30b8630802aa5047b8af5ef53c9f upstream.
+
+Dmitry (through syzbot) reported being able to trigger the WARN in
+get_pi_state() and a use-after-free on:
+
+       raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+
+Both are due to this race:
+
+  exit_pi_state_list()                         put_pi_state()
+
+  lock(&curr->pi_lock)
+  while() {
+       pi_state = list_first_entry(head);
+       hb = hash_futex(&pi_state->key);
+       unlock(&curr->pi_lock);
+
+                                               dec_and_test(&pi_state->refcount);
+
+       lock(&hb->lock)
+       lock(&pi_state->pi_mutex.wait_lock)     // uaf if pi_state free'd
+       lock(&curr->pi_lock);
+
+       ....
+
+       unlock(&curr->pi_lock);
+       get_pi_state();                         // WARN; refcount==0
+
+The problem is we take the reference count too late, and don't allow it
+being 0. Fix it by using inc_not_zero() and simply retrying the loop
+when we fail to get a refcount. In that case put_pi_state() should
+remove the entry from the list.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Gratian Crisan <gratian.crisan@ni.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: dvhart@infradead.org
+Cc: syzbot <bot+2af19c9e1ffe4d4ee1d16c56ae7580feaee75765@syzkaller.appspotmail.com>
+Cc: syzkaller-bugs@googlegroups.com
+Fixes: c74aef2d06a9 ("futex: Fix pi_state->owner serialization")
+Link: http://lkml.kernel.org/r/20171031101853.xpfh72y643kdfhjs@hirez.programming.kicks-ass.net
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c |   23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -901,11 +901,27 @@ void exit_pi_state_list(struct task_stru
+        */
+       raw_spin_lock_irq(&curr->pi_lock);
+       while (!list_empty(head)) {
+-
+               next = head->next;
+               pi_state = list_entry(next, struct futex_pi_state, list);
+               key = pi_state->key;
+               hb = hash_futex(&key);
++
++              /*
++               * We can race against put_pi_state() removing itself from the
++               * list (a waiter going away). put_pi_state() will first
++               * decrement the reference count and then modify the list, so
++               * its possible to see the list entry but fail this reference
++               * acquire.
++               *
++               * In that case; drop the locks to let put_pi_state() make
++               * progress and retry the loop.
++               */
++              if (!atomic_inc_not_zero(&pi_state->refcount)) {
++                      raw_spin_unlock_irq(&curr->pi_lock);
++                      cpu_relax();
++                      raw_spin_lock_irq(&curr->pi_lock);
++                      continue;
++              }
+               raw_spin_unlock_irq(&curr->pi_lock);
+               spin_lock(&hb->lock);
+@@ -916,8 +932,10 @@ void exit_pi_state_list(struct task_stru
+                * task still owns the PI-state:
+                */
+               if (head->next != next) {
++                      /* retain curr->pi_lock for the loop invariant */
+                       raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+                       spin_unlock(&hb->lock);
++                      put_pi_state(pi_state);
+                       continue;
+               }
+@@ -925,9 +943,8 @@ void exit_pi_state_list(struct task_stru
+               WARN_ON(list_empty(&pi_state->list));
+               list_del_init(&pi_state->list);
+               pi_state->owner = NULL;
+-              raw_spin_unlock(&curr->pi_lock);
+-              get_pi_state(pi_state);
++              raw_spin_unlock(&curr->pi_lock);
+               raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+               spin_unlock(&hb->lock);
diff --git a/queue-4.13/perf-cgroup-fix-perf-cgroup-hierarchy-support.patch b/queue-4.13/perf-cgroup-fix-perf-cgroup-hierarchy-support.patch
new file mode 100644 (file)
index 0000000..7d9eda3
--- /dev/null
@@ -0,0 +1,53 @@
+From be96b316deff35e119760982c43af74e606fa143 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Sat, 28 Oct 2017 09:49:37 -0700
+Subject: perf/cgroup: Fix perf cgroup hierarchy support
+
+From: Tejun Heo <tj@kernel.org>
+
+commit be96b316deff35e119760982c43af74e606fa143 upstream.
+
+The following commit:
+
+  864c2357ca89 ("perf/core: Do not set cpuctx->cgrp for unscheduled cgroups")
+
+made list_update_cgroup_event() skip setting cpuctx->cgrp if no cgroup event
+targets %current's cgroup.
+
+This breaks perf_event's hierarchical support because events which target one
+of the ancestors get ignored.
+
+Fix it by using cgroup_is_descendant() test instead of equality.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
+Cc: David Carrillo-Cisneros <davidcc@google.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: kernel-team@fb.com
+Fixes: 864c2357ca89 ("perf/core: Do not set cpuctx->cgrp for unscheduled cgroups")
+Link: http://lkml.kernel.org/r/20171028164237.GA972780@devbig577.frc2.facebook.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/events/core.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -901,9 +901,11 @@ list_update_cgroup_event(struct perf_eve
+       cpuctx_entry = &cpuctx->cgrp_cpuctx_entry;
+       /* cpuctx->cgrp is NULL unless a cgroup event is active in this CPU .*/
+       if (add) {
++              struct perf_cgroup *cgrp = perf_cgroup_from_task(current, ctx);
++
+               list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list));
+-              if (perf_cgroup_from_task(current, ctx) == event->cgrp)
+-                      cpuctx->cgrp = event->cgrp;
++              if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup))
++                      cpuctx->cgrp = cgrp;
+       } else {
+               list_del(cpuctx_entry);
+               cpuctx->cgrp = NULL;
index e9cb8d994992e7fe683129d784a93b8f0afb724b..0936d04b1d1325cad0352b6b2681697929389b7d 100644 (file)
@@ -30,3 +30,5 @@ mips-smp-fix-deadlock-online-race.patch
 revert-x86-do-not-use-cpufreq_quick_get-for-proc-cpuinfo-cpu-mhz.patch
 x86-cpu-fix-up-cpu-mhz-in-proc-cpuinfo.patch
 powerpc-kprobes-dereference-function-pointers-only-if-the-address-does-not-belong-to-kernel-text.patch
+futex-fix-more-put_pi_state-vs.-exit_pi_state_list-races.patch
+perf-cgroup-fix-perf-cgroup-hierarchy-support.patch