hitHuang opened a new pull request, #19377:
URL: https://github.com/apache/nuttx/pull/19377
## Summary
`riscv_fillpage()` is the LOADPF/STOREPF handler used under `CONFIG_PAGING`.
Both of
its fault paths (virtual address not mappable, leaf PTE already mapped with a
permission violation) unconditionally called `PANIC_WITH_REGS()`, taking
down the
whole kernel even when the fault was caused by an ordinary user-space task
dereferencing a bad pointer.
`riscv_exception()` already has a pattern for this: if the faulting task is
a user
task and not currently inside a syscall, it rewrites the trap frame to
return into
`_exit(SIGSEGV)` on the task's own kernel stack instead of panicking, and
only panics
when there's no safe task to terminate (kernel thread, or a fault while
already
running kernel code on behalf of a syscall). `riscv_fillpage()` never reused
this
logic, so any user-space wild-pointer access that missed the paged-in
text/data/heap
regions crashed the entire system instead of just the offending process.
This PR extracts that decision (terminate the task vs. panic) out of
`riscv_exception()` into a shared static helper, `riscv_fault_handler()`,
and has
both `riscv_exception()` and both fault sites in `riscv_fillpage()` call it.
## Impact
- Only affects `CONFIG_PAGING` builds (`BUILD_KERNEL && ARCH_USE_MMU &&
!ARCH_ROMPGTABLE && !LEGACY_PAGING`) on RISC-V.
- Behavior change: a user-space task that faults in `riscv_fillpage()` on an
address
outside the mappable text/data/heap ranges, or on top of an already-mapped
leaf PTE
(permission violation), is now terminated with `SIGSEGV` instead of taking
down the
kernel. Kernel threads and faults occurring in kernel context on behalf of
a syscall
still panic, since there's no user task that can be safely unwound in that
case.
- This also applies to permission-mismatch faults triggered by a user-space
application (leaf PTE already valid but its permissions don't satisfy the
access,
e.g. a write to an already-loaded `.text` page): that case used to
unconditionally
panic the kernel, and now terminates the offending task instead,
consistent with
every other fault path in this file.
- No Kconfig, API, or build system changes.
- Pure refactor for `riscv_exception()` itself: its own panic/terminate
logic is now
in `riscv_fault_handler()`, called the same way as before.
## Testing
Tested on QEMU RISC-V (`rv-virt`), both `knsh_paging` (32-bit) and
`knsh64_paging`
(64-bit) configs. Also verified on Houmo M50 hardware.
Test app, a modified `hello` that dereferences a NULL pointer:
```c
int main(int argc, FAR char *argv[])
{
*(int *)0 = 0x5a5a5a5a;
printf("Hello, World!!\n");
return 0;
}
```
**Before this fix**: the NULL write is treated as "address not mappable", and
`riscv_fillpage` panics the whole kernel:
```
NuttShell (NSH) NuttX-13.0.0-RC2
nsh> hello
[ 2.307000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: 8020edc0, MTVAL: c0001000
[ 2.318000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: 8020fa1c, MTVAL: c1000ffc
[ 2.320000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: 8021011c, MTVAL: c080638c
[ 2.322000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: 80211108, MTVAL: c0804004
[ 2.324000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: c00003bc, MTVAL: c0803ffc
[ 2.328000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
0000000f, EPC: c00003ee, MTVAL: 00000000
[ 2.328000] riscv_fillpage: PANIC!!! virtual address not mappable: 0
[ 2.328000] dump_assert_info: Current Version: NuttX 13.0.0-RC2
194d38ea4f Jul 8 2026 11:32:56 risc-v
[ 2.328000] dump_assert_info: Assertion failed panic: at file: :0 task:
hello process: hello 0xc00003ba
[ 2.328000] up_dump_register: EPC: c00003ee
[ 2.328000] up_dump_register: A0: 00000001 A1: c0802020 A2: 00000000 A3:
00000020
[ 2.328000] up_dump_register: A4: 00000000 A5: 5a5a5a5a A6: 00000000 A7:
00000000
[ 2.328000] up_dump_register: T0: 0000001c T1: 80608720 T2: 80609320 T3:
00042022
[ 2.328000] up_dump_register: T4: 00000001 T5: 80607a70 T6: 00000000
[ 2.328000] up_dump_register: S0: 00000668 S1: 80609988 S2: 8020f40a S3:
00000000
[ 2.328000] up_dump_register: S4: 00000000 S5: 00000000 S6: 0000001c S7:
00000000
[ 2.328000] up_dump_register: S8: 00000000 S9: 00000000 S10: 00042022
S11: 80609308
[ 2.328000] up_dump_register: SP: c0803fb0 FP: 00000668 TP: 00000000 RA:
c00003d6
[ 2.328000] dump_stackinfo: User Stack:
[ 2.328000] dump_stackinfo: base: 0xc0802030
[ 2.328000] dump_stackinfo: size: 00008144
[ 2.328000] dump_stackinfo: sp: 0xc0803fb0
[ 2.328000] stack_dump: 0xc0803f90: 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
[ 2.328000] stack_dump: 0xc0803fb0: 00000000 00000000 c0802020 00000001
00000000 00000000 00000000 c00003d6
[ 2.328000] stack_dump: 0xc0803fd0: 00000000 00000000 c0802020 00000001
00000000 00000000 00000000 00000000
[ 2.328000] stack_dump: 0xc0803ff0: 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
[ 2.328000] dump_tasks: PID GROUP PRI POLICY TYPE NPX STATE
EVENT SIGMASK STACKBASE STACKSIZE COMMAND
[ 2.328000] dump_tasks: ---- --- --- -------- ------- --- -------
---------- ---------------- 0x80606000 2048 irq
[ 2.328000] dump_task: 0 0 0 FIFO Kthread - Ready
0000000000000000 0x80607b40 3040 Idle_Task
[ 2.328000] dump_task: 1 0 100 RR Kthread - Waiting
Semaphore 0000000000000000 0x8060a050 1968 lpwork 0x80600010 0x80600060
[ 2.328000] dump_task: 3 3 100 RR Task - Waiting
Signal 0000000000000000 0xc0802040 3008 /system/bin/init
[ 2.328000] dump_task: 4 4 100 RR Task - Running
0000000000000000 0xc0802030 8144 hello
```
The whole system goes down for a single user process's bad pointer.
**After this fix**: same test app, same NULL write. `riscv_fillpage` still
detects the
fault the same way, but now routes it through `riscv_fault_handler()`, which
recognizes `hello` as a user task not in a syscall and terminates it with
`SIGSEGV`
instead of panicking:
```
NuttShell (NSH) NuttX-13.0.0-RC2
nsh> hello
[ 1.724000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0001000
[ 1.734000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
000000000000000f, EPC: 000000008020ff78, MTVAL: 00000000c1000ff8
[ 1.737000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
000000000000000f, EPC: 00000000802106aa, MTVAL: 00000000c08065d0
[ 1.740000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE:
000000000000000f, EPC: 00000000c0000060, MTVAL: 0000000000000000
[ 1.740000] riscv_fillpage: Virtual address not mappable: 0
[ 1.740000] riscv_fault_handler: Segmentation fault in hello (PID 4:
hello)
nsh> ps
TID PID PPID PRI POLICY TYPE NPX STATE EVENT SIGMASK
STACK COMMAND
0 0 0 0 FIFO Kthread - Ready
0000000000000000 0003024 Idle_Task
1 0 0 100 RR Kthread - Waiting Semaphore
0000000000000000 0001936 lpwork 0x80600100 0x80600180
3 3 0 100 RR Task - Running
0000000000000000 0002976 /system/bin/init
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]