1 /* 2 * Copyright (C) 2018 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 #ifdef _WIN32 18 // nothing to see here 19 #else 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include <sys/types.h> 25 #include <sys/wait.h> 26 #include <unistd.h> 27 28 #include "android-base/logging.h" 29 30 #include "androidfw/PosixUtils.h" 31 32 namespace { 33 34 std::unique_ptr<std::string> ReadFile(int fd) { 35 std::unique_ptr<std::string> str(new std::string()); 36 char buf[1024]; 37 ssize_t r; 38 while ((r = read(fd, buf, sizeof(buf))) > 0) { 39 str->append(buf, r); 40 } 41 if (r != 0) { 42 return nullptr; 43 } 44 return str; 45 } 46 47 } 48 49 namespace android { 50 namespace util { 51 52 std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv) { 53 int stdout[2]; // stdout[0] read, stdout[1] write 54 if (pipe(stdout) != 0) { 55 PLOG(ERROR) << "pipe"; 56 return nullptr; 57 } 58 59 int stderr[2]; // stdout[0] read, stdout[1] write 60 if (pipe(stderr) != 0) { 61 PLOG(ERROR) << "pipe"; 62 close(stdout[0]); 63 close(stdout[1]); 64 return nullptr; 65 } 66 67 auto gid = getgid(); 68 auto uid = getuid(); 69 70 char const** argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1)); 71 for (size_t i = 0; i < argv.size(); i++) { 72 argv0[i] = argv[i].c_str(); 73 } 74 argv0[argv.size()] = nullptr; 75 int pid = fork(); 76 switch (pid) { 77 case -1: // error 78 free(argv0); 79 PLOG(ERROR) << "fork"; 80 return nullptr; 81 case 0: // child 82 if (setgid(gid) != 0) { 83 PLOG(ERROR) << "setgid"; 84 exit(1); 85 } 86 87 if (setuid(uid) != 0) { 88 PLOG(ERROR) << "setuid"; 89 exit(1); 90 } 91 92 close(stdout[0]); 93 if (dup2(stdout[1], STDOUT_FILENO) == -1) { 94 abort(); 95 } 96 close(stderr[0]); 97 if (dup2(stderr[1], STDERR_FILENO) == -1) { 98 abort(); 99 } 100 execvp(argv0[0], const_cast<char* const*>(argv0)); 101 PLOG(ERROR) << "execv"; 102 abort(); 103 default: // parent 104 free(argv0); 105 close(stdout[1]); 106 close(stderr[1]); 107 int status; 108 waitpid(pid, &status, 0); 109 if (!WIFEXITED(status)) { 110 close(stdout[0]); 111 close(stderr[0]); 112 return nullptr; 113 } 114 std::unique_ptr<ProcResult> result(new ProcResult()); 115 result->status = status; 116 const auto out = ReadFile(stdout[0]); 117 result->stdout = out ? *out : ""; 118 close(stdout[0]); 119 const auto err = ReadFile(stderr[0]); 120 result->stderr = err ? *err : ""; 121 close(stderr[0]); 122 return result; 123 } 124 } 125 126 } // namespace util 127 } // namespace android 128 #endif 129