blob: 2649fb975792e5803f4253aadc945aaf553074fe [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 Mab6f7c472020-03-03 17:58:35 -080021#include <fcntl.h>
Yi Jin1a11fa12018-02-22 16:44:10 -080022#include <sys/prctl.h>
Yi Jinc36e91d2018-03-08 11:25:58 -080023#include <wait.h>
Yi Jin1a11fa12018-02-22 16:44:10 -080024
Yi Jinb592e3b2018-02-01 15:17:04 -080025#include "section_list.h"
26
Yi Jin6cacbcb2018-03-30 14:04:52 -070027namespace android {
28namespace os {
29namespace incidentd {
30
31using namespace android::base;
32
Yi Jinb592e3b2018-02-01 15:17:04 -080033const Privacy* get_privacy_of_section(int id) {
34 int l = 0;
35 int r = PRIVACY_POLICY_COUNT - 1;
36 while (l <= r) {
37 int mid = (l + r) >> 1;
38 const Privacy* p = PRIVACY_POLICY_LIST[mid];
39
40 if (p->field_id < (uint32_t)id) {
41 l = mid + 1;
42 } else if (p->field_id > (uint32_t)id) {
43 r = mid - 1;
44 } else {
45 return p;
46 }
47 }
48 return NULL;
49}
50
51// ================================================================================
52Fpipe::Fpipe() : mRead(), mWrite() {}
53
54Fpipe::~Fpipe() { close(); }
55
56bool Fpipe::close() {
57 mRead.reset();
58 mWrite.reset();
59 return true;
60}
61
62bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
63
Yi Jin6355d2f2018-03-14 15:18:02 -070064unique_fd& Fpipe::readFd() { return mRead; }
Yi Jinb592e3b2018-02-01 15:17:04 -080065
Yi Jin6355d2f2018-03-14 15:18:02 -070066unique_fd& Fpipe::writeFd() { return mWrite; }
Yi Jin1a11fa12018-02-22 16:44:10 -080067
Mike Mab6f7c472020-03-03 17:58:35 -080068pid_t fork_execute_cmd(char* const argv[], Fpipe* input, Fpipe* output, int* status) {
69 int in = -1;
70 if (input != nullptr) {
71 in = input->readFd().release();
72 // Auto close write end of the input pipe on exec to prevent leaking fd in child process
73 fcntl(input->writeFd().get(), F_SETFD, FD_CLOEXEC);
74 }
75 int out = output->writeFd().release();
76 // Auto close read end of the output pipe on exec
77 fcntl(output->readFd().get(), F_SETFD, FD_CLOEXEC);
78 return fork_execute_cmd(argv, in, out, status);
79}
80
81pid_t fork_execute_cmd(char* const argv[], int in, int out, int* status) {
82 int dummy_status = 0;
83 if (status == nullptr) {
84 status = &dummy_status;
85 }
86 *status = 0;
Yi Jin1a11fa12018-02-22 16:44:10 -080087 pid_t pid = fork();
Mike Mab6f7c472020-03-03 17:58:35 -080088 if (pid < 0) {
89 *status = -errno;
90 return -1;
91 }
Yi Jin1a11fa12018-02-22 16:44:10 -080092 if (pid == 0) {
Mike Mab6f7c472020-03-03 17:58:35 -080093 // In child
94 if (in >= 0 && (TEMP_FAILURE_RETRY(dup2(in, STDIN_FILENO)) < 0 || close(in))) {
Yi Jinc36e91d2018-03-08 11:25:58 -080095 ALOGW("Failed to dup2 stdin.");
Yi Jin1a11fa12018-02-22 16:44:10 -080096 _exit(EXIT_FAILURE);
97 }
Mike Mab6f7c472020-03-03 17:58:35 -080098 if (TEMP_FAILURE_RETRY(dup2(out, STDOUT_FILENO)) < 0 || close(out)) {
Yi Jinc36e91d2018-03-08 11:25:58 -080099 ALOGW("Failed to dup2 stdout.");
100 _exit(EXIT_FAILURE);
101 }
Mike Mab6f7c472020-03-03 17:58:35 -0800102 // Make sure the child dies when incidentd dies
Yi Jin1a11fa12018-02-22 16:44:10 -0800103 prctl(PR_SET_PDEATHSIG, SIGKILL);
Yi Jinc36e91d2018-03-08 11:25:58 -0800104 execvp(argv[0], argv);
105 _exit(errno); // always exits with failure if any
Yi Jin1a11fa12018-02-22 16:44:10 -0800106 }
Mike Mab6f7c472020-03-03 17:58:35 -0800107 // In parent
108 if ((in >= 0 && close(in) < 0) || close(out) < 0) {
109 ALOGW("Failed to close pd. Killing child process");
110 *status = -errno;
111 kill_child(pid);
112 return -1;
113 }
Yi Jin1a11fa12018-02-22 16:44:10 -0800114 return pid;
115}
Kweku Adamseadd1232018-02-05 16:45:13 -0800116
Yi Jin1a11fa12018-02-22 16:44:10 -0800117// ================================================================================
118const char** varargs(const char* first, va_list rest) {
119 va_list copied_rest;
120 int numOfArgs = 1; // first is already count.
121
122 va_copy(copied_rest, rest);
123 while (va_arg(copied_rest, const char*) != NULL) {
124 numOfArgs++;
125 }
126 va_end(copied_rest);
127
128 // allocate extra 1 for NULL terminator
129 const char** ret = (const char**)malloc(sizeof(const char*) * (numOfArgs + 1));
130 ret[0] = first;
Yi Jin06ebd1a2018-02-28 11:25:58 -0800131 for (int i = 1; i < numOfArgs; i++) {
Yi Jin1a11fa12018-02-22 16:44:10 -0800132 const char* arg = va_arg(rest, const char*);
Yi Jin06ebd1a2018-02-28 11:25:58 -0800133 ret[i] = arg;
Yi Jin1a11fa12018-02-22 16:44:10 -0800134 }
Yi Jin06ebd1a2018-02-28 11:25:58 -0800135 ret[numOfArgs] = NULL;
Yi Jin1a11fa12018-02-22 16:44:10 -0800136 return ret;
137}
Kweku Adamseadd1232018-02-05 16:45:13 -0800138
139// ================================================================================
140const uint64_t NANOS_PER_SEC = 1000000000;
141uint64_t Nanotime() {
142 timespec ts;
143 clock_gettime(CLOCK_MONOTONIC, &ts);
144 return static_cast<uint64_t>(ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec);
145}
Yi Jinc36e91d2018-03-08 11:25:58 -0800146
147// ================================================================================
Yi Jinc36e91d2018-03-08 11:25:58 -0800148static status_t statusCode(int status) {
149 if (WIFSIGNALED(status)) {
150 VLOG("return by signal: %s", strerror(WTERMSIG(status)));
151 return -WTERMSIG(status);
152 } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
153 VLOG("return by exit: %s", strerror(WEXITSTATUS(status)));
154 return -WEXITSTATUS(status);
155 }
156 return NO_ERROR;
157}
158
Mike Mab6f7c472020-03-03 17:58:35 -0800159static bool waitpid_with_timeout(pid_t pid, int timeout_ms, int* status) {
160 sigset_t child_mask, old_mask;
161 sigemptyset(&child_mask);
162 sigaddset(&child_mask, SIGCHLD);
163
164 if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
165 ALOGW("sigprocmask failed: %s", strerror(errno));
166 return false;
167 }
168
169 timespec ts;
170 ts.tv_sec = timeout_ms / 1000;
171 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
172 int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
173 int saved_errno = errno;
174
175 // Set the signals back the way they were.
176 if (sigprocmask(SIG_SETMASK, &old_mask, nullptr) == -1) {
177 ALOGW("sigprocmask failed: %s", strerror(errno));
178 if (ret == 0) {
179 return false;
180 }
181 }
182 if (ret == -1) {
183 errno = saved_errno;
184 if (errno == EAGAIN) {
185 errno = ETIMEDOUT;
186 } else {
187 ALOGW("sigtimedwait failed: %s", strerror(errno));
188 }
189 return false;
190 }
191
192 pid_t child_pid = waitpid(pid, status, WNOHANG);
193 if (child_pid == pid) {
194 return true;
195 }
196 if (child_pid == -1) {
197 ALOGW("waitpid failed: %s", strerror(errno));
198 } else {
199 ALOGW("Waiting for pid %d, got pid %d instead", pid, child_pid);
200 }
201 return false;
202}
203
Yi Jinc36e91d2018-03-08 11:25:58 -0800204status_t kill_child(pid_t pid) {
205 int status;
Yi Jinc36e91d2018-03-08 11:25:58 -0800206 kill(pid, SIGKILL);
207 if (waitpid(pid, &status, 0) == -1) return -1;
208 return statusCode(status);
209}
210
Mike Mab6f7c472020-03-03 17:58:35 -0800211status_t wait_child(pid_t pid, int timeout_ms) {
Yi Jinc36e91d2018-03-08 11:25:58 -0800212 int status;
Mike Mab6f7c472020-03-03 17:58:35 -0800213 if (waitpid_with_timeout(pid, timeout_ms, &status)) {
214 return statusCode(status);
Yi Jinc36e91d2018-03-08 11:25:58 -0800215 }
Mike Mab6f7c472020-03-03 17:58:35 -0800216 return kill_child(pid);
Yi Jinc36e91d2018-03-08 11:25:58 -0800217}
Yi Jin6cacbcb2018-03-30 14:04:52 -0700218
219} // namespace incidentd
220} // namespace os
Joe Onorato99598ee2019-02-11 15:55:13 +0000221} // namespace android