summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Nissler <mnissler@rivosinc.com>2023-02-15 17:48:28 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-17 10:45:08 +0300
commit713c335e5a8f1e65dbe9980ed77d8ae4c0364c34 (patch)
treebf6f8ae9c2ea1cd52cecfef30612b20ef8e636a9
parentf9fdb3e7b0758516fbc5ae12e3ec23d9060f7035 (diff)
downloadlinux-713c335e5a8f1e65dbe9980ed77d8ae4c0364c34.tar.xz
riscv: Avoid enabling interrupts in die()
[ Upstream commit 130aee3fd9981297ff9354e5d5609cd59aafbbea ] While working on something else, I noticed that the kernel would start accepting interrupts again after crashing in an interrupt handler. Since the kernel is already in inconsistent state, enabling interrupts is dangerous and opens up risk of kernel state deteriorating further. Interrupts do get enabled via what looks like an unintended side effect of spin_unlock_irq, so switch to the more cautious spin_lock_irqsave/spin_unlock_irqrestore instead. Fixes: 76d2a0493a17 ("RISC-V: Init and Halt Code") Signed-off-by: Mattias Nissler <mnissler@rivosinc.com> Reviewed-by: Björn Töpel <bjorn@kernel.org> Link: https://lore.kernel.org/r/20230215144828.3370316-1-mnissler@rivosinc.com Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--arch/riscv/kernel/traps.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index bc6b30f3add8..227253fde33c 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -32,10 +32,11 @@ void die(struct pt_regs *regs, const char *str)
static int die_counter;
int ret;
long cause;
+ unsigned long flags;
oops_enter();
- spin_lock_irq(&die_lock);
+ spin_lock_irqsave(&die_lock, flags);
console_verbose();
bust_spinlocks(1);
@@ -52,7 +53,7 @@ void die(struct pt_regs *regs, const char *str)
bust_spinlocks(0);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
- spin_unlock_irq(&die_lock);
+ spin_unlock_irqrestore(&die_lock, flags);
oops_exit();
if (in_interrupt())