casaroli opened a new pull request, #20583: URL: https://github.com/apache/nuttx/pull/20583
## Summary An alternative to #20570 for the environment in a kernel build, so that the two can be compared. In a kernel build the environment of a process is in its user heap, but `getenv()`, `setenv()` and the other functions were system calls, and `environ` was not a variable. This PR moves the environment functions to libc, as openvela does: - The first commit is openvela's e60e6de82f by guoshichao: the environment fields move from `task_group_s` to `task_info_s`, which is in user memory. - The second commit moves `getenv()`, `setenv()`, `putenv()`, `unsetenv()`, `clearenv()`, `secure_getenv()` and `get_environ_ptr()` to `libs/libc/environ`. They leave the system call table. The kernel keeps `env_dup()` for a new task, `env_release()`, `env_foreach()` for procfs, and `env_sanitize_secure()`. `environ` becomes an lvalue, so a program can assign it and change its entries, as POSIX allows. Programs do both: gnulib's `putenv()` replaces an entry in place, and GNU make assigns its own array, with strings on its stack. The code that freed the environment then freed strings that it did not allocate, and the heap asserted (inside the kernel, with #20570). libc now keeps the array that it allocated and a parallel array of the strings that it allocated, and compares them with `environ` before each change. It frees a string only while the string is still where libc put it; a string that a program put into the environment is never freed. ## Impact - All builds: the environment functions are libc functions, not system calls. Programs of a kernel build must be built again. - `environ` can be assigned in all builds. - `setenv(name, "", 1)` sets an empty value, as POSIX says. Before, it removed the variable. - In a kernel build `env_release()` does not free the environment of a user process: it is in the user heap, which goes away with the address environment. ## Testing A test program that assigns `environ` and changes its entries, built against the export package of `qemu-armv8a:knsh` and run in QEMU 11: ``` nsh> envtest envtest: setenv A, B A=1 B=2 C=- envtest: environ[i] replaced in place A=replaced-in-place B=2 C=- envtest: setenv A after the replacement A=3 B=2 C=- envtest: unsetenv A A=- B=2 C=- envtest: environ = own array A=- B=2 C=from-the-stack envtest: setenv B after the assignment A=- B=4 C=from-the-stack envtest: clearenv A=- B=- C=- envtest: setenv A after clearenv A=5 B=- C=- envtest: done ``` `ostest` on `qemu-armv8a:knsh` (kernel build) and `qemu-armv8a:nsh` (flat build): the environment checks pass, and `ostest_main: Exiting with status 0`. Builds: `qemu-armv8a:knsh` (with `make export` and the apps `make import`), `rv-virt:knsh64`, `qemu-armv7a:knsh`, `sabre-6quad:netknsh`, `lm3s6965-ek:qemu-flat`, `lm3s6965-ek:qemu-protected`, `mps2-an500:nsh`, `qemu-armv8a:nsh`, `rv-virt:nsh64`, `esp32-devkitc:nsh`. `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]
