]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Jun 2024 13:27:35 +0000 (15:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Jun 2024 13:27:35 +0000 (15:27 +0200)
added patches:
riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch
riscv-stacktrace-fixed-walk_stackframe.patch
sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch

queue-6.6/riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch [new file with mode: 0644]
queue-6.6/riscv-stacktrace-fixed-walk_stackframe.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch [new file with mode: 0644]

diff --git a/queue-6.6/riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch b/queue-6.6/riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch
new file mode 100644 (file)
index 0000000..90eb7ec
--- /dev/null
@@ -0,0 +1,56 @@
+From a638b0461b58aa3205cd9d5f14d6f703d795b4af Mon Sep 17 00:00:00 2001
+From: Sergey Matyukevich <sergey.matyukevich@syntacore.com>
+Date: Thu, 23 May 2024 11:43:23 +0300
+Subject: riscv: prevent pt_regs corruption for secondary idle threads
+
+From: Sergey Matyukevich <sergey.matyukevich@syntacore.com>
+
+commit a638b0461b58aa3205cd9d5f14d6f703d795b4af upstream.
+
+Top of the kernel thread stack should be reserved for pt_regs. However
+this is not the case for the idle threads of the secondary boot harts.
+Their stacks overlap with their pt_regs, so both may get corrupted.
+
+Similar issue has been fixed for the primary hart, see c7cdd96eca28
+("riscv: prevent stack corruption by reserving task_pt_regs(p) early").
+However that fix was not propagated to the secondary harts. The problem
+has been noticed in some CPU hotplug tests with V enabled. The function
+smp_callin stored several registers on stack, corrupting top of pt_regs
+structure including status field. As a result, kernel attempted to save
+or restore inexistent V context.
+
+Fixes: 9a2451f18663 ("RISC-V: Avoid using per cpu array for ordered booting")
+Fixes: 2875fe056156 ("RISC-V: Add cpu_ops and modify default booting method")
+Signed-off-by: Sergey Matyukevich <sergey.matyukevich@syntacore.com>
+Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Link: https://lore.kernel.org/r/20240523084327.2013211-1-geomatsi@gmail.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/kernel/cpu_ops_sbi.c      |    2 +-
+ arch/riscv/kernel/cpu_ops_spinwait.c |    3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/arch/riscv/kernel/cpu_ops_sbi.c
++++ b/arch/riscv/kernel/cpu_ops_sbi.c
+@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cp
+       /* Make sure tidle is updated */
+       smp_mb();
+       bdata->task_ptr = tidle;
+-      bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE;
++      bdata->stack_ptr = task_pt_regs(tidle);
+       /* Make sure boot data is updated */
+       smp_mb();
+       hsm_data = __pa(bdata);
+--- a/arch/riscv/kernel/cpu_ops_spinwait.c
++++ b/arch/riscv/kernel/cpu_ops_spinwait.c
+@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdat
+       /* Make sure tidle is updated */
+       smp_mb();
+-      WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid],
+-                 task_stack_page(tidle) + THREAD_SIZE);
++      WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle));
+       WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
+ }
diff --git a/queue-6.6/riscv-stacktrace-fixed-walk_stackframe.patch b/queue-6.6/riscv-stacktrace-fixed-walk_stackframe.patch
new file mode 100644 (file)
index 0000000..cd9590e
--- /dev/null
@@ -0,0 +1,127 @@
+From a2a4d4a6a0bf5eba66f8b0b32502cc20d82715a0 Mon Sep 17 00:00:00 2001
+From: Matthew Bystrin <dev.mbstr@gmail.com>
+Date: Tue, 21 May 2024 22:13:13 +0300
+Subject: riscv: stacktrace: fixed walk_stackframe()
+
+From: Matthew Bystrin <dev.mbstr@gmail.com>
+
+commit a2a4d4a6a0bf5eba66f8b0b32502cc20d82715a0 upstream.
+
+If the load access fault occures in a leaf function (with
+CONFIG_FRAME_POINTER=y), when wrong stack trace will be displayed:
+
+[<ffffffff804853c2>] regmap_mmio_read32le+0xe/0x1c
+---[ end trace 0000000000000000 ]---
+
+Registers dump:
+    ra     0xffffffff80485758 <regmap_mmio_read+36>
+    sp     0xffffffc80200b9a0
+    fp     0xffffffc80200b9b0
+    pc     0xffffffff804853ba <regmap_mmio_read32le+6>
+
+Stack dump:
+    0xffffffc80200b9a0:  0xffffffc80200b9e0  0xffffffc80200b9e0
+    0xffffffc80200b9b0:  0xffffffff8116d7e8  0x0000000000000100
+    0xffffffc80200b9c0:  0xffffffd8055b9400  0xffffffd8055b9400
+    0xffffffc80200b9d0:  0xffffffc80200b9f0  0xffffffff8047c526
+    0xffffffc80200b9e0:  0xffffffc80200ba30  0xffffffff8047fe9a
+
+The assembler dump of the function preambula:
+    add     sp,sp,-16
+    sd      s0,8(sp)
+    add     s0,sp,16
+
+In the fist stack frame, where ra is not stored on the stack we can
+observe:
+
+        0(sp)                  8(sp)
+        .---------------------------------------------.
+    sp->|       frame->fp      | frame->ra (saved fp) |
+        |---------------------------------------------|
+    fp->|         ....         |         ....         |
+        |---------------------------------------------|
+        |                      |                      |
+
+and in the code check is performed:
+       if (regs && (regs->epc == pc) && (frame->fp & 0x7))
+
+I see no reason to check frame->fp value at all, because it is can be
+uninitialized value on the stack. A better way is to check frame->ra to
+be an address on the stack. After the stacktrace shows as expect:
+
+[<ffffffff804853c2>] regmap_mmio_read32le+0xe/0x1c
+[<ffffffff80485758>] regmap_mmio_read+0x24/0x52
+[<ffffffff8047c526>] _regmap_bus_reg_read+0x1a/0x22
+[<ffffffff8047fe9a>] _regmap_read+0x5c/0xea
+[<ffffffff80480376>] _regmap_update_bits+0x76/0xc0
+...
+---[ end trace 0000000000000000 ]---
+As pointed by Samuel Holland it is incorrect to remove check of the stackframe
+entirely.
+
+Changes since v2 [2]:
+ - Add accidentally forgotten curly brace
+
+Changes since v1 [1]:
+ - Instead of just dropping frame->fp check, replace it with validation of
+   frame->ra, which should be a stack address.
+ - Move frame pointer validation into the separate function.
+
+[1] https://lore.kernel.org/linux-riscv/20240426072701.6463-1-dev.mbstr@gmail.com/
+[2] https://lore.kernel.org/linux-riscv/20240521131314.48895-1-dev.mbstr@gmail.com/
+
+Fixes: f766f77a74f5 ("riscv/stacktrace: Fix stack output without ra on the stack top")
+Signed-off-by: Matthew Bystrin <dev.mbstr@gmail.com>
+Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
+Link: https://lore.kernel.org/r/20240521191727.62012-1-dev.mbstr@gmail.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/kernel/stacktrace.c |   20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/arch/riscv/kernel/stacktrace.c
++++ b/arch/riscv/kernel/stacktrace.c
+@@ -18,6 +18,16 @@
+ extern asmlinkage void ret_from_exception(void);
++static inline int fp_is_valid(unsigned long fp, unsigned long sp)
++{
++      unsigned long low, high;
++
++      low = sp + sizeof(struct stackframe);
++      high = ALIGN(sp, THREAD_SIZE);
++
++      return !(fp < low || fp > high || fp & 0x07);
++}
++
+ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
+                            bool (*fn)(void *, unsigned long), void *arg)
+ {
+@@ -41,21 +51,19 @@ void notrace walk_stackframe(struct task
+       }
+       for (;;) {
+-              unsigned long low, high;
+               struct stackframe *frame;
+               if (unlikely(!__kernel_text_address(pc) || (level++ >= 0 && !fn(arg, pc))))
+                       break;
+-              /* Validate frame pointer */
+-              low = sp + sizeof(struct stackframe);
+-              high = ALIGN(sp, THREAD_SIZE);
+-              if (unlikely(fp < low || fp > high || fp & 0x7))
++              if (unlikely(!fp_is_valid(fp, sp)))
+                       break;
++
+               /* Unwind stack frame */
+               frame = (struct stackframe *)fp - 1;
+               sp = fp;
+-              if (regs && (regs->epc == pc) && (frame->fp & 0x7)) {
++              if (regs && (regs->epc == pc) && fp_is_valid(frame->ra, sp)) {
++                      /* We hit function where ra is not saved on the stack */
+                       fp = frame->ra;
+                       pc = regs->ra;
+               } else {
index c2d747af58380a674295ef64ca3a0112e88012b3..194784cef878abb44a6cc022d67ea63ff3e45234 100644 (file)
@@ -733,3 +733,5 @@ perf-sched-timehist-fix-g-call-graph-option-failure.patch
 f2fs-write-missing-last-sum-blk-of-file-pinning-section.patch
 f2fs-use-f2fs_-err-info-_ratelimited-for-cleanup.patch
 sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch
+riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch
+riscv-stacktrace-fixed-walk_stackframe.patch
diff --git a/queue-6.6/sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch b/queue-6.6/sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch
new file mode 100644 (file)
index 0000000..48b4693
--- /dev/null
@@ -0,0 +1,33 @@
+From 4a77c3dead97339478c7422eb07bf4bf63577008 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sun, 2 Jun 2024 18:15:25 -0400
+Subject: SUNRPC: Fix loop termination condition in gss_free_in_token_pages()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 4a77c3dead97339478c7422eb07bf4bf63577008 upstream.
+
+The in_token->pages[] array is not NULL terminated. This results in
+the following KASAN splat:
+
+  KASAN: maybe wild-memory-access in range [0x04a2013400000008-0x04a201340000000f]
+
+Fixes: bafa6b4d95d9 ("SUNRPC: Fix gss_free_in_token_pages()")
+Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/auth_gss/svcauth_gss.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1079,7 +1079,7 @@ static int gss_read_proxy_verf(struct sv
+               goto out_denied_free;
+       pages = DIV_ROUND_UP(inlen, PAGE_SIZE);
+-      in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL);
++      in_token->pages = kcalloc(pages + 1, sizeof(struct page *), GFP_KERNEL);
+       if (!in_token->pages)
+               goto out_denied_free;
+       in_token->page_base = 0;