]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Dec 2022 11:37:05 +0000 (12:37 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Dec 2022 11:37:05 +0000 (12:37 +0100)
added patches:
ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.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

queue-5.15/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch [new file with mode: 0644]
queue-5.15/proc-avoid-integer-type-confusion-in-get_proc_long.patch [new file with mode: 0644]
queue-5.15/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch b/queue-5.15/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch
new file mode 100644 (file)
index 0000000..306aa49
--- /dev/null
@@ -0,0 +1,67 @@
+From b52be557e24c47286738276121177a41f54e3b83 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+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>
+
+commit b52be557e24c47286738276121177a41f54e3b83 upstream.
+
+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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/sem.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -2182,14 +2182,15 @@ long __do_semtimedop(int semid, struct s
+                * 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;
+               }
+-              rcu_read_lock();
+               locknum = sem_lock(sma, sops, nsops);
+               if (!ipc_valid_object(&sma->sem_perm))
diff --git a/queue-5.15/proc-avoid-integer-type-confusion-in-get_proc_long.patch b/queue-5.15/proc-avoid-integer-type-confusion-in-get_proc_long.patch
new file mode 100644 (file)
index 0000000..02045b6
--- /dev/null
@@ -0,0 +1,40 @@
+From e6cfaf34be9fcd1a8285a294e18986bfc41a409c Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Mon, 5 Dec 2022 11:33:40 -0800
+Subject: proc: avoid integer type confusion in get_proc_long
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit e6cfaf34be9fcd1a8285a294e18986bfc41a409c upstream.
+
+proc_get_long() is passed a size_t, but then assigns it to an 'int'
+variable for the length.  Let's not do that, even if our IO paths are
+limited to MAX_RW_COUNT (exactly because of these kinds of type errors).
+
+So do the proper test in the rigth type.
+
+Reported-by: Kyle Zeng <zengyhkyle@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sysctl.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -454,13 +454,12 @@ static int proc_get_long(char **buf, siz
+                         unsigned long *val, bool *neg,
+                         const char *perm_tr, unsigned perm_tr_len, char *tr)
+ {
+-      int len;
+       char *p, tmp[TMPBUFLEN];
++      ssize_t len = *size;
+-      if (!*size)
++      if (len <= 0)
+               return -EINVAL;
+-      len = *size;
+       if (len > TMPBUFLEN - 1)
+               len = TMPBUFLEN - 1;
diff --git a/queue-5.15/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch b/queue-5.15/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch
new file mode 100644 (file)
index 0000000..3d3ddf2
--- /dev/null
@@ -0,0 +1,106 @@
+From bce9332220bd677d83b19d21502776ad555a0e73 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Mon, 5 Dec 2022 12:09:06 -0800
+Subject: proc: proc_skip_spaces() shouldn't think it is working on C strings
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit bce9332220bd677d83b19d21502776ad555a0e73 upstream.
+
+proc_skip_spaces() seems to think it is working on C strings, and ends
+up being just a wrapper around skip_spaces() with a really odd calling
+convention.
+
+Instead of basing it on skip_spaces(), it should have looked more like
+proc_skip_char(), which really is the exact same function (except it
+skips a particular character, rather than whitespace).  So use that as
+inspiration, odd coding and all.
+
+Now the calling convention actually makes sense and works for the
+intended purpose.
+
+Reported-and-tested-by: Kyle Zeng <zengyhkyle@gmail.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sysctl.c |   25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -379,13 +379,14 @@ int proc_dostring(struct ctl_table *tabl
+                       ppos);
+ }
+-static size_t proc_skip_spaces(char **buf)
++static void proc_skip_spaces(char **buf, size_t *size)
+ {
+-      size_t ret;
+-      char *tmp = skip_spaces(*buf);
+-      ret = tmp - *buf;
+-      *buf = tmp;
+-      return ret;
++      while (*size) {
++              if (!isspace(**buf))
++                      break;
++              (*size)--;
++              (*buf)++;
++      }
+ }
+ static void proc_skip_char(char **buf, size_t *size, const char v)
+@@ -632,7 +633,7 @@ static int __do_proc_dointvec(void *tbl_
+               bool neg;
+               if (write) {
+-                      left -= proc_skip_spaces(&p);
++                      proc_skip_spaces(&p, &left);
+                       if (!left)
+                               break;
+@@ -659,7 +660,7 @@ static int __do_proc_dointvec(void *tbl_
+       if (!write && !first && left && !err)
+               proc_put_char(&buffer, &left, '\n');
+       if (write && !err && left)
+-              left -= proc_skip_spaces(&p);
++              proc_skip_spaces(&p, &left);
+       if (write && first)
+               return err ? : -EINVAL;
+       *lenp -= left;
+@@ -701,7 +702,7 @@ static int do_proc_douintvec_w(unsigned
+       if (left > PAGE_SIZE - 1)
+               left = PAGE_SIZE - 1;
+-      left -= proc_skip_spaces(&p);
++      proc_skip_spaces(&p, &left);
+       if (!left) {
+               err = -EINVAL;
+               goto out_free;
+@@ -721,7 +722,7 @@ static int do_proc_douintvec_w(unsigned
+       }
+       if (!err && left)
+-              left -= proc_skip_spaces(&p);
++              proc_skip_spaces(&p, &left);
+ out_free:
+       if (err)
+@@ -1258,7 +1259,7 @@ static int __do_proc_doulongvec_minmax(v
+               if (write) {
+                       bool neg;
+-                      left -= proc_skip_spaces(&p);
++                      proc_skip_spaces(&p, &left);
+                       if (!left)
+                               break;
+@@ -1286,7 +1287,7 @@ static int __do_proc_doulongvec_minmax(v
+       if (!write && !first && left && !err)
+               proc_put_char(&buffer, &left, '\n');
+       if (write && !err)
+-              left -= proc_skip_spaces(&p);
++              proc_skip_spaces(&p, &left);
+       if (write && first)
+               return err ? : -EINVAL;
+       *lenp -= left;
index d90a8a1bb2cd9e7541ad15aa98e694ff1d2a549e..5f0ac5c0fc580c77c89ef4466c2ebb83fdaa267d 100644 (file)
@@ -118,3 +118,6 @@ acpi-hmat-fix-initiator-registration-for-single-init.patch
 revert-clocksource-drivers-riscv-events-are-stopped-.patch
 char-tpm-protect-tpm_pm_suspend-with-locks.patch
 input-raydium_ts_i2c-fix-memory-leak-in-raydium_i2c_send.patch
+ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.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