Allow passing environment also for LD_PRELOAD
This expands support for passing an environment for the child process
also for the LD_PRELOAD case. The code now constructs the enviroment
for the child in a separate environment array for both code paths.
This also avoids messing with the parent's environment, which may have
unintended side effects.
BUG=chromium:1050997
TEST=New unit tests.
Change-Id: Ib05cad1d1ebe6e10d429501c8e467c3a53632753
diff --git a/util_unittest.cc b/util_unittest.cc
index c97dc2a..ab4805a 100644
--- a/util_unittest.cc
+++ b/util_unittest.cc
@@ -15,6 +15,20 @@
#include "util.h"
+namespace {
+
+std::string dump_env(const char *const *env) {
+ std::string result;
+ for (; *env; ++env) {
+ result += *env;
+ result += "\n";
+ }
+
+ return result;
+}
+
+} // namespace
+
// Sanity check for the strip func.
TEST(strip, basic) {
char str[] = " foo\t";
@@ -81,3 +95,66 @@
ASSERT_EQ(nullptr, p);
ASSERT_EQ(nullptr, tokenize(&p, ","));
}
+
+// Check environment manipulation functions.
+TEST(environment, copy_and_modify) {
+ minijail_free_env(nullptr);
+
+ char **env = minijail_copy_env(nullptr);
+ EXPECT_EQ("", dump_env(env));
+ minijail_free_env(env);
+
+ const char *const kConstEnv[] = {
+ "val1=1",
+ "val2=2",
+ "dup=1",
+ "dup=2",
+ "empty=",
+ nullptr,
+ };
+
+ // libc unfortunately uses char* const[] as the type for the environment, and
+ // we match that. It's actually missing a const-ness of the chars making up
+ // the environment strings, but we need that to initialize the |kEnv|
+ // constant. Hence, do a cast here to force things into alignment...
+ char* const* kEnv = const_cast<char* const*>(kConstEnv);
+
+ env = minijail_copy_env(kEnv);
+ EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
+ minijail_free_env(env);
+
+ env = minijail_copy_env(kEnv);
+ EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
+
+ EXPECT_EQ(EINVAL, minijail_setenv(nullptr, "val1", "3", 1));
+ char **env_ret = nullptr;
+ EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "val1", "3", 1));
+
+ env_ret = env;
+ EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, nullptr, "3", 1));
+ EXPECT_EQ(env, env_ret);
+ EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", "3", 1));
+ EXPECT_EQ(env, env_ret);
+ EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", nullptr, 1));
+ EXPECT_EQ(env, env_ret);
+
+ EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 0));
+ EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 1));
+ EXPECT_EQ("val1=3\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "val2", "4", 1));
+ EXPECT_EQ("val1=3\nval2=4\ndup=1\ndup=2\nempty=\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "dup", "5", 1));
+ EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "empty", "6", 1));
+ EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=6\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "empty", "", 1));
+ EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "new1", "7", 0));
+ EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
+ EXPECT_EQ(0, minijail_setenv(&env, "new2", "8", 1));
+ EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+ dump_env(env));
+
+ minijail_free_env(env);
+}