2019-09-25 00:06:59

by Vincent Chen

[permalink] [raw]
Subject: [PATCH 0/4] riscv: correct the do_trap_break()


The following three situations may occur in the current implementation of
do_trap_break().
1. When the CONFIG_GENERIC_BUG is disabled, if a kernel thread is trapped
by BUG(), the whole system will be in the loop that infinitely handles
the break exception instead of entering the die function.
2. When the kernel runs code on behalf of a user thread, and the kernel
executes a WARN() or WARN_ON(), the user thread will be sent a bogus
SIGTRAP.
3. Handling the unexpected ebreak instructions is to send a SIGTRAP
to the trapped thread. However, if a kernel executes an unexpected
ebreak, it may cause the kernel thread to be stuck in the ebreak
instruction.

This patch set will solve the above problems by adjusting the
implementations of the do_trap_break().


Vincent Chen (4):
riscv: avoid kernel hangs when trapped in BUG()
rsicv: avoid sending a SIGTRAP to a user thread trapped in WARN()
riscv: Correct the handling of unexpected ebreak in do_trap_break()
riscv: remove the switch statement in do_trap_break()

arch/riscv/kernel/traps.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

--
2.7.4


2019-09-25 00:06:59

by Vincent Chen

[permalink] [raw]
Subject: [PATCH 1/4] riscv: avoid kernel hangs when trapped in BUG()

When the CONFIG_GENERIC_BUG is disabled by disabling CONFIG_BUG, if a
kernel thread is trapped by BUG(), the whole system will be in the
loop that infinitely handles the ebreak exception instead of entering the
die function. To fix this problem, the do_trap_break() will always call
the die() to deal with the break exception as the type of break is
BUG_TRAP_TYPE_BUG.

Signed-off-by: Vincent Chen <[email protected]>
---
arch/riscv/kernel/traps.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 424eb72d56b1..055a937aca70 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -124,23 +124,23 @@ static inline unsigned long get_break_insn_length(unsigned long pc)

asmlinkage void do_trap_break(struct pt_regs *regs)
{
-#ifdef CONFIG_GENERIC_BUG
if (!user_mode(regs)) {
enum bug_trap_type type;

type = report_bug(regs->sepc, regs);
switch (type) {
+#ifdef CONFIG_GENERIC_BUG
case BUG_TRAP_TYPE_NONE:
break;
case BUG_TRAP_TYPE_WARN:
regs->sepc += get_break_insn_length(regs->sepc);
break;
case BUG_TRAP_TYPE_BUG:
+#endif /* CONFIG_GENERIC_BUG */
+ default:
die(regs, "Kernel BUG");
}
}
-#endif /* CONFIG_GENERIC_BUG */
-
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc));
}

--
2.7.4

2019-09-27 22:28:19

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/4] riscv: avoid kernel hangs when trapped in BUG()

On Mon, Sep 23, 2019 at 08:45:14AM +0800, Vincent Chen wrote:
> When the CONFIG_GENERIC_BUG is disabled by disabling CONFIG_BUG, if a
> kernel thread is trapped by BUG(), the whole system will be in the
> loop that infinitely handles the ebreak exception instead of entering the
> die function. To fix this problem, the do_trap_break() will always call
> the die() to deal with the break exception as the type of break is
> BUG_TRAP_TYPE_BUG.
>
> Signed-off-by: Vincent Chen <[email protected]>

Looks good,

Reviewed-by: Christoph Hellwig <[email protected]>

2019-10-04 18:27:53

by Paul Walmsley

[permalink] [raw]
Subject: Re: [PATCH 1/4] riscv: avoid kernel hangs when trapped in BUG()

On Mon, 23 Sep 2019, Vincent Chen wrote:

> When the CONFIG_GENERIC_BUG is disabled by disabling CONFIG_BUG, if a
> kernel thread is trapped by BUG(), the whole system will be in the
> loop that infinitely handles the ebreak exception instead of entering the
> die function. To fix this problem, the do_trap_break() will always call
> the die() to deal with the break exception as the type of break is
> BUG_TRAP_TYPE_BUG.
>
> Signed-off-by: Vincent Chen <[email protected]>

Thanks, queued for v5.4-rc.


- Paul