1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "UtilsHost.h"
18 
19 #include <poll.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 
24 #include <sstream>
25 
26 #include <log/log.h>
27 
28 #include "FdUtils.h"
29 #include "Utils.h"
30 
31 namespace android {
32 
33 using android::binder::unique_fd;
34 
~CommandResult()35 CommandResult::~CommandResult() {
36     if (!pid.has_value()) return;
37     if (*pid == 0) {
38         ALOGW("%s: PID is unexpectedly 0, won't kill it", __PRETTY_FUNCTION__);
39         return;
40     }
41 
42     ALOGE_IF(kill(*pid, SIGKILL) != 0, "kill(%d): %s", *pid, strerror(errno));
43 
44     while (pid.has_value()) {
45         int status;
46         LOG_HOST("%s: Waiting for PID %d to exit.", __PRETTY_FUNCTION__, *pid);
47         int waitres = waitpid(*pid, &status, 0);
48         if (waitres == -1) {
49             ALOGE("%s: waitpid(%d): %s", __PRETTY_FUNCTION__, *pid, strerror(errno));
50             break;
51         }
52         if (WIFEXITED(status)) {
53             LOG_HOST("%s: PID %d exited.", __PRETTY_FUNCTION__, *pid);
54             pid.reset();
55         } else if (WIFSIGNALED(status)) {
56             LOG_HOST("%s: PID %d terminated by signal %d.", __PRETTY_FUNCTION__, *pid,
57                      WTERMSIG(status));
58             pid.reset();
59         } else if (WIFSTOPPED(status)) {
60             ALOGW("%s: pid %d stopped", __PRETTY_FUNCTION__, *pid);
61         } else if (WIFCONTINUED(status)) {
62             ALOGW("%s: pid %d continued", __PRETTY_FUNCTION__, *pid);
63         }
64     }
65 }
66 
operator <<(std::ostream & os,const CommandResult & res)67 std::ostream& operator<<(std::ostream& os, const CommandResult& res) {
68     if (res.exitCode) os << "code=" << *res.exitCode;
69     if (res.signal) os << "signal=" << *res.signal;
70     if (res.pid) os << ", pid=" << *res.pid;
71     return os << ", stdout=" << res.stdoutStr << ", stderr=" << res.stderrStr;
72 }
73 
toString() const74 std::string CommandResult::toString() const {
75     std::stringstream ss;
76     ss << (*this);
77     return ss.str();
78 }
79 
execute(std::vector<std::string> argStringVec,const std::function<bool (const CommandResult &)> & end)80 std::optional<CommandResult> execute(std::vector<std::string> argStringVec,
81                                      const std::function<bool(const CommandResult&)>& end) {
82     // turn vector<string> into null-terminated char* vector.
83     std::vector<char*> argv;
84     argv.reserve(argStringVec.size() + 1);
85     for (auto& arg : argStringVec) argv.push_back(arg.data());
86     argv.push_back(nullptr);
87 
88     CommandResult ret;
89     unique_fd outWrite;
90     if (!binder::Pipe(&ret.outPipe, &outWrite)) {
91         PLOGE("pipe() for outPipe");
92         return {};
93     }
94     unique_fd errWrite;
95     if (!binder::Pipe(&ret.errPipe, &errWrite)) {
96         PLOGE("pipe() for errPipe");
97         return {};
98     }
99 
100     int pid = fork();
101     if (pid == -1) {
102         PLOGE("fork()");
103         return {};
104     }
105     if (pid == 0) {
106         // child
107         ret.outPipe.reset();
108         ret.errPipe.reset();
109 
110         int res = TEMP_FAILURE_RETRY(dup2(outWrite.get(), STDOUT_FILENO));
111         LOG_ALWAYS_FATAL_IF(-1 == res, "dup2(outPipe): %s", strerror(errno));
112         outWrite.reset();
113 
114         res = TEMP_FAILURE_RETRY(dup2(errWrite.get(), STDERR_FILENO));
115         LOG_ALWAYS_FATAL_IF(-1 == res, "dup2(errPipe): %s", strerror(errno));
116         errWrite.reset();
117 
118         execvp(argv[0], argv.data());
119         LOG_ALWAYS_FATAL("execvp() returns");
120     }
121     // parent
122     outWrite.reset();
123     errWrite.reset();
124     ret.pid = pid;
125 
126     auto handlePoll = [](unique_fd* fd, const pollfd* pfd, std::string* s) {
127         if (!fd->ok()) return true;
128         if (pfd->revents & POLLIN) {
129             char buf[1024];
130             ssize_t n = TEMP_FAILURE_RETRY(read(fd->get(), buf, sizeof(buf)));
131             if (n < 0) return false;
132             if (n > 0) *s += std::string_view(buf, n);
133         }
134         if (pfd->revents & POLLHUP) {
135             fd->reset();
136         }
137         return true;
138     };
139 
140     // Drain both stdout and stderr. Check end() regularly until both are closed.
141     while (ret.outPipe.ok() || ret.errPipe.ok()) {
142         pollfd fds[2];
143         pollfd *outPollFd = nullptr, *errPollFd = nullptr;
144         memset(fds, 0, sizeof(fds));
145         nfds_t nfds = 0;
146         if (ret.outPipe.ok()) {
147             outPollFd = &fds[nfds++];
148             *outPollFd = {.fd = ret.outPipe.get(), .events = POLLIN};
149         }
150         if (ret.errPipe.ok()) {
151             errPollFd = &fds[nfds++];
152             *errPollFd = {.fd = ret.errPipe.get(), .events = POLLIN};
153         }
154         int pollRet = poll(fds, nfds, 1000 /* ms timeout */);
155         if (pollRet == -1) {
156             PLOGE("poll()");
157             return {};
158         }
159 
160         if (!handlePoll(&ret.outPipe, outPollFd, &ret.stdoutStr)) {
161             PLOGE("read(stdout)");
162             return {};
163         }
164         if (!handlePoll(&ret.errPipe, errPollFd, &ret.stderrStr)) {
165             PLOGE("read(stderr)");
166             return {};
167         }
168 
169         if (end && end(ret)) return ret;
170     }
171 
172     // If both stdout and stderr are closed by the subprocess, it may or may not be terminated.
173     while (ret.pid.has_value()) {
174         int status;
175         auto exitPid = waitpid(pid, &status, 0);
176         if (exitPid == -1) {
177             PLOGE("waitpid(%d)", pid);
178             return {};
179         }
180         if (exitPid == pid) {
181             if (WIFEXITED(status)) {
182                 ret.pid = std::nullopt;
183                 ret.exitCode = WEXITSTATUS(status);
184             } else if (WIFSIGNALED(status)) {
185                 ret.pid = std::nullopt;
186                 ret.signal = WTERMSIG(status);
187             } else if (WIFSTOPPED(status)) {
188                 ALOGW("%s: pid %d stopped", __PRETTY_FUNCTION__, *ret.pid);
189             } else if (WIFCONTINUED(status)) {
190                 ALOGW("%s: pid %d continued", __PRETTY_FUNCTION__, *ret.pid);
191             }
192         }
193         // ret is not changed unless the process is terminated (where pid == nullopt). Hence there
194         // is no need to check the predicate `end(ret)`.
195     }
196 
197     return ret;
198 }
199 } // namespace android
200