From e86ce14944d8c436b79a45cec98878a9eecd9492 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Dec 2022 12:37:14 +0100 Subject: [PATCH] 6.0-stable patches 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 --- ...-sem_array-access-in-semtimedop-race.patch | 67 +++++++++++ ...eger-type-confusion-in-get_proc_long.patch | 40 +++++++ ...n-t-think-it-is-working-on-c-strings.patch | 106 ++++++++++++++++++ queue-6.0/series | 3 + 4 files changed, 216 insertions(+) create mode 100644 queue-6.0/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch create mode 100644 queue-6.0/proc-avoid-integer-type-confusion-in-get_proc_long.patch create mode 100644 queue-6.0/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch diff --git a/queue-6.0/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch b/queue-6.0/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch new file mode 100644 index 00000000000..d02c198c302 --- /dev/null +++ b/queue-6.0/ipc-sem-fix-dangling-sem_array-access-in-semtimedop-race.patch @@ -0,0 +1,67 @@ +From b52be557e24c47286738276121177a41f54e3b83 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Mon, 5 Dec 2022 17:59:27 +0100 +Subject: ipc/sem: Fix dangling sem_array access in semtimedop race + +From: Jann Horn + +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 +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + ipc/sem.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -2179,14 +2179,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-6.0/proc-avoid-integer-type-confusion-in-get_proc_long.patch b/queue-6.0/proc-avoid-integer-type-confusion-in-get_proc_long.patch new file mode 100644 index 00000000000..fdc1a6cfe7d --- /dev/null +++ b/queue-6.0/proc-avoid-integer-type-confusion-in-get_proc_long.patch @@ -0,0 +1,40 @@ +From e6cfaf34be9fcd1a8285a294e18986bfc41a409c Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 5 Dec 2022 11:33:40 -0800 +Subject: proc: avoid integer type confusion in get_proc_long + +From: Linus Torvalds + +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 +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sysctl.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -340,13 +340,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-6.0/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch b/queue-6.0/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch new file mode 100644 index 00000000000..14dd323629b --- /dev/null +++ b/queue-6.0/proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch @@ -0,0 +1,106 @@ +From bce9332220bd677d83b19d21502776ad555a0e73 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +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 + +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 +Acked-by: Eric Dumazet +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sysctl.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -265,13 +265,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) +@@ -518,7 +519,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; +@@ -545,7 +546,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; +@@ -587,7 +588,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; +@@ -607,7 +608,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) +@@ -1072,7 +1073,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; + +@@ -1101,7 +1102,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; diff --git a/queue-6.0/series b/queue-6.0/series index 96d1cedd439..704f88b0f4b 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -122,3 +122,6 @@ 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 powerpc-bpf-32-fix-oops-on-tail-call-tests.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 -- 2.47.3