From 49a8f8f74eff5320b25ca47ac4bace6a0527cacc Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 6 Dec 2022 06:44:05 -0500 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...ling-sem_array-access-in-semtimedop-.patch | 72 +++++++++++++++++++ queue-5.10/series | 1 + 2 files changed, 73 insertions(+) create mode 100644 queue-5.10/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch diff --git a/queue-5.10/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch b/queue-5.10/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch new file mode 100644 index 00000000000..5379aad657d --- /dev/null +++ b/queue-5.10/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-.patch @@ -0,0 +1,72 @@ +From 6583a41428b75414c9fb510fb3acd1c61a93f1e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 17:59:27 +0100 +Subject: ipc/sem: Fix dangling sem_array access in semtimedop race + +From: Jann Horn + +[ 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 +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + ipc/sem.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ipc/sem.c b/ipc/sem.c +index 2cb6515ef1dd..916f7a90be31 100644 +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -2190,14 +2190,15 @@ 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) { + /* see SEM_BARRIER_2 for purpose/pairing */ + smp_acquire__after_ctrl_dep(); ++ 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 + diff --git a/queue-5.10/series b/queue-5.10/series index 5354c18058c..80324a2b8a0 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -93,3 +93,4 @@ block-unhash-blkdev-part-inode-when-the-part-is-deleted.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 -- 2.47.3