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 <sys/prctl.h> 22 #include <wait.h> 23 24 #include "section_list.h" 25 26 namespace android { 27 namespace os { 28 namespace incidentd { 29 30 using namespace android::base; 31 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 // ================================================================================ 51 Fpipe::Fpipe() : mRead(), mWrite() {} 52 53 Fpipe::~Fpipe() { close(); } 54 55 bool Fpipe::close() { 56 mRead.reset(); 57 mWrite.reset(); 58 return true; 59 } 60 61 bool Fpipe::init() { return Pipe(&mRead, &mWrite); } 62 63 unique_fd& Fpipe::readFd() { return mRead; } 64 65 unique_fd& Fpipe::writeFd() { return mWrite; } 66 67 pid_t fork_execute_cmd(char* const argv[], Fpipe* input, Fpipe* output) { 68 // fork used in multithreaded environment, avoid adding unnecessary code in child process 69 pid_t pid = fork(); 70 if (pid == 0) { 71 if (input != NULL && (TEMP_FAILURE_RETRY(dup2(input->readFd().get(), STDIN_FILENO)) < 0 || 72 !input->close())) { 73 ALOGW("Failed to dup2 stdin."); 74 _exit(EXIT_FAILURE); 75 } 76 if (TEMP_FAILURE_RETRY(dup2(output->writeFd().get(), STDOUT_FILENO)) < 0 || 77 !output->close()) { 78 ALOGW("Failed to dup2 stdout."); 79 _exit(EXIT_FAILURE); 80 } 81 /* make sure the child dies when incidentd dies */ 82 prctl(PR_SET_PDEATHSIG, SIGKILL); 83 execvp(argv[0], argv); 84 _exit(errno); // always exits with failure if any 85 } 86 // close the fds used in child process. 87 if (input != NULL) input->readFd().reset(); 88 output->writeFd().reset(); 89 return pid; 90 } 91 92 // ================================================================================ 93 const char** varargs(const char* first, va_list rest) { 94 va_list copied_rest; 95 int numOfArgs = 1; // first is already count. 96 97 va_copy(copied_rest, rest); 98 while (va_arg(copied_rest, const char*) != NULL) { 99 numOfArgs++; 100 } 101 va_end(copied_rest); 102 103 // allocate extra 1 for NULL terminator 104 const char** ret = (const char**)malloc(sizeof(const char*) * (numOfArgs + 1)); 105 ret[0] = first; 106 for (int i = 1; i < numOfArgs; i++) { 107 const char* arg = va_arg(rest, const char*); 108 ret[i] = arg; 109 } 110 ret[numOfArgs] = NULL; 111 return ret; 112 } 113 114 // ================================================================================ 115 const uint64_t NANOS_PER_SEC = 1000000000; 116 uint64_t Nanotime() { 117 timespec ts; 118 clock_gettime(CLOCK_MONOTONIC, &ts); 119 return static_cast<uint64_t>(ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec); 120 } 121 122 // ================================================================================ 123 const int WAIT_MAX = 5; 124 const struct timespec WAIT_INTERVAL_NS = {0, 200 * 1000 * 1000}; 125 126 static status_t statusCode(int status) { 127 if (WIFSIGNALED(status)) { 128 VLOG("return by signal: %s", strerror(WTERMSIG(status))); 129 return -WTERMSIG(status); 130 } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { 131 VLOG("return by exit: %s", strerror(WEXITSTATUS(status))); 132 return -WEXITSTATUS(status); 133 } 134 return NO_ERROR; 135 } 136 137 status_t kill_child(pid_t pid) { 138 int status; 139 VLOG("try to kill child process %d", pid); 140 kill(pid, SIGKILL); 141 if (waitpid(pid, &status, 0) == -1) return -1; 142 return statusCode(status); 143 } 144 145 status_t wait_child(pid_t pid) { 146 int status; 147 bool died = false; 148 // wait for child to report status up to 1 seconds 149 for (int loop = 0; !died && loop < WAIT_MAX; loop++) { 150 if (waitpid(pid, &status, WNOHANG) == pid) died = true; 151 // sleep for 0.2 second 152 nanosleep(&WAIT_INTERVAL_NS, NULL); 153 } 154 if (!died) return kill_child(pid); 155 return statusCode(status); 156 } 157 158 } // namespace incidentd 159 } // namespace os 160 } // namespace android 161