1 /*
2 * Copyright (C) 2017 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 #define DEBUG false
17 #include "Log.h"
18
19 #include "incidentd_util.h"
20
21 #include <android/util/EncodedBuffer.h>
22 #include <fcntl.h>
23 #include <sys/prctl.h>
24 #include <wait.h>
25
26 #include "section_list.h"
27
28 namespace android {
29 namespace os {
30 namespace incidentd {
31
get_privacy_of_section(int id)32 const Privacy* get_privacy_of_section(int id) {
33 int l = 0;
34 int r = PRIVACY_POLICY_COUNT - 1;
35 while (l <= r) {
36 int mid = (l + r) >> 1;
37 const Privacy* p = PRIVACY_POLICY_LIST[mid];
38
39 if (p->field_id < (uint32_t)id) {
40 l = mid + 1;
41 } else if (p->field_id > (uint32_t)id) {
42 r = mid - 1;
43 } else {
44 return p;
45 }
46 }
47 return NULL;
48 }
49
50 std::vector<sp<EncodedBuffer>> gBufferPool;
51 std::mutex gBufferPoolLock;
52
get_buffer_from_pool()53 sp<EncodedBuffer> get_buffer_from_pool() {
54 std::scoped_lock<std::mutex> lock(gBufferPoolLock);
55 if (gBufferPool.size() == 0) {
56 return new EncodedBuffer();
57 }
58 sp<EncodedBuffer> buffer = gBufferPool.back();
59 gBufferPool.pop_back();
60 return buffer;
61 }
62
return_buffer_to_pool(sp<EncodedBuffer> buffer)63 void return_buffer_to_pool(sp<EncodedBuffer> buffer) {
64 buffer->clear();
65 std::scoped_lock<std::mutex> lock(gBufferPoolLock);
66 gBufferPool.push_back(buffer);
67 }
68
clear_buffer_pool()69 void clear_buffer_pool() {
70 std::scoped_lock<std::mutex> lock(gBufferPoolLock);
71 gBufferPool.clear();
72 }
73
74 // ================================================================================
Fpipe()75 Fpipe::Fpipe() : mRead(), mWrite() {}
76
~Fpipe()77 Fpipe::~Fpipe() { close(); }
78
close()79 bool Fpipe::close() {
80 mRead.reset();
81 mWrite.reset();
82 return true;
83 }
84
init()85 bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
86
readFd()87 unique_fd& Fpipe::readFd() { return mRead; }
88
writeFd()89 unique_fd& Fpipe::writeFd() { return mWrite; }
90
fork_execute_cmd(char * const argv[],Fpipe * input,Fpipe * output,int * status)91 pid_t fork_execute_cmd(char* const argv[], Fpipe* input, Fpipe* output, int* status) {
92 int in = -1;
93 if (input != nullptr) {
94 in = input->readFd().release();
95 // Auto close write end of the input pipe on exec to prevent leaking fd in child process
96 fcntl(input->writeFd().get(), F_SETFD, FD_CLOEXEC);
97 }
98 int out = output->writeFd().release();
99 // Auto close read end of the output pipe on exec
100 fcntl(output->readFd().get(), F_SETFD, FD_CLOEXEC);
101 return fork_execute_cmd(argv, in, out, status);
102 }
103
fork_execute_cmd(char * const argv[],int in,int out,int * status)104 pid_t fork_execute_cmd(char* const argv[], int in, int out, int* status) {
105 int dummy_status = 0;
106 if (status == nullptr) {
107 status = &dummy_status;
108 }
109 *status = 0;
110 pid_t pid = vfork();
111 if (pid < 0) {
112 *status = -errno;
113 return -1;
114 }
115 if (pid == 0) {
116 // In child
117 if (in >= 0 && (TEMP_FAILURE_RETRY(dup2(in, STDIN_FILENO)) < 0 || close(in))) {
118 ALOGW("Failed to dup2 stdin.");
119 _exit(EXIT_FAILURE);
120 }
121 if (TEMP_FAILURE_RETRY(dup2(out, STDOUT_FILENO)) < 0 || close(out)) {
122 ALOGW("Failed to dup2 stdout.");
123 _exit(EXIT_FAILURE);
124 }
125 // Make sure the child dies when incidentd dies
126 prctl(PR_SET_PDEATHSIG, SIGKILL);
127 execvp(argv[0], argv);
128 _exit(errno); // always exits with failure if any
129 }
130 // In parent
131 if ((in >= 0 && close(in) < 0) || close(out) < 0) {
132 ALOGW("Failed to close pd. Killing child process");
133 *status = -errno;
134 kill_child(pid);
135 return -1;
136 }
137 return pid;
138 }
139
140 // ================================================================================
varargs(const char * first,va_list rest)141 const char** varargs(const char* first, va_list rest) {
142 va_list copied_rest;
143 int numOfArgs = 1; // first is already count.
144
145 va_copy(copied_rest, rest);
146 while (va_arg(copied_rest, const char*) != NULL) {
147 numOfArgs++;
148 }
149 va_end(copied_rest);
150
151 // allocate extra 1 for NULL terminator
152 const char** ret = (const char**)malloc(sizeof(const char*) * (numOfArgs + 1));
153 ret[0] = first;
154 for (int i = 1; i < numOfArgs; i++) {
155 const char* arg = va_arg(rest, const char*);
156 ret[i] = arg;
157 }
158 ret[numOfArgs] = NULL;
159 return ret;
160 }
161
162 // ================================================================================
163 const uint64_t NANOS_PER_SEC = 1000000000;
Nanotime()164 uint64_t Nanotime() {
165 timespec ts;
166 clock_gettime(CLOCK_MONOTONIC, &ts);
167 return static_cast<uint64_t>(ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec);
168 }
169
170 // ================================================================================
statusCode(int status)171 static status_t statusCode(int status) {
172 if (WIFSIGNALED(status)) {
173 VLOG("return by signal: %s", strerror(WTERMSIG(status)));
174 return -WTERMSIG(status);
175 } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
176 VLOG("return by exit: %s", strerror(WEXITSTATUS(status)));
177 return -WEXITSTATUS(status);
178 }
179 return NO_ERROR;
180 }
181
waitpid_with_timeout(pid_t pid,int timeout_ms,int * status)182 static bool waitpid_with_timeout(pid_t pid, int timeout_ms, int* status) {
183 sigset_t child_mask, old_mask;
184 sigemptyset(&child_mask);
185 sigaddset(&child_mask, SIGCHLD);
186
187 // block SIGCHLD before we check if a process has exited
188 if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
189 ALOGW("*** sigprocmask failed: %s\n", strerror(errno));
190 return false;
191 }
192
193 // if the child has exited already, handle and reset signals before leaving
194 pid_t child_pid = waitpid(pid, status, WNOHANG);
195 if (child_pid != pid) {
196 if (child_pid > 0) {
197 ALOGW("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
198 sigprocmask(SIG_SETMASK, &old_mask, nullptr);
199 return false;
200 }
201 } else {
202 sigprocmask(SIG_SETMASK, &old_mask, nullptr);
203 return true;
204 }
205
206 // wait for a SIGCHLD
207 timespec ts;
208 ts.tv_sec = timeout_ms / 1000;
209 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
210 int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
211 int saved_errno = errno;
212
213 // Set the signals back the way they were.
214 if (sigprocmask(SIG_SETMASK, &old_mask, nullptr) == -1) {
215 ALOGW("*** sigprocmask failed: %s\n", strerror(errno));
216 if (ret == 0) {
217 return false;
218 }
219 }
220 if (ret == -1) {
221 errno = saved_errno;
222 if (errno == EAGAIN) {
223 errno = ETIMEDOUT;
224 } else {
225 ALOGW("*** sigtimedwait failed: %s\n", strerror(errno));
226 }
227 return false;
228 }
229
230 child_pid = waitpid(pid, status, WNOHANG);
231 if (child_pid != pid) {
232 if (child_pid != -1) {
233 ALOGW("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
234 } else {
235 ALOGW("*** waitpid failed: %s\n", strerror(errno));
236 }
237 return false;
238 }
239 return true;
240 }
241
kill_child(pid_t pid)242 status_t kill_child(pid_t pid) {
243 int status;
244 kill(pid, SIGKILL);
245 if (waitpid(pid, &status, 0) == -1) return -1;
246 return statusCode(status);
247 }
248
wait_child(pid_t pid,int timeout_ms)249 status_t wait_child(pid_t pid, int timeout_ms) {
250 int status;
251 if (waitpid_with_timeout(pid, timeout_ms, &status)) {
252 return statusCode(status);
253 }
254 return kill_child(pid);
255 }
256
257 } // namespace incidentd
258 } // namespace os
259 } // namespace android
260