From e59034de2619382bd1624a2c8297dfd3e79dfcc8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 11 Jun 2024 15:27:35 +0200 Subject: [PATCH] 6.6-stable patches 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 --- ...orruption-for-secondary-idle-threads.patch | 56 ++++++++ ...scv-stacktrace-fixed-walk_stackframe.patch | 127 ++++++++++++++++++ queue-6.6/series | 2 + ...condition-in-gss_free_in_token_pages.patch | 33 +++++ 4 files changed, 218 insertions(+) create mode 100644 queue-6.6/riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch create mode 100644 queue-6.6/riscv-stacktrace-fixed-walk_stackframe.patch create mode 100644 queue-6.6/sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch 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 index 00000000000..90eb7ec600e --- /dev/null +++ b/queue-6.6/riscv-prevent-pt_regs-corruption-for-secondary-idle-threads.patch @@ -0,0 +1,56 @@ +From a638b0461b58aa3205cd9d5f14d6f703d795b4af Mon Sep 17 00:00:00 2001 +From: Sergey Matyukevich +Date: Thu, 23 May 2024 11:43:23 +0300 +Subject: riscv: prevent pt_regs corruption for secondary idle threads + +From: Sergey Matyukevich + +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 +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/20240523084327.2013211-1-geomatsi@gmail.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cd9590e77d5 --- /dev/null +++ b/queue-6.6/riscv-stacktrace-fixed-walk_stackframe.patch @@ -0,0 +1,127 @@ +From a2a4d4a6a0bf5eba66f8b0b32502cc20d82715a0 Mon Sep 17 00:00:00 2001 +From: Matthew Bystrin +Date: Tue, 21 May 2024 22:13:13 +0300 +Subject: riscv: stacktrace: fixed walk_stackframe() + +From: Matthew Bystrin + +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: + +[] regmap_mmio_read32le+0xe/0x1c +---[ end trace 0000000000000000 ]--- + +Registers dump: + ra 0xffffffff80485758 + sp 0xffffffc80200b9a0 + fp 0xffffffc80200b9b0 + pc 0xffffffff804853ba + +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: + +[] regmap_mmio_read32le+0xe/0x1c +[] regmap_mmio_read+0x24/0x52 +[] _regmap_bus_reg_read+0x1a/0x22 +[] _regmap_read+0x5c/0xea +[] _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 +Reviewed-by: Samuel Holland +Link: https://lore.kernel.org/r/20240521191727.62012-1-dev.mbstr@gmail.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman +--- + 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 { diff --git a/queue-6.6/series b/queue-6.6/series index c2d747af583..194784cef87 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -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 index 00000000000..48b4693200f --- /dev/null +++ b/queue-6.6/sunrpc-fix-loop-termination-condition-in-gss_free_in_token_pages.patch @@ -0,0 +1,33 @@ +From 4a77c3dead97339478c7422eb07bf4bf63577008 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Sun, 2 Jun 2024 18:15:25 -0400 +Subject: SUNRPC: Fix loop termination condition in gss_free_in_token_pages() + +From: Chuck Lever + +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 +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + 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; -- 2.47.3