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

   ## Summary
   
   POSIX: `exec` and `posix_spawn()` fail with `E2BIG` when the arguments and 
the environment of the new image are larger than `ARG_MAX` bytes. 
`CONFIG_TASK_ARG_MAX` sets `ARG_MAX` and `sysconf(_SC_ARG_MAX)`, but nothing 
checked it. An argument list that did not fit the stack of the new task reached 
a `DEBUGASSERT` in `nxtask_setup_stackargs()`, so a program could stop the 
system with one long argument. Without assertions the loop set `-ENAMETOOLONG` 
but did not advance, so it never ended.
   
   - `nxtask_init()` undoes the scheduler setup when a later step fails. 
`nxtask_setup_scheduler()` gives the TCB a PID and puts it on the inactive task 
list; when `tls_init_info()` or `nxtask_setup_stackargs()` then failed, both 
stayed in place and the caller freed the TCB with `kmm_free()`. The next task 
creation could then crash the kernel. The kernel stack of the new task also 
leaked. This path was reachable without assertions before; the `E2BIG` below 
makes it reachable with them, so it comes first.
   - `nxtask_setup_stackargs()` ends with `E2BIG` when the arguments do not fit 
the stack, when the `argv[]` array does not fit with them (`up_stack_frame()` 
fails), or when there are more than `CONFIG_TASK_MAX_ARGS`.
   - `exec_internal()` counts the bytes of the argument and environment 
strings, with their terminators and pointers, before it loads the program, and 
fails with `E2BIG` above `ARG_MAX`.
   - Documentation: `posix_spawn()` and the `TASK_ARG_MAX` help.
   
   ## Impact
   
   `exec()` and `posix_spawn()` of a program with more than `ARG_MAX` bytes of 
arguments and environment fail with `E2BIG` (the default `ARG_MAX` is 4096). A 
configuration that passes more must raise `CONFIG_TASK_ARG_MAX`. All build 
modes and architectures.
   
   ## Testing
   
   Test program `e2big.c` on `qemu-armv8a:knsh` (QEMU with HVF, 
`CONFIG_TASK_ARG_MAX=65536`): a small argument, an argument and an environment 
larger than `ARG_MAX`, `execv()` with a too large argument, an argument within 
`ARG_MAX` that does not fit an 8 KiB stack (twice), then 8 small spawns. ostest 
runs after it in the same boot.
   
   | | master | this PR without its first commit | this PR |
   |---|---|---|---|
   | `e2big` | the argument larger than `ARG_MAX` stops the system with an 
assertion in the kernel (`task/task_setup.c:557`) | 7 of 7 pass | 7 of 7 pass |
   | ostest after `e2big` | (not reached) | kernel data abort when NSH starts 
ostest (`arm64_fatal.c:696`, fault address `0x74736574736f` in one run, `0x10` 
in another): a freed TCB in the task lists | status 0 |
   
   ostest also exits with status 0 on `qemu-armv8a:nsh` with this PR, and on 
master with `CONFIG_TASK_ARG_MAX=65536` (knsh and nsh), so the option alone 
changes nothing.
   
   The `stack` case depends on the configuration: with a larger stack the 
argument fits, and the case gives 0, not `E2BIG`.
   
   Build, each OK: `qemu-armv8a:nsh` (flat, arm64), `qemu-armv8a:knsh` (kernel, 
arm64), `lm3s6965-ek:qemu-protected` (protected, armv7-m), `qemu-armv7a:knsh` 
(kernel, armv7-a), `rv-virt:nsh64` (flat, rv64), `rv-virt:knsh64` (kernel, 
rv64). No new warnings.
   
   `tools/checkpatch.sh -c -u -m -g` passes.
   


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