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
This commit is contained in:
Norman Feske 2021-02-12 11:46:55 +01:00
parent fd0e6685fc
commit a99f6a81b6
3 changed files with 13 additions and 0 deletions

View File

@ -28,6 +28,7 @@
<resource name="RAM" quantum="1G"/>
<config>
<arg value="name_of_executeable"/>
<env key="WIZARD" value="gandalf"/>
<libc stdin="/null" stdout="/log" stderr="/log">
<fd id="3" path="/seek_test" readable="yes" seek="5"/>
</libc>

View File

@ -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));

View File

@ -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());