]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Tue, 6 Dec 2022 11:44:07 +0000 (06:44 -0500)
committerSasha Levin <sashal@kernel.org>
Tue, 6 Dec 2022 11:44:07 +0000 (06:44 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch b/queue-4.14/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch
new file mode 100644 (file)
index 0000000..0b6cdce
--- /dev/null
@@ -0,0 +1,75 @@
+From 94604de3a297eb3137d3fbc8e0b4b87aee7b7f1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Dec 2022 17:59:27 +0100
+Subject: ipc/sem: Fix dangling sem_array access in semtimedop race
+
+From: Jann Horn <jannh@google.com>
+
+[ Upstream commit b52be557e24c47286738276121177a41f54e3b83 ]
+
+When __do_semtimedop() goes to sleep because it has to wait for a
+semaphore value becoming zero or becoming bigger than some threshold, it
+links the on-stack sem_queue to the sem_array, then goes to sleep
+without holding a reference on the sem_array.
+
+When __do_semtimedop() comes back out of sleep, one of two things must
+happen:
+
+ a) We prove that the on-stack sem_queue has been disconnected from the
+    (possibly freed) sem_array, making it safe to return from the stack
+    frame that the sem_queue exists in.
+
+ b) We stabilize our reference to the sem_array, lock the sem_array, and
+    detach the sem_queue from the sem_array ourselves.
+
+sem_array has RCU lifetime, so for case (b), the reference can be
+stabilized inside an RCU read-side critical section by locklessly
+checking whether the sem_queue is still connected to the sem_array.
+
+However, the current code does the lockless check on sem_queue before
+starting an RCU read-side critical section, so the result of the
+lockless check immediately becomes useless.
+
+Fix it by doing rcu_read_lock() before the lockless check.  Now RCU
+ensures that if we observe the object being on our queue, the object
+can't be freed until rcu_read_unlock().
+
+This bug is only hittable on kernel builds with full preemption support
+(either CONFIG_PREEMPT or PREEMPT_DYNAMIC with preempt=full).
+
+Fixes: 370b262c896e ("ipc/sem: avoid idr tree lookup for interrupted semop")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ ipc/sem.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ipc/sem.c b/ipc/sem.c
+index 6adc245f3e02..89fef4550b38 100644
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -2064,6 +2064,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
+                * scenarios where we were awakened externally, during the
+                * window between wake_q_add() and wake_up_q().
+                */
++              rcu_read_lock();
+               error = READ_ONCE(queue.status);
+               if (error != -EINTR) {
+                       /*
+@@ -2073,10 +2074,10 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
+                        * overwritten by the previous owner of the semaphore.
+                        */
+                       smp_mb();
++                      rcu_read_unlock();
+                       goto out_free;
+               }
+-              rcu_read_lock();
+               locknum = sem_lock(sma, sops, nsops);
+               if (!ipc_valid_object(&sma->sem_perm))
+-- 
+2.35.1
+
index e59a31eebc9aef4a97bb76b874becf0103a4760d..5f20d382bb4109eda2943b2b8911ad62a4de09a2 100644 (file)
@@ -78,3 +78,4 @@ mmc-sdhci-fix-voltage-switch-delay.patch
 proc-avoid-integer-type-confusion-in-get_proc_long.patch
 proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch
 v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch
+ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch