casaroli opened a new pull request, #20834: URL: https://github.com/apache/nuttx/pull/20834
## Summary `mprotect()` returned 0 and changed nothing, also in kernel builds where the MMU can change the page permissions. A page made read-only stayed writable, a page could not become executable, and bad arguments were not reported. In all builds, `mprotect()` now returns `EINVAL` when `addr` is not a multiple of `sysconf(_SC_PAGESIZE)` or `prot` has an unknown bit. Without `CONFIG_ARCH_ADDRENV` a valid request still returns 0 and changes nothing: without an MMU the permissions cannot be enforced. With `CONFIG_ARCH_ADDRENV`, `mprotect()` calls `up_addrenv_mprot()` for the address environment of the caller. It returns `ENOMEM` when a page of the range is not mapped user memory, and then nothing changes. With `PROT_EXEC` the kernel also makes the instruction cache coherent for the range, so code written to the pages runs without a cache maintenance call in the program. `PROT_READ | PROT_WRITE | PROT_EXEC` is allowed; a W^X policy can come later as an option. `up_addrenv_mprot()` on arm64 and RISC-V now checks the whole range before it changes an entry: a user address with a valid page entry. Before, it accepted any address, changed invalid entries and stopped half way on an error. On arm64, `PROT_NONE` now removes the user access (it gave a readable page). On RISC-V, `PROT_WRITE` now also sets R (W without R is a reserved encoding), and with `CONFIG_SMP` every hart runs `sfence.vma` and `fence.i` through `nxsched_smp_call()` (before, only the local hart did). On arm64, `fork()` now copies the page attributes of the parent. Before, the child got the default permissions, so a read-only page of the parent was writable in the child. The commits: - arch/arm64: Check the range in up_addrenv_mprot() and support PROT_NONE. - arch/risc-v: Check the range in up_addrenv_mprot(). - arch/risc-v: Flush all harts in up_addrenv_mprot(). - fs/mmap: Implement mprotect(). - arch/arm64: Keep the page permissions in fork(). - Documentation: Update the mprotect() support. ## Impact Kernel builds (`CONFIG_ARCH_ADDRENV`) on arm64 and RISC-V: `mprotect()` changes the page permissions. A program that wrote to a page after it made the page read-only now gets a fault. All builds: `mprotect()` with an unaligned `addr` or an unknown `prot` bit now fails with `EINVAL` instead of returning 0. Other targets with `CONFIG_ARCH_ADDRENV` (x86_64, armv7-a, the arm64 MPU and ESP32-S3) have a `up_addrenv_mprot()` that does nothing: there a valid request returns 0 as before. The ELF loader calls `up_addrenv_mprot()` for `.text`. That range passes the new check. ## Testing Test program `mprotect.c`. Each fault case runs in a child process that the program spawns: mmap an anonymous page, make it read-only and write it; PROT_NONE and read; write code to a page and call it before and after `PROT_READ | PROT_EXEC`; write new code after RW, back to RX, call it; `PROT_READ | PROT_WRITE | PROT_EXEC`; a read-only `.bss` page, also in a fork() child; EINVAL and ENOMEM cases. In a flat build only the argument checks run. - qemu-armv8a:knsh (HVF): master 16 of 22 checks fail; this branch all pass. Without the fork() commit only the read-only `.bss` page in the fork() child fails. - rv-virt:knsh64, rv-virt:ksmp64 (4 harts) and rv-virt:knsh64_paging (QEMU TCG, `CONFIG_FS_SHMFS` added so that anonymous mmap() gives pages): this branch all pass (the fork() case is skipped: no fork() on RISC-V). rv-virt:knsh64 on master: 15 of 21 fail. - qemu-armv8a:nsh (flat, HVF): `sysconf(_SC_PAGESIZE)` is 8192 there. Master returns 0 for an unaligned `addr` and an unknown `prot` bit; this branch returns EINVAL, and valid requests return 0. ostest: exit status 0 on qemu-armv8a:knsh, qemu-armv8a:nsh, rv-virt:knsh64, rv-virt:ksmp64 and rv-virt:knsh64_paging. -- 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]
