From e6d8df2c198b501e4b4acce664c10018fc6c3e97 Mon Sep 17 00:00:00 2001 From: Daniel Rossier Date: Thu, 16 Jul 2026 18:31:09 +0200 Subject: [PATCH] so3: terminate the faulting user process on an EL0 abort instead of panicking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A data/instruction abort taken from EL0 (ESR_ELx_EC_DABT_LOW / IABT_LOW) is a fault in the running user process — typically a NULL-pointer dereference. It used to fall through to trap_handle_error() + kernel_panic(), bringing down the whole kernel. Handle it in a new user_fault(): report which process faulted and where, then sys_do_exit_group() to kill only that process so the shell regains control. Kernel-mode (EL1) aborts use a different exception class and still reach the fatal path. Scoped to !CONFIG_AVZ (AVZ keeps its mmio-decode / s3c_crash path). --- so3/so3/arch/arm64/traps.c | 44 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/so3/so3/arch/arm64/traps.c b/so3/so3/arch/arm64/traps.c index 61038a56a..962ce297e 100644 --- a/so3/so3/arch/arm64/traps.c +++ b/so3/so3/arch/arm64/traps.c @@ -40,6 +40,9 @@ #else /* CONFIG_AVZ */ #include +#include +#include +#include #endif /* !CONFIG_AVZ */ #include @@ -215,9 +218,36 @@ int dabt_handle(cpu_regs_t *regs, unsigned long esr) #endif } +#ifndef CONFIG_AVZ +/* A synchronous abort taken from a lower EL (EL0) is a fault in the running + * user process — typically a NULL-pointer dereference. Report which process + * faulted and where, then terminate that process ONLY, so the shell regains + * control instead of the whole kernel panicking. Kernel-mode (EL1) faults use a + * different exception class (DABT/IABT "current EL") and still reach the fatal + * path in trap_handle(). */ + +static void user_fault(unsigned long esr) +{ + unsigned long far = read_sysreg(far_el1); + unsigned long elr = read_sysreg(elr_el1); + pcb_t *pcb = current()->pcb; + + printk("[SO3] process \"%s\" (pid %d) faulted at address 0x%lx (pc=0x%lx, ESR=0x%lx) - terminating it.\n", + pcb ? pcb->name : "?", pcb ? pcb->pid : -1, far, elr, esr); + + /* Terminate the offending process. sys_do_exit_group() sets it zombie and + * schedules away, so it does not return here; the parent's wait4() reaps + * it and the shell reprints its prompt. IRQs must be enabled for the + * scheduler, as in the syscall path above. */ + + local_irq_enable(); + sys_do_exit_group(128 + SIGSEGV); +} +#endif /* !CONFIG_AVZ */ + /** * This is the entry point for all exceptions currently managed by SO3. - * + * * Regarding the SOO hypercalls, all addresses got from arguments * *must* be physical addresses. * @@ -253,8 +283,13 @@ void trap_handle(cpu_regs_t *regs) case ESR_ELx_EC_DABT_LOW: ret = dabt_handle(regs, esr); - if (ret == -1) + if (ret == -1) { +#ifdef CONFIG_AVZ goto __err; +#else + user_fault(esr); /* EL0 data abort: terminate the user process */ +#endif + } break; /* SVC used for syscalls */ @@ -429,7 +464,12 @@ void trap_handle(cpu_regs_t *regs) } case ESR_ELx_EC_IABT_LOW: +#ifdef CONFIG_AVZ goto __err; +#else + user_fault(esr); /* EL0 instruction abort: terminate the user process */ + break; +#endif default: __err: