diff options
Diffstat (limited to 'cmds/dumpstate/DumpstateUtil.cpp')
-rw-r--r-- | cmds/dumpstate/DumpstateUtil.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp index 4b69607156..c833d0e6bd 100644 --- a/cmds/dumpstate/DumpstateUtil.cpp +++ b/cmds/dumpstate/DumpstateUtil.cpp @@ -124,6 +124,12 @@ CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Re return *this; } +CommandOptions::CommandOptionsBuilder& +CommandOptions::CommandOptionsBuilder::CloseAllFileDescriptorsOnExec() { + values.close_all_fds_on_exec_ = true; + return *this; +} + CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Log( const std::string& message) { values.logging_message_ = message; @@ -137,6 +143,7 @@ CommandOptions CommandOptions::CommandOptionsBuilder::Build() { CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout_ms) : timeout_ms_(timeout_ms), always_(false), + close_all_fds_on_exec_(false), account_mode_(DONT_DROP_ROOT), output_mode_(NORMAL_OUTPUT), logging_message_("") { @@ -157,6 +164,10 @@ bool CommandOptions::Always() const { return values.always_; } +bool CommandOptions::ShouldCloseAllFileDescriptorsOnExec() const { + return values.close_all_fds_on_exec_; +} + PrivilegeMode CommandOptions::PrivilegeMode() const { return values.account_mode_; } @@ -180,6 +191,7 @@ CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeoutInMs(int64_t ti std::string PropertiesHelper::build_type_ = ""; int PropertiesHelper::dry_run_ = -1; int PropertiesHelper::unroot_ = -1; +int PropertiesHelper::parallel_run_ = -1; bool PropertiesHelper::IsUserBuild() { if (build_type_.empty()) { @@ -202,6 +214,14 @@ bool PropertiesHelper::IsUnroot() { return unroot_ == 1; } +bool PropertiesHelper::IsParallelRun() { + if (parallel_run_ == -1) { + parallel_run_ = android::base::GetBoolProperty("dumpstate.parallel_run", + /* default_value = */true) ? 1 : 0; + } + return parallel_run_ == 1; +} + int DumpFileToFd(int out_fd, const std::string& title, const std::string& path) { android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC))); if (fd.get() < 0) { @@ -268,7 +288,8 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri MYLOGI(logging_message.c_str(), command_string.c_str()); } - bool silent = (options.OutputMode() == REDIRECT_TO_STDERR); + bool silent = (options.OutputMode() == REDIRECT_TO_STDERR || + options.ShouldCloseAllFileDescriptorsOnExec()); bool redirecting_to_fd = STDOUT_FILENO != fd; if (PropertiesHelper::IsDryRun() && !options.Always()) { @@ -305,7 +326,27 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri return -1; } - if (silent) { + if (options.ShouldCloseAllFileDescriptorsOnExec()) { + int devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDIN_FILENO)); + close(devnull_fd); + devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDOUT_FILENO)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDERR_FILENO)); + close(devnull_fd); + // This is to avoid leaking FDs that, accidentally, have not been + // marked as O_CLOEXEC. Leaking FDs across exec can cause failures + // when execing a process that has a SELinux auto_trans rule. + // Here we assume that the dumpstate process didn't open more than + // 1000 FDs. In theory we could iterate through /proc/self/fd/, but + // doing that in a fork-safe way is too complex and not worth it + // (opendir()/readdir() do heap allocations and take locks). + for (int i = 0; i < 1000; i++) { + if (i != STDIN_FILENO && i!= STDOUT_FILENO && i != STDERR_FILENO) { + close(i); + } + } + } else if (silent) { // Redirects stdout to stderr TEMP_FAILURE_RETRY(dup2(STDERR_FILENO, STDOUT_FILENO)); } else if (redirecting_to_fd) { |