summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch138
1 files changed, 138 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch
new file mode 100644
index 000000000..24f1986a8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch
@@ -0,0 +1,138 @@
+From 0dae88a92596db9405fd4a341c1915cf7d8fbad4 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 20 Jan 2021 16:00:24 +0100
+Subject: [PATCH] futex: Ensure the correct return value from futex_lock_pi()
+
+commit 12bb3f7f1b03d5913b3f9d4236a488aa7774dfe9 upstream
+
+In case that futex_lock_pi() was aborted by a signal or a timeout and the
+task returned without acquiring the rtmutex, but is the designated owner of
+the futex due to a concurrent futex_unlock_pi() fixup_owner() is invoked to
+establish consistent state. In that case it invokes fixup_pi_state_owner()
+which in turn tries to acquire the rtmutex again. If that succeeds then it
+does not propagate this success to fixup_owner() and futex_lock_pi()
+returns -EINTR or -ETIMEOUT despite having the futex locked.
+
+Return success from fixup_pi_state_owner() in all cases where the current
+task owns the rtmutex and therefore the futex and propagate it correctly
+through fixup_owner(). Fixup the other callsite which does not expect a
+positive return value.
+
+Fixes: c1e2f0eaf015 ("futex: Avoid violating the 10th rule of futex")
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/futex.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/kernel/futex.c b/kernel/futex.c
+index b6dec5f79370..d2cc406c6658 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -2506,8 +2506,8 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+ }
+
+ if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
+- /* We got the lock after all, nothing to fix. */
+- ret = 0;
++ /* We got the lock. pi_state is correct. Tell caller. */
++ ret = 1;
+ goto out_unlock;
+ }
+
+@@ -2535,7 +2535,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+ * We raced against a concurrent self; things are
+ * already fixed up. Nothing to do.
+ */
+- ret = 0;
++ ret = 1;
+ goto out_unlock;
+ }
+ newowner = argowner;
+@@ -2581,7 +2581,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+ raw_spin_unlock(&newowner->pi_lock);
+ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+
+- return 0;
++ return argowner == current;
+
+ /*
+ * In order to reschedule or handle a page fault, we need to drop the
+@@ -2623,7 +2623,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+ * Check if someone else fixed it for us:
+ */
+ if (pi_state->owner != oldowner) {
+- ret = 0;
++ ret = argowner == current;
+ goto out_unlock;
+ }
+
+@@ -2656,8 +2656,6 @@ static long futex_wait_restart(struct restart_block *restart);
+ */
+ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
+ {
+- int ret = 0;
+-
+ if (locked) {
+ /*
+ * Got the lock. We might not be the anticipated owner if we
+@@ -2668,8 +2666,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
+ * stable state, anything else needs more attention.
+ */
+ if (q->pi_state->owner != current)
+- ret = fixup_pi_state_owner(uaddr, q, current);
+- goto out;
++ return fixup_pi_state_owner(uaddr, q, current);
++ return 1;
+ }
+
+ /*
+@@ -2680,10 +2678,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
+ * Another speculative read; pi_state->owner == current is unstable
+ * but needs our attention.
+ */
+- if (q->pi_state->owner == current) {
+- ret = fixup_pi_state_owner(uaddr, q, NULL);
+- goto out;
+- }
++ if (q->pi_state->owner == current)
++ return fixup_pi_state_owner(uaddr, q, NULL);
+
+ /*
+ * Paranoia check. If we did not take the lock, then we should not be
+@@ -2696,8 +2692,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
+ q->pi_state->owner);
+ }
+
+-out:
+- return ret ? ret : locked;
++ return 0;
+ }
+
+ /**
+@@ -3406,7 +3401,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
+ if (q.pi_state && (q.pi_state->owner != current)) {
+ spin_lock(q.lock_ptr);
+ ret = fixup_pi_state_owner(uaddr2, &q, current);
+- if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
++ if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
+ pi_state = q.pi_state;
+ get_pi_state(pi_state);
+ }
+@@ -3416,6 +3411,11 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
+ */
+ put_pi_state(q.pi_state);
+ spin_unlock(q.lock_ptr);
++ /*
++ * Adjust the return value. It's either -EFAULT or
++ * success (1) but the caller expects 0 for success.
++ */
++ ret = ret < 0 ? ret : 0;
+ }
+ } else {
+ struct rt_mutex *pi_mutex;
+--
+2.17.1
+