blob: ec0b79b34c0228f8e44398fc667de97d8fb3941b [file] [log] [blame]
Yi Jinb592e3b2018-02-01 15:17:04 -08001/*
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 */
Yi Jin1a11fa12018-02-22 16:44:10 -080016#define DEBUG false
17#include "Log.h"
18
Yi Jinb592e3b2018-02-01 15:17:04 -080019#include "incidentd_util.h"
20
Mike Ma892ccd92020-03-20 16:30:37 -070021#include <android/util/EncodedBuffer.h>
Mike Mab6f7c472020-03-03 17:58:35 -080022#include <fcntl.h>
Yi Jin1a11fa12018-02-22 16:44:10 -080023#include <sys/prctl.h>
Yi Jinc36e91d2018-03-08 11:25:58 -080024#include <wait.h>
Yi Jin1a11fa12018-02-22 16:44:10 -080025
Yi Jinb592e3b2018-02-01 15:17:04 -080026#include "section_list.h"
27
Yi Jin6cacbcb2018-03-30 14:04:52 -070028namespace android {
29namespace os {
30namespace incidentd {
31
Yi Jinb592e3b2018-02-01 15:17:04 -080032const 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
Mike Ma892ccd92020-03-20 16:30:37 -070050std::vector<sp<EncodedBuffer>> gBufferPool;
51std::mutex gBufferPoolLock;
52
53sp<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
63void 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
69void clear_buffer_pool() {
70 std::scoped_lock<std::mutex> lock(gBufferPoolLock);
71 gBufferPool.clear();
72}
73
Yi Jinb592e3b2018-02-01 15:17:04 -080074// ================================================================================
75Fpipe::Fpipe() : mRead(), mWrite() {}
76
77Fpipe::~Fpipe() { close(); }
78
79bool Fpipe::close() {
80 mRead.reset();
81 mWrite.reset();
82 return true;
83}
84
85bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
86
Yi Jin6355d2f2018-03-14 15:18:02 -070087unique_fd& Fpipe::readFd() { return mRead; }
Yi Jinb592e3b2018-02-01 15:17:04 -080088
Yi Jin6355d2f2018-03-14 15:18:02 -070089unique_fd& Fpipe::writeFd() { return mWrite; }
Yi Jin1a11fa12018-02-22 16:44:10 -080090
Mike Mab6f7c472020-03-03 17:58:35 -080091pid_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
104pid_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;
Mike Ma892ccd92020-03-20 16:30:37 -0700110 pid_t pid = vfork();
Mike Mab6f7c472020-03-03 17:58:35 -0800111 if (pid < 0) {
112 *status = -errno;
113 return -1;
114 }
Yi Jin1a11fa12018-02-22 16:44:10 -0800115 if (pid == 0) {
Mike Mab6f7c472020-03-03 17:58:35 -0800116 // In child
117 if (in >= 0 && (TEMP_FAILURE_RETRY(dup2(in, STDIN_FILENO)) < 0 || close(in))) {
Yi Jinc36e91d2018-03-08 11:25:58 -0800118 ALOGW("Failed to dup2 stdin.");
Yi Jin1a11fa12018-02-22 16:44:10 -0800119 _exit(EXIT_FAILURE);
120 }
Mike Mab6f7c472020-03-03 17:58:35 -0800121 if (TEMP_FAILURE_RETRY(dup2(out, STDOUT_FILENO)) < 0 || close(out)) {
Yi Jinc36e91d2018-03-08 11:25:58 -0800122 ALOGW("Failed to dup2 stdout.");
123 _exit(EXIT_FAILURE);
124 }
Mike Mab6f7c472020-03-03 17:58:35 -0800125 // Make sure the child dies when incidentd dies
Yi Jin1a11fa12018-02-22 16:44:10 -0800126 prctl(PR_SET_PDEATHSIG, SIGKILL);
Yi Jinc36e91d2018-03-08 11:25:58 -0800127 execvp(argv[0], argv);
128 _exit(errno); // always exits with failure if any
Yi Jin1a11fa12018-02-22 16:44:10 -0800129 }
Mike Mab6f7c472020-03-03 17:58:35 -0800130 // 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 }
Yi Jin1a11fa12018-02-22 16:44:10 -0800137 return pid;
138}
Kweku Adamseadd1232018-02-05 16:45:13 -0800139
Yi Jin1a11fa12018-02-22 16:44:10 -0800140// ================================================================================
141const 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;
Yi Jin06ebd1a2018-02-28 11:25:58 -0800154 for (int i = 1; i < numOfArgs; i++) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800155 const char* arg = va_arg(rest, const char*);
Yi Jin06ebd1a2018-02-28 11:25:58 -0800156 ret[i] = arg;
Yi Jin1a11fa12018-02-22 16:44:10 -0800157 }
Yi Jin06ebd1a2018-02-28 11:25:58 -0800158 ret[numOfArgs] = NULL;
Yi Jin1a11fa12018-02-22 16:44:10 -0800159 return ret;
160}
Kweku Adamseadd1232018-02-05 16:45:13 -0800161
162// ================================================================================
163const uint64_t NANOS_PER_SEC = 1000000000;
164uint64_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}
Yi Jinc36e91d2018-03-08 11:25:58 -0800169
170// ================================================================================
Yi Jinc36e91d2018-03-08 11:25:58 -0800171static 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
Mike Mab6f7c472020-03-03 17:58:35 -0800182static 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
Tim Murray1f3012d2022-02-17 12:36:33 -0800187 // block SIGCHLD before we check if a process has exited
Mike Mab6f7c472020-03-03 17:58:35 -0800188 if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
Tim Murray1f3012d2022-02-17 12:36:33 -0800189 ALOGW("*** sigprocmask failed: %s\n", strerror(errno));
Mike Mab6f7c472020-03-03 17:58:35 -0800190 return false;
191 }
192
Tim Murray1f3012d2022-02-17 12:36:33 -0800193 // 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
Mike Mab6f7c472020-03-03 17:58:35 -0800207 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) {
Tim Murray1f3012d2022-02-17 12:36:33 -0800215 ALOGW("*** sigprocmask failed: %s\n", strerror(errno));
Mike Mab6f7c472020-03-03 17:58:35 -0800216 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 {
Tim Murray1f3012d2022-02-17 12:36:33 -0800225 ALOGW("*** sigtimedwait failed: %s\n", strerror(errno));
Mike Mab6f7c472020-03-03 17:58:35 -0800226 }
227 return false;
228 }
229
Tim Murray1f3012d2022-02-17 12:36:33 -0800230 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;
Mike Mab6f7c472020-03-03 17:58:35 -0800238 }
Tim Murray1f3012d2022-02-17 12:36:33 -0800239 return true;
Mike Mab6f7c472020-03-03 17:58:35 -0800240}
241
Yi Jinc36e91d2018-03-08 11:25:58 -0800242status_t kill_child(pid_t pid) {
243 int status;
Yi Jinc36e91d2018-03-08 11:25:58 -0800244 kill(pid, SIGKILL);
245 if (waitpid(pid, &status, 0) == -1) return -1;
246 return statusCode(status);
247}
248
Mike Mab6f7c472020-03-03 17:58:35 -0800249status_t wait_child(pid_t pid, int timeout_ms) {
Yi Jinc36e91d2018-03-08 11:25:58 -0800250 int status;
Mike Mab6f7c472020-03-03 17:58:35 -0800251 if (waitpid_with_timeout(pid, timeout_ms, &status)) {
252 return statusCode(status);
Yi Jinc36e91d2018-03-08 11:25:58 -0800253 }
Mike Mab6f7c472020-03-03 17:58:35 -0800254 return kill_child(pid);
Yi Jinc36e91d2018-03-08 11:25:58 -0800255}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700256
257} // namespace incidentd
258} // namespace os
Joe Onorato99598ee2019-02-11 15:55:13 +0000259} // namespace android