From 0a7603c097e9ac8845a51808aef35978fa6f0cfb Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Mon, 21 Feb 2022 19:38:14 +0000 Subject: Add a timeout for all installd operations. Bug: 216514270 Test: atest installd_utils_test Test: atest installd_dexopt_test Change-Id: I6c25e1df756ca486de1c8611185dbedf60d7cd7d Merged-In: I6c25e1df756ca486de1c8611185dbedf60d7cd7d (cherry picked from commit 495142ac75cdb2595a61755d7ab42a748e651728) --- cmds/installd/utils.cpp | 78 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 19 deletions(-) (limited to 'cmds/installd/utils.cpp') diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index faccded34b..f04ee337d9 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -19,18 +19,21 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include -#include #include +#include #include #include #include @@ -1059,30 +1062,45 @@ int ensure_config_user_dirs(userid_t userid) { return fs_prepare_dir(path.c_str(), 0750, uid, gid); } -int wait_child(pid_t pid) -{ +static int wait_child(pid_t pid) { int status; - pid_t got_pid; + pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, /*options=*/0)); - while (1) { - got_pid = waitpid(pid, &status, 0); - if (got_pid == -1 && errno == EINTR) { - printf("waitpid interrupted, retrying\n"); - } else { - break; - } - } if (got_pid != pid) { - ALOGW("waitpid failed: wanted %d, got %d: %s\n", - (int) pid, (int) got_pid, strerror(errno)); - return 1; + PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid; + return W_EXITCODE(/*exit_code=*/255, /*signal_number=*/0); } - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - return 0; - } else { - return status; /* always nonzero */ + return status; +} + +int wait_child_with_timeout(pid_t pid, int timeout_ms) { + int pidfd = pidfd_open(pid, /*flags=*/0); + if (pidfd < 0) { + PLOG(ERROR) << "pidfd_open failed for pid " << pid; + kill(pid, SIGKILL); + return wait_child(pid); + } + + struct pollfd pfd; + pfd.fd = pidfd; + pfd.events = POLLIN; + int poll_ret = TEMP_FAILURE_RETRY(poll(&pfd, /*nfds=*/1, timeout_ms)); + + close(pidfd); + + if (poll_ret < 0) { + PLOG(ERROR) << "poll failed for pid " << pid; + kill(pid, SIGKILL); + return wait_child(pid); } + if (poll_ret == 0) { + LOG(WARNING) << "Child process " << pid << " timed out after " << timeout_ms + << "ms. Killing it"; + kill(pid, SIGKILL); + return wait_child(pid); + } + return wait_child(pid); } /** @@ -1295,5 +1313,27 @@ void drop_capabilities(uid_t uid) { } } +bool remove_file_at_fd(int fd, /*out*/ std::string* path) { + char path_buffer[PATH_MAX + 1]; + std::string proc_path = android::base::StringPrintf("/proc/self/fd/%d", fd); + ssize_t len = readlink(proc_path.c_str(), path_buffer, PATH_MAX); + if (len < 0) { + PLOG(WARNING) << "Could not remove file at fd " << fd << ": Failed to get file path"; + return false; + } + path_buffer[len] = '\0'; + if (path != nullptr) { + *path = path_buffer; + } + if (unlink(path_buffer) != 0) { + if (errno == ENOENT) { + return true; + } + PLOG(WARNING) << "Could not remove file at path " << path_buffer; + return false; + } + return true; +} + } // namespace installd } // namespace android -- cgit v1.2.3-59-g8ed1b