Save environment snapshot and use at fork/exec

Some applications may inadvertently or maliciously set of environment
variables such as LD_LIBRARY_PATH before spawning subprocesses.
To make this more difficult, save the environment at the time the
runtime starts and use the saved copy anytime Exec is called.

BUG: 30160149
TEST: make test-art-{host,target}

Change-Id: I887b78bdb21ab20855636a96da14a74c767bbfef
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 0a01cdb..3ba20a4 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -16,6 +16,8 @@
 
 #include "utils.h"
 
+#include <stdlib.h>
+
 #include "base/enums.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
@@ -380,10 +382,59 @@
   if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
     // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks.
     EXPECT_FALSE(Exec(command, &error_msg));
-    EXPECT_NE(0U, error_msg.size());
+    EXPECT_FALSE(error_msg.empty());
   }
 }
 
+TEST_F(UtilsTest, EnvSnapshotAdditionsAreNotVisible) {
+  static constexpr const char* kModifiedVariable = "EXEC_SHOULD_NOT_EXPORT_THIS";
+  static constexpr int kOverwrite = 1;
+  // Set an variable in the current environment.
+  EXPECT_EQ(setenv(kModifiedVariable, "NEVER", kOverwrite), 0);
+  // Test that it is not exported.
+  std::vector<std::string> command;
+  if (kIsTargetBuild) {
+    std::string android_root(GetAndroidRoot());
+    command.push_back(android_root + "/bin/printenv");
+  } else {
+    command.push_back("/usr/bin/printenv");
+  }
+  command.push_back(kModifiedVariable);
+  std::string error_msg;
+  if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
+    // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks.
+    EXPECT_FALSE(Exec(command, &error_msg));
+    EXPECT_NE(0U, error_msg.size()) << error_msg;
+  }
+}
+
+TEST_F(UtilsTest, EnvSnapshotDeletionsAreNotVisible) {
+  static constexpr const char* kDeletedVariable = "PATH";
+  static constexpr int kOverwrite = 1;
+  // Save the variable's value.
+  const char* save_value = getenv(kDeletedVariable);
+  EXPECT_NE(save_value, nullptr);
+  // Delete the variable.
+  EXPECT_EQ(unsetenv(kDeletedVariable), 0);
+  // Test that it is not exported.
+  std::vector<std::string> command;
+  if (kIsTargetBuild) {
+    std::string android_root(GetAndroidRoot());
+    command.push_back(android_root + "/bin/printenv");
+  } else {
+    command.push_back("/usr/bin/printenv");
+  }
+  command.push_back(kDeletedVariable);
+  std::string error_msg;
+  if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
+    // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks.
+    EXPECT_TRUE(Exec(command, &error_msg));
+    EXPECT_EQ(0U, error_msg.size()) << error_msg;
+  }
+  // Restore the variable's value.
+  EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0);
+}
+
 TEST_F(UtilsTest, IsValidDescriptor) {
   std::vector<uint8_t> descriptor(
       { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, ';', 0x00 });