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]
