commit:     b321cd403c653d5bac54b5ec8341bc631fe3331e
Author:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
AuthorDate: Sat Mar 13 22:35:53 2021 +0000
Commit:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
CommitDate: Sat Mar 13 22:53:39 2021 +0000
URL:        https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=b321cd40

libsandbox: try harder not to regenerate environment

In bug #775842 Sam noticed sandbox crash on libabigail-1.8.2 testsuite:

    #0  0x00007f0e0d10e392 in sb_new_envp ()
      at libsandbox.c:1184
    #1  0x00007f0e0d112745 in system_DEFAULT ()
      at wrapper-funcs/__wrapper_exec.c:315
    #2  0x000055ece6570b52 in test_task::perform (this=0x55ece72978b0)
      at 
/usr/lib/gcc/x86_64-pc-linux-gnu/11.0.1/include/g++-v11/bits/basic_string.h:186
    #3  0x00007f0e0d05fce5 in abigail::workers::worker::wait_to_execute_a_task 
(p=0x55ece728f380)
      at 
/tmp/portage/dev-util/libabigail-1.8.2/work/libabigail-1.8.2/src/abg-workers.cc:415
    #4  0x00007f0e0c8f7cae in start_thread (arg=0x7f0e0b433640)
      at pthread_create.c:473
    #5  0x00007f0e0ca0eb2f in clone ()
      at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

The test roughly does call system() from spawned parallel threads:
    for_each_test(){
      spawn_thread([]{
        system("cmd"); wait();
      }
    }

Sandbox has to inject sandbox-specific environment variables where
they don't exist. This is fundamentally racy in multithreaded
environment:

    for_each_test(){
      spawn_thread([]{
        environ = modified_env;
        system("cmd"); wait();
        environ = orig_env;
      }
    }

Most of the time environment does not have to change after initial
environment injection. f3e51a9303124 ("exec*() wrappers: never mutate
'environ' of host process") exposed a bug in sandbox's logic of
checking existing environment: unset variables like `SANDBOX_DENY`

The change treats unset/expected-unset variables as non deviating.

Reported-by: Sam James
Bug: https://bugs.gentoo.org/775842
Signed-off-by: Sergei Trofimovich <slyfox <AT> gentoo.org>

 libsandbox/libsandbox.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index b4d732d..166516c 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -1181,6 +1181,7 @@ struct sb_envp_ctx sb_new_envp(char **envp, bool insert)
        found_var_cnt = 0;
        memset(found_vars, 0, sizeof(found_vars));
 
+       /* Iterate through user's environment and check against expected. */
        str_list_for_each_item(envp, entry, count) {
                for (i = 0; i < num_vars; ++i) {
                        if (found_vars[i])
@@ -1192,6 +1193,14 @@ struct sb_envp_ctx sb_new_envp(char **envp, bool insert)
                }
        }
 
+       /* Treat unset and expected-unset variables as found. This will allow us
+        * to keep existing environment. */
+       for (i = 0; i < num_vars; ++i) {
+               if (vars[i].value == NULL && found_vars[i] == NULL) {
+                       ++found_var_cnt;
+               }
+       }
+
        /* Now specially handle merging of LD_PRELOAD */
        char *ld_preload;
        bool merge_ld_preload = found_vars[0] && !strstr(found_vars[0], 
sandbox_lib);

Reply via email to