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