mirror of
https://github.com/apache/nuttx.git
synced 2026-10-08 23:05:20 +00:00
arch/risc-v: fix fault handler misattributing kernel faults to user tasks
riscv_fault_handler() only checked the task type and SYSCALL flag, so a fault taken inside an interrupt handler (running in kernel mode) was blamed on the user task that happened to be interrupted and killed with SIGSEGV, hiding the real kernel bug. Use the STATUS_PPP bit of the trap frame to tell whether the fault originated from user mode: only then is it safe to kill the task. Signed-off-by: liang.huang <liang.huang@houmo.ai>
This commit is contained in:
parent
41837f0699
commit
32f578f37a
1 changed files with 12 additions and 5 deletions
|
|
@ -87,10 +87,11 @@ static const char *g_reasons_str[RISCV_MAX_EXCEPTION + 1] =
|
|||
*
|
||||
* Description:
|
||||
* Handle a fault caused by the running task. If the task is a user task
|
||||
* not currently in a syscall, kill it with SIGSEGV instead of
|
||||
* taking down the whole system. Otherwise (kernel thread, or a fault
|
||||
* while already in kernel context on behalf of a syscall) there is no
|
||||
* safe task to kill, so panic.
|
||||
* not currently in a syscall or interrupt context, kill it with SIGSEGV
|
||||
* instead of taking down the whole system. Otherwise (kernel thread, a
|
||||
* fault while already in kernel context on behalf of a syscall, or a
|
||||
* fault while handling an interrupt) there is no safe task to kill, so
|
||||
* panic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cause - The (masked) machine cause of the exception, used for the
|
||||
|
|
@ -104,8 +105,14 @@ static void riscv_fault_handler(uintreg_t cause, void *regs)
|
|||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* The STATUS_PPP check alone is enough: any kernel-mode fault (kernel
|
||||
* thread, syscall body, or interrupt) has STATUS_PPP != 0. The other
|
||||
* two checks are kept as defensive redundancy.
|
||||
*/
|
||||
|
||||
if (((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) &&
|
||||
((tcb->flags & TCB_FLAG_SYSCALL) == false))
|
||||
((tcb->flags & TCB_FLAG_SYSCALL) == false) &&
|
||||
!(((uintreg_t *)regs)[REG_INT_CTX] & STATUS_PPP))
|
||||
{
|
||||
struct tcb_s *ptcb = nxsched_get_tcb(tcb->group->tg_pid);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue