xref: /aosp_15_r20/frameworks/base/libs/androidfw/PosixUtils.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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