1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #ifdef _WIN32
18*d57664e9SAndroid Build Coastguard Worker // nothing to see here
19*d57664e9SAndroid Build Coastguard Worker #else
20*d57664e9SAndroid Build Coastguard Worker #include <optional>
21*d57664e9SAndroid Build Coastguard Worker #include <string>
22*d57664e9SAndroid Build Coastguard Worker #include <vector>
23*d57664e9SAndroid Build Coastguard Worker
24*d57664e9SAndroid Build Coastguard Worker #include <sys/types.h>
25*d57664e9SAndroid Build Coastguard Worker #include <sys/wait.h>
26*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
27*d57664e9SAndroid Build Coastguard Worker
28*d57664e9SAndroid Build Coastguard Worker #include "android-base/logging.h"
29*d57664e9SAndroid Build Coastguard Worker
30*d57664e9SAndroid Build Coastguard Worker #include "androidfw/PosixUtils.h"
31*d57664e9SAndroid Build Coastguard Worker
ReadFile(int fd)32*d57664e9SAndroid Build Coastguard Worker static std::optional<std::string> ReadFile(int fd) {
33*d57664e9SAndroid Build Coastguard Worker std::string str;
34*d57664e9SAndroid Build Coastguard Worker char buf[1024];
35*d57664e9SAndroid Build Coastguard Worker ssize_t r;
36*d57664e9SAndroid Build Coastguard Worker while ((r = read(fd, buf, sizeof(buf))) > 0) {
37*d57664e9SAndroid Build Coastguard Worker str.append(buf, r);
38*d57664e9SAndroid Build Coastguard Worker }
39*d57664e9SAndroid Build Coastguard Worker if (r != 0) {
40*d57664e9SAndroid Build Coastguard Worker return std::nullopt;
41*d57664e9SAndroid Build Coastguard Worker }
42*d57664e9SAndroid Build Coastguard Worker return std::move(str);
43*d57664e9SAndroid Build Coastguard Worker }
44*d57664e9SAndroid Build Coastguard Worker
45*d57664e9SAndroid Build Coastguard Worker namespace android {
46*d57664e9SAndroid Build Coastguard Worker namespace util {
47*d57664e9SAndroid Build Coastguard Worker
ExecuteBinary(const std::vector<std::string> & argv)48*d57664e9SAndroid Build Coastguard Worker ProcResult ExecuteBinary(const std::vector<std::string>& argv) {
49*d57664e9SAndroid Build Coastguard Worker int stdout[2]; // [0] read, [1] write
50*d57664e9SAndroid Build Coastguard Worker if (pipe(stdout) != 0) {
51*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "out pipe";
52*d57664e9SAndroid Build Coastguard Worker return ProcResult{-1};
53*d57664e9SAndroid Build Coastguard Worker }
54*d57664e9SAndroid Build Coastguard Worker
55*d57664e9SAndroid Build Coastguard Worker int stderr[2]; // [0] read, [1] write
56*d57664e9SAndroid Build Coastguard Worker if (pipe(stderr) != 0) {
57*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "err pipe";
58*d57664e9SAndroid Build Coastguard Worker close(stdout[0]);
59*d57664e9SAndroid Build Coastguard Worker close(stdout[1]);
60*d57664e9SAndroid Build Coastguard Worker return ProcResult{-1};
61*d57664e9SAndroid Build Coastguard Worker }
62*d57664e9SAndroid Build Coastguard Worker
63*d57664e9SAndroid Build Coastguard Worker auto gid = getgid();
64*d57664e9SAndroid Build Coastguard Worker auto uid = getuid();
65*d57664e9SAndroid Build Coastguard Worker
66*d57664e9SAndroid Build Coastguard Worker // better keep no C++ objects going into the child here
67*d57664e9SAndroid Build Coastguard Worker auto argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1));
68*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < argv.size(); i++) {
69*d57664e9SAndroid Build Coastguard Worker argv0[i] = argv[i].c_str();
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker argv0[argv.size()] = nullptr;
72*d57664e9SAndroid Build Coastguard Worker int pid = fork();
73*d57664e9SAndroid Build Coastguard Worker switch (pid) {
74*d57664e9SAndroid Build Coastguard Worker case -1: // error
75*d57664e9SAndroid Build Coastguard Worker free(argv0);
76*d57664e9SAndroid Build Coastguard Worker close(stdout[0]);
77*d57664e9SAndroid Build Coastguard Worker close(stdout[1]);
78*d57664e9SAndroid Build Coastguard Worker close(stderr[0]);
79*d57664e9SAndroid Build Coastguard Worker close(stderr[1]);
80*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "fork";
81*d57664e9SAndroid Build Coastguard Worker return ProcResult{-1};
82*d57664e9SAndroid Build Coastguard Worker case 0: // child
83*d57664e9SAndroid Build Coastguard Worker if (setgid(gid) != 0) {
84*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "setgid";
85*d57664e9SAndroid Build Coastguard Worker exit(1);
86*d57664e9SAndroid Build Coastguard Worker }
87*d57664e9SAndroid Build Coastguard Worker
88*d57664e9SAndroid Build Coastguard Worker if (setuid(uid) != 0) {
89*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "setuid";
90*d57664e9SAndroid Build Coastguard Worker exit(1);
91*d57664e9SAndroid Build Coastguard Worker }
92*d57664e9SAndroid Build Coastguard Worker
93*d57664e9SAndroid Build Coastguard Worker close(stdout[0]);
94*d57664e9SAndroid Build Coastguard Worker if (dup2(stdout[1], STDOUT_FILENO) == -1) {
95*d57664e9SAndroid Build Coastguard Worker abort();
96*d57664e9SAndroid Build Coastguard Worker }
97*d57664e9SAndroid Build Coastguard Worker close(stderr[0]);
98*d57664e9SAndroid Build Coastguard Worker if (dup2(stderr[1], STDERR_FILENO) == -1) {
99*d57664e9SAndroid Build Coastguard Worker abort();
100*d57664e9SAndroid Build Coastguard Worker }
101*d57664e9SAndroid Build Coastguard Worker execvp(argv0[0], const_cast<char* const*>(argv0));
102*d57664e9SAndroid Build Coastguard Worker PLOG(ERROR) << "execv";
103*d57664e9SAndroid Build Coastguard Worker abort();
104*d57664e9SAndroid Build Coastguard Worker default: // parent
105*d57664e9SAndroid Build Coastguard Worker free(argv0);
106*d57664e9SAndroid Build Coastguard Worker close(stdout[1]);
107*d57664e9SAndroid Build Coastguard Worker close(stderr[1]);
108*d57664e9SAndroid Build Coastguard Worker int status;
109*d57664e9SAndroid Build Coastguard Worker waitpid(pid, &status, 0);
110*d57664e9SAndroid Build Coastguard Worker if (!WIFEXITED(status)) {
111*d57664e9SAndroid Build Coastguard Worker close(stdout[0]);
112*d57664e9SAndroid Build Coastguard Worker close(stderr[0]);
113*d57664e9SAndroid Build Coastguard Worker return ProcResult{-1};
114*d57664e9SAndroid Build Coastguard Worker }
115*d57664e9SAndroid Build Coastguard Worker ProcResult result(status);
116*d57664e9SAndroid Build Coastguard Worker auto out = ReadFile(stdout[0]);
117*d57664e9SAndroid Build Coastguard Worker result.stdout_str = out ? std::move(*out) : "";
118*d57664e9SAndroid Build Coastguard Worker close(stdout[0]);
119*d57664e9SAndroid Build Coastguard Worker auto err = ReadFile(stderr[0]);
120*d57664e9SAndroid Build Coastguard Worker result.stderr_str = err ? std::move(*err) : "";
121*d57664e9SAndroid Build Coastguard Worker close(stderr[0]);
122*d57664e9SAndroid Build Coastguard Worker return result;
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker }
125*d57664e9SAndroid Build Coastguard Worker
126*d57664e9SAndroid Build Coastguard Worker } // namespace util
127*d57664e9SAndroid Build Coastguard Worker } // namespace android
128*d57664e9SAndroid Build Coastguard Worker #endif
129