From a99f6a81b671ac33bfb38bdd08aff5f09d132a4b Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 12 Feb 2021 11:46:55 +0100 Subject: [PATCH] libc: clone 'environ' pointer value after fork The 'environ' pointer is a global variable that must be considered as part of the application state. It must be copied from the parent to the child process during fork. Otherwise, a child returning from fork is unable to access environment variables before invoking execve. The actual environment variables and their values are already captured because they reside at the application heap, which is cloned from the parent. So the copied 'environ' pointer refers to valid data. Fixes #4015 --- repos/libports/recipes/pkg/test-libc_fork/runtime | 1 + repos/libports/src/lib/libc/kernel.cc | 6 ++++++ repos/libports/src/test/fork/test.cc | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/repos/libports/recipes/pkg/test-libc_fork/runtime b/repos/libports/recipes/pkg/test-libc_fork/runtime index daaac5abc5..57914546ea 100644 --- a/repos/libports/recipes/pkg/test-libc_fork/runtime +++ b/repos/libports/recipes/pkg/test-libc_fork/runtime @@ -28,6 +28,7 @@ + diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index ac208b223e..50fa93bac1 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -19,6 +19,9 @@ Libc::Kernel * Libc::Kernel::_kernel_ptr; +extern char **environ; + + /** * Blockade for main context */ @@ -346,6 +349,9 @@ void Libc::Kernel::_clone_state_from_parent() _cloned_heap_ranges.for_each([&] (Cloned_malloc_heap_range &heap_range) { heap_range.import_content(*_clone_connection); }); + /* value of global environ pointer (the env vars are already on the heap) */ + _clone_connection->memory_content(&environ, sizeof(environ)); + /* fetch user contex of the parent's application */ _clone_connection->memory_content(&_user_context, sizeof(_user_context)); _clone_connection->memory_content(&_main_monitor_job, sizeof(_main_monitor_job)); diff --git a/repos/libports/src/test/fork/test.cc b/repos/libports/src/test/fork/test.cc index 6f4ec4f282..b1ef7398ff 100644 --- a/repos/libports/src/test/fork/test.cc +++ b/repos/libports/src/test/fork/test.cc @@ -38,6 +38,12 @@ int main(int, char **argv) printf("pid %d: fork returned %d\n", getpid(), fork_ret); + /* check the consistency of known environment variable in both processes */ + if (!getenv("WIZARD") || strcmp(getenv("WIZARD"), "gandalf") != 0) { + printf("Error: inheritance of environment variable failed\n"); + return -1; + } + /* child */ if (fork_ret == 0) { printf("pid %d: child says hello\n", getpid());