Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
06e2ade846 | ||
|
5298957d9b | ||
|
8c776ecf64 | ||
|
a6877bd422 |
@@ -14,7 +14,7 @@ of Proton to still use fsync in new kernel releases.
|
|||||||
Signed-off-by: André Almeida <andrealmeid@collabora.com>
|
Signed-off-by: André Almeida <andrealmeid@collabora.com>
|
||||||
---
|
---
|
||||||
include/uapi/linux/futex.h | 12 ++++++
|
include/uapi/linux/futex.h | 12 ++++++
|
||||||
kernel/futex.c | 75 +++++++++++++++++++++++++++++++++++++-
|
kernel/futex/core.c | 75 +++++++++++++++++++++++++++++++++++++-
|
||||||
2 files changed, 86 insertions(+), 1 deletion(-)
|
2 files changed, 86 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
|
diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
|
||||||
@@ -47,10 +47,10 @@ index 2a06b99f9803..417c5d89b745 100644
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for robust futexes: the kernel cleans up held futexes at
|
* Support for robust futexes: the kernel cleans up held futexes at
|
||||||
diff --git a/kernel/futex.c b/kernel/futex.c
|
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
|
||||||
index 4a9e7ce3714a..c3f2e65afab8 100644
|
index 4a9e7ce3714a..c3f2e65afab8 100644
|
||||||
--- a/kernel/futex.c
|
--- a/kernel/futex/core.c
|
||||||
+++ b/kernel/futex.c
|
+++ b/kernel/futex/core.c
|
||||||
@@ -4012,6 +4012,7 @@ static __always_inline bool futex_cmd_has_timeout(u32 cmd)
|
@@ -4012,6 +4012,7 @@ static __always_inline bool futex_cmd_has_timeout(u32 cmd)
|
||||||
case FUTEX_LOCK_PI2:
|
case FUTEX_LOCK_PI2:
|
||||||
case FUTEX_WAIT_BITSET:
|
case FUTEX_WAIT_BITSET:
|
||||||
|
@@ -43,7 +43,7 @@ Link: https://lore.kernel.org/r/20210923171111.300673-17-andrealmeid@collabora.c
|
|||||||
include/linux/syscalls.h | 6 +
|
include/linux/syscalls.h | 6 +
|
||||||
include/uapi/asm-generic/unistd.h | 5 +-
|
include/uapi/asm-generic/unistd.h | 5 +-
|
||||||
include/uapi/linux/futex.h | 26 +++
|
include/uapi/linux/futex.h | 26 +++
|
||||||
kernel/futex.c | 334 ++++++++++++++++++++++++++++++
|
kernel/futex/core.c | 334 ++++++++++++++++++++++++++++++
|
||||||
kernel/sys_ni.c | 1 +
|
kernel/sys_ni.c | 1 +
|
||||||
5 files changed, 371 insertions(+), 1 deletion(-)
|
5 files changed, 371 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
@@ -125,10 +125,10 @@ index a89eb0accd5e..1666f5e4b837 100644
|
|||||||
/*
|
/*
|
||||||
* Support for robust futexes: the kernel cleans up held futexes at
|
* Support for robust futexes: the kernel cleans up held futexes at
|
||||||
* thread exit time.
|
* thread exit time.
|
||||||
diff --git a/kernel/futex.c b/kernel/futex.c
|
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
|
||||||
index 408cad5e8968..d7dc0bd9379c 100644
|
index 408cad5e8968..d7dc0bd9379c 100644
|
||||||
--- a/kernel/futex.c
|
--- a/kernel/futex/core.c
|
||||||
+++ b/kernel/futex.c
|
+++ b/kernel/futex/core.c
|
||||||
@@ -285,6 +285,18 @@ static const struct futex_q futex_q_init = {
|
@@ -285,6 +285,18 @@ static const struct futex_q futex_q_init = {
|
||||||
.requeue_state = ATOMIC_INIT(Q_REQUEUE_PI_NONE),
|
.requeue_state = ATOMIC_INIT(Q_REQUEUE_PI_NONE),
|
||||||
};
|
};
|
||||||
|
@@ -314,99 +314,3 @@ index 8c6517d29b8e0c..37068542aafe7f 100644
|
|||||||
mutex_unlock(&ggtt->vm.mutex);
|
mutex_unlock(&ggtt->vm.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
From 189603b802a2bb276b82a0a4f66528ad29156f46 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alexey Izbyshev <izbyshev@ispras.ru>
|
|
||||||
Date: Sat, 12 Nov 2022 00:54:39 +0300
|
|
||||||
Subject: [PATCH] futex: Resend potentially swallowed owner death notification
|
|
||||||
|
|
||||||
Commit ca16d5bee598 ("futex: Prevent robust futex exit race") addressed
|
|
||||||
two cases when tasks waiting on a robust non-PI futex remained blocked
|
|
||||||
despite the futex not being owned anymore:
|
|
||||||
|
|
||||||
* if the owner died after writing zero to the futex word, but before
|
|
||||||
waking up a waiter
|
|
||||||
|
|
||||||
* if a task waiting on the futex was woken up, but died before updating
|
|
||||||
the futex word (effectively swallowing the notification without acting
|
|
||||||
on it)
|
|
||||||
|
|
||||||
In the second case, the task could be woken up either by the previous
|
|
||||||
owner (after the futex word was reset to zero) or by the kernel (after
|
|
||||||
the OWNER_DIED bit was set and the TID part of the futex word was reset
|
|
||||||
to zero) if the previous owner died without the resetting the futex.
|
|
||||||
|
|
||||||
Because the referenced commit wakes up a potential waiter only if the
|
|
||||||
whole futex word is zero, the latter subcase remains unaddressed.
|
|
||||||
|
|
||||||
Fix this by looking only at the TID part of the futex when deciding
|
|
||||||
whether a wake up is needed.
|
|
||||||
|
|
||||||
Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race")
|
|
||||||
Signed-off-by: Alexey Izbyshev <izbyshev@ispras.ru>
|
|
||||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
||||||
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
|
||||||
Link: https://lore.kernel.org/r/20221111215439.248185-1-izbyshev@ispras.ru
|
|
||||||
---
|
|
||||||
kernel/futex/core.c | 26 +++++++++++++++++---------
|
|
||||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
|
|
||||||
index b22ef1efe75118..514e4582b86341 100644
|
|
||||||
--- a/kernel/futex/core.c
|
|
||||||
+++ b/kernel/futex/core.c
|
|
||||||
@@ -638,6 +638,7 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
|
|
||||||
bool pi, bool pending_op)
|
|
||||||
{
|
|
||||||
u32 uval, nval, mval;
|
|
||||||
+ pid_t owner;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Futex address must be 32bit aligned */
|
|
||||||
@@ -659,6 +660,10 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
|
|
||||||
* 2. A woken up waiter is killed before it can acquire the
|
|
||||||
* futex in user space.
|
|
||||||
*
|
|
||||||
+ * In the second case, the wake up notification could be generated
|
|
||||||
+ * by the unlock path in user space after setting the futex value
|
|
||||||
+ * to zero or by the kernel after setting the OWNER_DIED bit below.
|
|
||||||
+ *
|
|
||||||
* In both cases the TID validation below prevents a wakeup of
|
|
||||||
* potential waiters which can cause these waiters to block
|
|
||||||
* forever.
|
|
||||||
@@ -667,24 +672,27 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
|
|
||||||
*
|
|
||||||
* 1) task->robust_list->list_op_pending != NULL
|
|
||||||
* @pending_op == true
|
|
||||||
- * 2) User space futex value == 0
|
|
||||||
+ * 2) The owner part of user space futex value == 0
|
|
||||||
* 3) Regular futex: @pi == false
|
|
||||||
*
|
|
||||||
* If these conditions are met, it is safe to attempt waking up a
|
|
||||||
* potential waiter without touching the user space futex value and
|
|
||||||
- * trying to set the OWNER_DIED bit. The user space futex value is
|
|
||||||
- * uncontended and the rest of the user space mutex state is
|
|
||||||
- * consistent, so a woken waiter will just take over the
|
|
||||||
- * uncontended futex. Setting the OWNER_DIED bit would create
|
|
||||||
- * inconsistent state and malfunction of the user space owner died
|
|
||||||
- * handling.
|
|
||||||
+ * trying to set the OWNER_DIED bit. If the futex value is zero,
|
|
||||||
+ * the rest of the user space mutex state is consistent, so a woken
|
|
||||||
+ * waiter will just take over the uncontended futex. Setting the
|
|
||||||
+ * OWNER_DIED bit would create inconsistent state and malfunction
|
|
||||||
+ * of the user space owner died handling. Otherwise, the OWNER_DIED
|
|
||||||
+ * bit is already set, and the woken waiter is expected to deal with
|
|
||||||
+ * this.
|
|
||||||
*/
|
|
||||||
- if (pending_op && !pi && !uval) {
|
|
||||||
+ owner = uval & FUTEX_TID_MASK;
|
|
||||||
+
|
|
||||||
+ if (pending_op && !pi && !owner) {
|
|
||||||
futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
|
|
||||||
+ if (owner != task_pid_vnr(curr))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
Reference in New Issue
Block a user