--- /dev/null
+From foo@baz Thu Feb 11 03:21:16 PM CET 2021
+From: Lee Jones <lee.jones@linaro.org>
+Date: Thu, 11 Feb 2021 09:26:59 +0000
+Subject: futex: Change locking rules
+To: stable@vger.kernel.org
+Cc: zhengyejian@foxmail.com, Peter Zijlstra <peterz@infradead.org>, juri.lelli@arm.com, bigeasy@linutronix.de, xlpang@redhat.com, rostedt@goodmis.org, mathieu.desnoyers@efficios.com, jdesfossez@efficios.com, dvhart@infradead.org, bristot@redhat.com, Thomas Gleixner <tglx@linutronix.de>, Lee Jones <lee.jones@linaro.org>
+Message-ID: <20210211092700.11772-3-lee.jones@linaro.org>
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+Currently futex-pi relies on hb->lock to serialize everything. But hb->lock
+creates another set of problems, especially priority inversions on RT where
+hb->lock becomes a rt_mutex itself.
+
+The rt_mutex::wait_lock is the most obvious protection for keeping the
+futex user space value and the kernel internal pi_state in sync.
+
+Rework and document the locking so rt_mutex::wait_lock is held accross all
+operations which modify the user space value and the pi state.
+
+This allows to invoke rt_mutex_unlock() (including deboost) without holding
+hb->lock as a next step.
+
+Nothing yet relies on the new locking rules.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: juri.lelli@arm.com
+Cc: bigeasy@linutronix.de
+Cc: xlpang@redhat.com
+Cc: rostedt@goodmis.org
+Cc: mathieu.desnoyers@efficios.com
+Cc: jdesfossez@efficios.com
+Cc: dvhart@infradead.org
+Cc: bristot@redhat.com
+Link: http://lkml.kernel.org/r/20170322104151.751993333@infradead.org
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+[Lee: Back-ported in support of a previous futex back-port attempt]
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/futex.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 112 insertions(+), 26 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1019,6 +1019,39 @@ static void exit_pi_state_list(struct ta
+ * [10] There is no transient state which leaves owner and user space
+ * TID out of sync. Except one error case where the kernel is denied
+ * write access to the user address, see fixup_pi_state_owner().
++ *
++ *
++ * Serialization and lifetime rules:
++ *
++ * hb->lock:
++ *
++ * hb -> futex_q, relation
++ * futex_q -> pi_state, relation
++ *
++ * (cannot be raw because hb can contain arbitrary amount
++ * of futex_q's)
++ *
++ * pi_mutex->wait_lock:
++ *
++ * {uval, pi_state}
++ *
++ * (and pi_mutex 'obviously')
++ *
++ * p->pi_lock:
++ *
++ * p->pi_state_list -> pi_state->list, relation
++ *
++ * pi_state->refcount:
++ *
++ * pi_state lifetime
++ *
++ *
++ * Lock order:
++ *
++ * hb->lock
++ * pi_mutex->wait_lock
++ * p->pi_lock
++ *
+ */
+
+ /*
+@@ -1026,10 +1059,12 @@ static void exit_pi_state_list(struct ta
+ * the pi_state against the user space value. If correct, attach to
+ * it.
+ */
+-static int attach_to_pi_state(u32 uval, struct futex_pi_state *pi_state,
++static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
++ struct futex_pi_state *pi_state,
+ struct futex_pi_state **ps)
+ {
+ pid_t pid = uval & FUTEX_TID_MASK;
++ int ret, uval2;
+
+ /*
+ * Userspace might have messed up non-PI and PI futexes [3]
+@@ -1037,9 +1072,34 @@ static int attach_to_pi_state(u32 uval,
+ if (unlikely(!pi_state))
+ return -EINVAL;
+
++ /*
++ * We get here with hb->lock held, and having found a
++ * futex_top_waiter(). This means that futex_lock_pi() of said futex_q
++ * has dropped the hb->lock in between queue_me() and unqueue_me_pi(),
++ * which in turn means that futex_lock_pi() still has a reference on
++ * our pi_state.
++ */
+ WARN_ON(!atomic_read(&pi_state->refcount));
+
+ /*
++ * Now that we have a pi_state, we can acquire wait_lock
++ * and do the state validation.
++ */
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++
++ /*
++ * Since {uval, pi_state} is serialized by wait_lock, and our current
++ * uval was read without holding it, it can have changed. Verify it
++ * still is what we expect it to be, otherwise retry the entire
++ * operation.
++ */
++ if (get_futex_value_locked(&uval2, uaddr))
++ goto out_efault;
++
++ if (uval != uval2)
++ goto out_eagain;
++
++ /*
+ * Handle the owner died case:
+ */
+ if (uval & FUTEX_OWNER_DIED) {
+@@ -1054,11 +1114,11 @@ static int attach_to_pi_state(u32 uval,
+ * is not 0. Inconsistent state. [5]
+ */
+ if (pid)
+- return -EINVAL;
++ goto out_einval;
+ /*
+ * Take a ref on the state and return success. [4]
+ */
+- goto out_state;
++ goto out_attach;
+ }
+
+ /*
+@@ -1070,14 +1130,14 @@ static int attach_to_pi_state(u32 uval,
+ * Take a ref on the state and return success. [6]
+ */
+ if (!pid)
+- goto out_state;
++ goto out_attach;
+ } else {
+ /*
+ * If the owner died bit is not set, then the pi_state
+ * must have an owner. [7]
+ */
+ if (!pi_state->owner)
+- return -EINVAL;
++ goto out_einval;
+ }
+
+ /*
+@@ -1086,11 +1146,29 @@ static int attach_to_pi_state(u32 uval,
+ * user space TID. [9/10]
+ */
+ if (pid != task_pid_vnr(pi_state->owner))
+- return -EINVAL;
+-out_state:
++ goto out_einval;
++
++out_attach:
+ atomic_inc(&pi_state->refcount);
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+ *ps = pi_state;
+ return 0;
++
++out_einval:
++ ret = -EINVAL;
++ goto out_error;
++
++out_eagain:
++ ret = -EAGAIN;
++ goto out_error;
++
++out_efault:
++ ret = -EFAULT;
++ goto out_error;
++
++out_error:
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ return ret;
+ }
+
+ /**
+@@ -1183,6 +1261,9 @@ static int attach_to_pi_owner(u32 uval,
+
+ /*
+ * No existing pi state. First waiter. [2]
++ *
++ * This creates pi_state, we have hb->lock held, this means nothing can
++ * observe this state, wait_lock is irrelevant.
+ */
+ pi_state = alloc_pi_state();
+
+@@ -1207,7 +1288,8 @@ static int attach_to_pi_owner(u32 uval,
+ return 0;
+ }
+
+-static int lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
++static int lookup_pi_state(u32 __user *uaddr, u32 uval,
++ struct futex_hash_bucket *hb,
+ union futex_key *key, struct futex_pi_state **ps,
+ struct task_struct **exiting)
+ {
+@@ -1218,7 +1300,7 @@ static int lookup_pi_state(u32 uval, str
+ * attach to the pi_state when the validation succeeds.
+ */
+ if (match)
+- return attach_to_pi_state(uval, match->pi_state, ps);
++ return attach_to_pi_state(uaddr, uval, match->pi_state, ps);
+
+ /*
+ * We are the first waiter - try to look up the owner based on
+@@ -1237,7 +1319,7 @@ static int lock_pi_update_atomic(u32 __u
+ if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
+ return -EFAULT;
+
+- /*If user space value changed, let the caller retry */
++ /* If user space value changed, let the caller retry */
+ return curval != uval ? -EAGAIN : 0;
+ }
+
+@@ -1301,7 +1383,7 @@ static int futex_lock_pi_atomic(u32 __us
+ */
+ match = futex_top_waiter(hb, key);
+ if (match)
+- return attach_to_pi_state(uval, match->pi_state, ps);
++ return attach_to_pi_state(uaddr, uval, match->pi_state, ps);
+
+ /*
+ * No waiter and user TID is 0. We are here because the
+@@ -1441,6 +1523,7 @@ static int wake_futex_pi(u32 __user *uad
+
+ if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) {
+ ret = -EFAULT;
++
+ } else if (curval != uval) {
+ /*
+ * If a unconditional UNLOCK_PI operation (user space did not
+@@ -1977,7 +2060,7 @@ retry_private:
+ * If that call succeeds then we have pi_state and an
+ * initial refcount on it.
+ */
+- ret = lookup_pi_state(ret, hb2, &key2,
++ ret = lookup_pi_state(uaddr2, ret, hb2, &key2,
+ &pi_state, &exiting);
+ }
+
+@@ -2282,7 +2365,6 @@ static int __fixup_pi_state_owner(u32 __
+ int err = 0;
+
+ oldowner = pi_state->owner;
+-
+ /* Owner died? */
+ if (!pi_state->owner)
+ newtid |= FUTEX_OWNER_DIED;
+@@ -2305,11 +2387,10 @@ static int __fixup_pi_state_owner(u32 __
+ * because we can fault here. Imagine swapped out pages or a fork
+ * that marked all the anonymous memory readonly for cow.
+ *
+- * Modifying pi_state _before_ the user space value would
+- * leave the pi_state in an inconsistent state when we fault
+- * here, because we need to drop the hash bucket lock to
+- * handle the fault. This might be observed in the PID check
+- * in lookup_pi_state.
++ * Modifying pi_state _before_ the user space value would leave the
++ * pi_state in an inconsistent state when we fault here, because we
++ * need to drop the locks to handle the fault. This might be observed
++ * in the PID check in lookup_pi_state.
+ */
+ retry:
+ if (!argowner) {
+@@ -2367,21 +2448,26 @@ retry:
+ return argowner == current;
+
+ /*
+- * To handle the page fault we need to drop the hash bucket
+- * lock here. That gives the other task (either the highest priority
+- * waiter itself or the task which stole the rtmutex) the
+- * chance to try the fixup of the pi_state. So once we are
+- * back from handling the fault we need to check the pi_state
+- * after reacquiring the hash bucket lock and before trying to
+- * do another fixup. When the fixup has been done already we
+- * simply return.
++ * To handle the page fault we need to drop the locks here. That gives
++ * the other task (either the highest priority waiter itself or the
++ * task which stole the rtmutex) the chance to try the fixup of the
++ * pi_state. So once we are back from handling the fault we need to
++ * check the pi_state after reacquiring the locks and before trying to
++ * do another fixup. When the fixup has been done already we simply
++ * return.
++ *
++ * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely
++ * drop hb->lock since the caller owns the hb -> futex_q relation.
++ * Dropping the pi_mutex->wait_lock requires the state revalidate.
+ */
+ handle_fault:
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+ spin_unlock(q->lock_ptr);
+
+ err = fault_in_user_writeable(uaddr);
+
+ spin_lock(q->lock_ptr);
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+
+ /*
+ * Check if someone else fixed it for us:
--- /dev/null
+From foo@baz Thu Feb 11 03:21:16 PM CET 2021
+From: Lee Jones <lee.jones@linaro.org>
+Date: Thu, 11 Feb 2021 09:27:00 +0000
+Subject: futex: Cure exit race
+To: stable@vger.kernel.org
+Cc: zhengyejian@foxmail.com, Thomas Gleixner <tglx@linutronix.de>, Stefan Liebler <stli@linux.ibm.com>, Peter Zijlstra <peterz@infradead.org>, Heiko Carstens <heiko.carstens@de.ibm.com>, Darren Hart <dvhart@infradead.org>, Ingo Molnar <mingo@kernel.org>, Sasha Levin <sashal@kernel.org>, Sudip Mukherjee <sudipm.mukherjee@gmail.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Lee Jones <lee.jones@linaro.org>
+Message-ID: <20210211092700.11772-4-lee.jones@linaro.org>
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit da791a667536bf8322042e38ca85d55a78d3c273 upstream.
+
+Stefan reported, that the glibc tst-robustpi4 test case fails
+occasionally. That case creates the following race between
+sys_exit() and sys_futex_lock_pi():
+
+ CPU0 CPU1
+
+ sys_exit() sys_futex()
+ do_exit() futex_lock_pi()
+ exit_signals(tsk) No waiters:
+ tsk->flags |= PF_EXITING; *uaddr == 0x00000PID
+ mm_release(tsk) Set waiter bit
+ exit_robust_list(tsk) { *uaddr = 0x80000PID;
+ Set owner died attach_to_pi_owner() {
+ *uaddr = 0xC0000000; tsk = get_task(PID);
+ } if (!tsk->flags & PF_EXITING) {
+ ... attach();
+ tsk->flags |= PF_EXITPIDONE; } else {
+ if (!(tsk->flags & PF_EXITPIDONE))
+ return -EAGAIN;
+ return -ESRCH; <--- FAIL
+ }
+
+ESRCH is returned all the way to user space, which triggers the glibc test
+case assert. Returning ESRCH unconditionally is wrong here because the user
+space value has been changed by the exiting task to 0xC0000000, i.e. the
+FUTEX_OWNER_DIED bit is set and the futex PID value has been cleared. This
+is a valid state and the kernel has to handle it, i.e. taking the futex.
+
+Cure it by rereading the user space value when PF_EXITING and PF_EXITPIDONE
+is set in the task which 'owns' the futex. If the value has changed, let
+the kernel retry the operation, which includes all regular sanity checks
+and correctly handles the FUTEX_OWNER_DIED case.
+
+If it hasn't changed, then return ESRCH as there is no way to distinguish
+this case from malfunctioning user space. This happens when the exiting
+task did not have a robust list, the robust list was corrupted or the user
+space value in the futex was simply bogus.
+
+Reported-by: Stefan Liebler <stli@linux.ibm.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
+Cc: Darren Hart <dvhart@infradead.org>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Sasha Levin <sashal@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=200467
+Link: https://lkml.kernel.org/r/20181210152311.986181245@linutronix.de
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[Lee: Required to satisfy functional dependency from futex back-port.
+ Re-add the missing handle_exit_race() parts from:
+ 3d4775df0a89 ("futex: Replace PF_EXITPIDONE with a state")]
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/futex.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 65 insertions(+), 6 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1201,11 +1201,67 @@ static void wait_for_owner_exiting(int r
+ put_task_struct(exiting);
+ }
+
++static int handle_exit_race(u32 __user *uaddr, u32 uval,
++ struct task_struct *tsk)
++{
++ u32 uval2;
++
++ /*
++ * If the futex exit state is not yet FUTEX_STATE_DEAD, wait
++ * for it to finish.
++ */
++ if (tsk && tsk->futex_state != FUTEX_STATE_DEAD)
++ return -EAGAIN;
++
++ /*
++ * Reread the user space value to handle the following situation:
++ *
++ * CPU0 CPU1
++ *
++ * sys_exit() sys_futex()
++ * do_exit() futex_lock_pi()
++ * futex_lock_pi_atomic()
++ * exit_signals(tsk) No waiters:
++ * tsk->flags |= PF_EXITING; *uaddr == 0x00000PID
++ * mm_release(tsk) Set waiter bit
++ * exit_robust_list(tsk) { *uaddr = 0x80000PID;
++ * Set owner died attach_to_pi_owner() {
++ * *uaddr = 0xC0000000; tsk = get_task(PID);
++ * } if (!tsk->flags & PF_EXITING) {
++ * ... attach();
++ * tsk->futex_state = } else {
++ * FUTEX_STATE_DEAD; if (tsk->futex_state !=
++ * FUTEX_STATE_DEAD)
++ * return -EAGAIN;
++ * return -ESRCH; <--- FAIL
++ * }
++ *
++ * Returning ESRCH unconditionally is wrong here because the
++ * user space value has been changed by the exiting task.
++ *
++ * The same logic applies to the case where the exiting task is
++ * already gone.
++ */
++ if (get_futex_value_locked(&uval2, uaddr))
++ return -EFAULT;
++
++ /* If the user space value has changed, try again. */
++ if (uval2 != uval)
++ return -EAGAIN;
++
++ /*
++ * The exiting task did not have a robust list, the robust list was
++ * corrupted or the user space value in *uaddr is simply bogus.
++ * Give up and tell user space.
++ */
++ return -ESRCH;
++}
++
+ /*
+ * Lookup the task for the TID provided from user space and attach to
+ * it after doing proper sanity checks.
+ */
+-static int attach_to_pi_owner(u32 uval, union futex_key *key,
++static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
+ struct futex_pi_state **ps,
+ struct task_struct **exiting)
+ {
+@@ -1216,12 +1272,15 @@ static int attach_to_pi_owner(u32 uval,
+ /*
+ * We are the first waiter - try to look up the real owner and attach
+ * the new pi_state to it, but bail out when TID = 0 [1]
++ *
++ * The !pid check is paranoid. None of the call sites should end up
++ * with pid == 0, but better safe than sorry. Let the caller retry
+ */
+ if (!pid)
+- return -ESRCH;
++ return -EAGAIN;
+ p = futex_find_get_task(pid);
+ if (!p)
+- return -ESRCH;
++ return handle_exit_race(uaddr, uval, NULL);
+
+ if (unlikely(p->flags & PF_KTHREAD)) {
+ put_task_struct(p);
+@@ -1240,7 +1299,7 @@ static int attach_to_pi_owner(u32 uval,
+ * FUTEX_STATE_DEAD, we know that the task has finished
+ * the cleanup:
+ */
+- int ret = (p->futex_state = FUTEX_STATE_DEAD) ? -ESRCH : -EAGAIN;
++ int ret = handle_exit_race(uaddr, uval, p);
+
+ raw_spin_unlock_irq(&p->pi_lock);
+ /*
+@@ -1306,7 +1365,7 @@ static int lookup_pi_state(u32 __user *u
+ * We are the first waiter - try to look up the owner based on
+ * @uval and attach to it.
+ */
+- return attach_to_pi_owner(uval, key, ps, exiting);
++ return attach_to_pi_owner(uaddr, uval, key, ps, exiting);
+ }
+
+ static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
+@@ -1422,7 +1481,7 @@ static int futex_lock_pi_atomic(u32 __us
+ * attach to the owner. If that fails, no harm done, we only
+ * set the FUTEX_WAITERS bit in the user space variable.
+ */
+- return attach_to_pi_owner(uval, key, ps, exiting);
++ return attach_to_pi_owner(uaddr, newval, key, ps, exiting);
+ }
+
+ /**
--- /dev/null
+From foo@baz Thu Feb 11 03:21:16 PM CET 2021
+From: Lee Jones <lee.jones@linaro.org>
+Date: Thu, 11 Feb 2021 09:26:58 +0000
+Subject: futex: Ensure the correct return value from futex_lock_pi()
+To: stable@vger.kernel.org
+Cc: zhengyejian@foxmail.com, Thomas Gleixner <tglx@linutronix.de>, Peter Zijlstra <peterz@infradead.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Lee Jones <lee.jones@linaro.org>
+Message-ID: <20210211092700.11772-2-lee.jones@linaro.org>
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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>
+[Lee: Back-ported in support of a previous futex attempt]
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/futex.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -2322,7 +2322,7 @@ retry:
+ }
+
+ if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
+- /* We got the lock after all, nothing to fix. */
++ /* We got the lock. pi_state is correct. Tell caller. */
+ return 1;
+ }
+
+@@ -2364,7 +2364,7 @@ retry:
+ */
+ pi_state_update_owner(pi_state, newowner);
+
+- return 0;
++ return argowner == current;
+
+ /*
+ * To handle the page fault we need to drop the hash bucket
+@@ -2447,8 +2447,6 @@ static long futex_wait_restart(struct re
+ */
+ 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
+@@ -2459,8 +2457,8 @@ static int fixup_owner(u32 __user *uaddr
+ * 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;
+ }
+
+ /*
+@@ -2471,10 +2469,8 @@ static int fixup_owner(u32 __user *uaddr
+ * 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
+@@ -2483,8 +2479,7 @@ static int fixup_owner(u32 __user *uaddr
+ if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current))
+ return fixup_pi_state_owner(uaddr, q, current);
+
+-out:
+- return ret ? ret : locked;
++ return 0;
+ }
+
+ /**
+@@ -3106,6 +3101,11 @@ static int futex_wait_requeue_pi(u32 __u
+ */
+ 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;
lib-string-add-strscpy_pad-function.patch
include-trace-events-writeback.h-fix-wstringop-trunc.patch
memcg-fix-a-crash-in-wb_workfn-when-a-device-disappe.patch
+futex-ensure-the-correct-return-value-from-futex_lock_pi.patch
+futex-change-locking-rules.patch
+futex-cure-exit-race.patch