hitHuang opened a new pull request, #19364:
URL: https://github.com/apache/nuttx/pull/19364

   ## Summary
   
   `riscv_fillpage()` is the LOADPF/STOREPF handler used under `CONFIG_PAGING`. 
It checked
   whether intermediate page table levels were already allocated, but never 
checked the
   final leaf PTE before installing a new mapping.
   
   RISC-V raises the same LOADPF/STOREPF cause both when a leaf PTE is absent 
(a real fault)
   and when it is present but its permission bits don't satisfy the access, 
e.g. a store to
   a `.text` page whose write access was revoked after ELF loading. The two 
cases are
   indistinguishable from `mcause` alone.
   
   Treating both cases as "page missing" let `riscv_fillpage` silently allocate 
a fresh,
   zeroed physical page over an existing mapping, discarding the old page (a 
leak) and
   defeating whatever permission that mapping was enforcing. Reproduced on real 
hardware: a
   user-space store to an already-loaded `.text` page got a fresh writable page 
instead of
   being rejected, silently zeroing out the code at that address.
   
   This PR checks the leaf PTE's valid bit before allocating; if a mapping 
already exists,
   it panics instead of overwriting it.
   
   ## Impact
   
   - Only affects `CONFIG_PAGING` builds (`BUILD_KERNEL && ARCH_USE_MMU &&
     !ARCH_ROMPGTABLE && !LEGACY_PAGING`) on RISC-V.
   - Behavior change: a LOADPF/STOREPF on an already-mapped leaf PTE (permission
     violation) now panics instead of silently reallocating and zeroing the 
page. This
     turns a silent memory-corruption bug into a detectable failure.
   - No Kconfig, API, or build system changes.
   
   ## Testing
   
   Verified on qemu rv-virt:
   
   Test app, a modified `hello` that writes to an already-loaded `.text` 
address:
   
   ```c
   int main(int argc, FAR char *argv[])
   {
     void *p = (void *)0xc0001000;
   
     *(int *)p = 0x5a5a5a5a;
   
   //  printf("Hello, World!!\n");
     return 0;
   }
   ```
   Corresponding disassembly. `c0000068` is the store that hits `0xc0001000`:
   ```
   00000000c000004c <main>:
       c000004c:   1101                    add     sp,sp,-32
       c000004e:   87aa                    mv      a5,a0
       c0000050:   e02e                    sd      a1,0(sp)
       c0000052:   c63e                    sw      a5,12(sp)
       c0000054:   000c07b7                lui     a5,0xc0
       c0000058:   0785                    add     a5,a5,1 # c0001 
<sig_trampoline-0xbff3ffff>
       c000005a:   07b2                    sll     a5,a5,0xc
       c000005c:   ec3e                    sd      a5,24(sp)
       c000005e:   67e2                    ld      a5,24(sp)
       c0000060:   5a5a6737                lui     a4,0x5a5a6
       c0000064:   a5a70713                add     a4,a4,-1446 # 5a5a5a5a 
<sig_trampoline-0x65a5a5a6>
   ->  c0000068:   c398                    sw      a4,0(a5)
       c000006a:   4781                    li      a5,0
       c000006c:   853e                    mv      a0,a5
       c000006e:   6105                    add     sp,sp,32
       c0000070:   8082                    ret
   ```
   **Before this fix**: `hello` runs to completion instead of crashing.
   
   Boot log (loader lazily faulting in `.text` pages via `riscv_fillpage`, 
before any
   user command is run):
   
   ```
   ABC[    0.046000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0001000
   [    0.057000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0002000
   [    0.059000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0003000
   [    0.062000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0004000
   [    0.064000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0005000
   [    0.066000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0006000
   [    0.069000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0007000
   [    0.071000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0008000
   [    0.073000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0009000
   [    0.075000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000a000
   [    0.077000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000b000
   [    0.079000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000c000
   [    0.081000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000d000
   [    0.083000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000e000
   [    0.086000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c000f000
   [    0.088000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0010000
   [    0.090000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0011000
   [    0.093000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0012000
   [    0.096000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0013000
   [    0.101000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020ff78, MTVAL: 00000000c1000ff8
   [    0.104000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 00000000802106aa, MTVAL: 00000000c08051d0
   
   NuttShell (NSH) NuttX-13.0.0-RC0
   ```
   
   Running `hello`. The store to `0xc0001000` raises a `Store/AMO page fault`;
   `riscv_fillpage` finds the leaf PTE already valid but doesn't check it, 
allocates a
   fresh zeroed page, and installs it over the existing `.text` mapping. 
`hello` returns
   normally and the shell stays responsive, i.e. no crash:
   
   ```
   nsh> hello
   [    1.820000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0001000
   [    1.831000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020ff78, MTVAL: 00000000c1000ff8
   [    1.834000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 00000000802106aa, MTVAL: 00000000c08065d0
   [    1.838000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 00000000c0000068, MTVAL: 00000000c0001000
   nsh>
   nsh>
   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
   ```
   
   GDB confirms the code page at `0xc0001000` (containing part of 
`nxsem_clockwait`) was
   replaced with all zeros after the write:
   
   ```
   (gdb) add-symbol-file ~/workspace/nuttx-fork/apps/bin_debug/hello
   add symbol table from file 
"/home/huang/workspace/nuttx-fork/apps/bin_debug/hello"
   (y or n) y
   Reading symbols from /home/huang/workspace/nuttx-fork/apps/bin_debug/hello...
   (gdb) b *0xc0000068
   Breakpoint 1 at 0xc0000068: file hello_main.c, line 42.
   (gdb) c
   Continuing.
   
   Breakpoint 1, 0x00000000c0000068 in main (argc=1, argv=0xc0802030) at 
hello_main.c:42
   42        *(int *)p = 0x5a5a5a5a;
   (gdb) x/16xw 0xC0001000
   0xc0001000 <sys_call3+30>:      0x00000073      0x87aa0001      0x6105853e   
   0x71798082
   0xc0001010 <nxsem_clockwait+2>: 0xec2af406      0xe43287ae      0x67e2ca3e   
   0x66a24752
   0xc0001020 <nxsem_clockwait+18>:        0x85be863a      0xf0ef4571      
0x87aafbdf      0x853e2781
   0xc0001030 <nxsem_clockwait+34>:        0x614570a2      0x11418082      
0xe02e87aa      0x6783c63e
   (gdb) c
   Continuing.
   
   Breakpoint 1, 0x00000000c0000068 in main (argc=1, argv=0xc0802030) at 
hello_main.c:42
   42        *(int *)p = 0x5a5a5a5a;
   (gdb) x/16xw 0xC0001000
   0xc0001000 <sys_call3+30>:      0x00000000      0x00000000      0x00000000   
   0x00000000
   0xc0001010 <nxsem_clockwait+2>: 0x00000000      0x00000000      0x00000000   
   0x00000000
   0xc0001020 <nxsem_clockwait+18>:        0x00000000      0x00000000      
0x00000000      0x00000000
   0xc0001030 <nxsem_clockwait+34>:        0x00000000      0x00000000      
0x00000000      0x00000000
   ```
   
   If the commented-out `printf()` call is re-enabled, `hello` crashes inside 
the printf
   path, because that path calls into code located in the now-zeroed page at
   `0xc0001000` — but that's incidental (it depends on which function happens 
to share
   the page with the corrupted address), not the expected failure mode.
   
   The root cause is that a write to `.text` raises a Store/AMO page fault, and 
because
   of the write permission granted in `riscv_fillpage` for the reasons 
described in
   https://github.com/apache/nuttx/pull/6193, that write to `.text` is allowed 
to
   succeed instead of being rejected.
   
   **After this fix**: the same write to `0xc0001000` now hits the leaf-PTE 
check, and
   `riscv_fillpage` panics instead of silently overwriting the mapping:
   
   ```
   nsh> hello
   [    4.182000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020f2d8, MTVAL: 00000000c0001000
   [    4.190000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 000000008020ff78, MTVAL: 00000000c1000ff8
   [    4.193000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 00000000802106aa, MTVAL: 00000000c08065d0
   [    4.196000] riscv_fillpage: EXCEPTION: Store/AMO page fault. MCAUSE: 
000000000000000f, EPC: 00000000c0000068, MTVAL: 00000000c0001000
   [    4.196000] riscv_fillpage: PANIC!!! page already mapped, permission 
violation: c0001000
   [    4.196000] dump_assert_info: Current Version: NuttX  13.0.0-RC0 
70fd28f73b-dirty Jul  8 2026 09:00:04 risc-v
   [    4.196000] dump_assert_info: Assertion failed panic: at file: :0 task: 
hello process: hello 0xc000001c
   [    4.196000] up_dump_register: EPC: 00000000c0000068
   [    4.196000] up_dump_register: A0: 0000000000000001 A1: 00000000c0802030 
A2: 0000000000000000 A3: 000000008060b6f0
   [    4.196000] up_dump_register: A4: 000000005a5a5a5a A5: 00000000c0001000 
A6: 0000000000000000 A7: 000000008020f942
   [    4.196000] up_dump_register: T0: 0000000080210718 T1: 0000000000000030 
T2: 000000008060a000 T3: 0000000200042022
   [    4.196000] up_dump_register: T4: 000000008060b6f0 T5: 0000000000000000 
T6: 0000000200042022
   [    4.196000] up_dump_register: S0: 000000008060b718 S1: 0000000000000148 
S2: 0000000000000000 S3: 0000000000000030
   [    4.196000] up_dump_register: S4: 0000000000000000 S5: 0000000200042022 
S6: 000000008060b6f0 S7: 0000000200042022
   [    4.196000] up_dump_register: S8: 0000000100000000 S9: 00000000806083c8 
S10: 0000001600000000 S11: 0000000200042022
   [    4.196000] up_dump_register: SP: 00000000c0803fb0 FP: 000000008060b718 
TP: 0000000000000000 RA: 00000000c0000040
   [    4.196000] dump_stackinfo: User Stack:
   [    4.196000] dump_stackinfo:   base: 0xc0802050
   [    4.196000] dump_stackinfo:   size: 00008112
   [    4.196000] dump_stackinfo:     sp: 0xc0803fb0
   [    4.196000] stack_dump: 0xc0803f70: 0000000000000000 0000000000000000 
0000000000000000 0000000000000000 0000000000000000 0000000000000000 
0000000000000000 0000000000000000
   [    4.196000] stack_dump: 0xc0803fb0: 00000000c0802030 0000000100000000 
0000000000000000 00000000c0001000 00000000c0802030 0000000100000000 
0000000000000000 0000000000000000
   [    4.196000] stack_dump: 0xc0803ff0: 0000000000000000 00000000802101a2 
0000000000000000 0000000000000000 0000000000000000 0000000000000000 
0000000000000000 0000000000000000
   [    4.196000] dump_tasks:    PID GROUP PRI POLICY   TYPE    NPX STATE   
EVENT      SIGMASK          STACKBASE  STACKSIZE   COMMAND
   [    4.196000] dump_tasks:   ----   --- --- -------- ------- --- ------- 
---------- ---------------- 0x80607000      2048   irq
   [    4.196000] dump_task:       0     0   0 FIFO     Kthread -   Ready       
       0000000000000000 0x80609430      3024   Idle_Task
   [    4.196000] dump_task:       1     0 100 RR       Kthread -   Waiting 
Semaphore  0000000000000000 0x8060c070      1936   lpwork 0x80600100 0x80600180
   [    4.196000] dump_task:       3     3 100 RR       Task    -   Waiting 
Signal     0000000000000000 0xc0802060      2976   /system/bin/init
   [    4.196000] dump_task:       4     4 100 RR       Task    -   Running     
       0000000000000000 0xc0802050      8112   hello
   ```


-- 
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]

Reply via email to