xref: /aosp_15_r20/system/core/init/subcontext.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker  *
4*00c7fec1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*00c7fec1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*00c7fec1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*00c7fec1SAndroid Build Coastguard Worker  *
8*00c7fec1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*00c7fec1SAndroid Build Coastguard Worker  *
10*00c7fec1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*00c7fec1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*00c7fec1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*00c7fec1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*00c7fec1SAndroid Build Coastguard Worker  * limitations under the License.
15*00c7fec1SAndroid Build Coastguard Worker  */
16*00c7fec1SAndroid Build Coastguard Worker 
17*00c7fec1SAndroid Build Coastguard Worker #include "subcontext.h"
18*00c7fec1SAndroid Build Coastguard Worker 
19*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <poll.h>
21*00c7fec1SAndroid Build Coastguard Worker #include <sys/time.h>
22*00c7fec1SAndroid Build Coastguard Worker #include <sys/resource.h>
23*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
24*00c7fec1SAndroid Build Coastguard Worker 
25*00c7fec1SAndroid Build Coastguard Worker #include <android-base/file.h>
26*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
27*00c7fec1SAndroid Build Coastguard Worker #include <android-base/properties.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <android-base/strings.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <selinux/android.h>
30*00c7fec1SAndroid Build Coastguard Worker 
31*00c7fec1SAndroid Build Coastguard Worker #include "action.h"
32*00c7fec1SAndroid Build Coastguard Worker #include "builtins.h"
33*00c7fec1SAndroid Build Coastguard Worker #include "mount_namespace.h"
34*00c7fec1SAndroid Build Coastguard Worker #include "proto_utils.h"
35*00c7fec1SAndroid Build Coastguard Worker #include "util.h"
36*00c7fec1SAndroid Build Coastguard Worker 
37*00c7fec1SAndroid Build Coastguard Worker #ifdef INIT_FULL_SOURCES
38*00c7fec1SAndroid Build Coastguard Worker #include <android/api-level.h>
39*00c7fec1SAndroid Build Coastguard Worker #include "property_service.h"
40*00c7fec1SAndroid Build Coastguard Worker #include "selabel.h"
41*00c7fec1SAndroid Build Coastguard Worker #include "selinux.h"
42*00c7fec1SAndroid Build Coastguard Worker #else
43*00c7fec1SAndroid Build Coastguard Worker #include "host_init_stubs.h"
44*00c7fec1SAndroid Build Coastguard Worker #endif
45*00c7fec1SAndroid Build Coastguard Worker 
46*00c7fec1SAndroid Build Coastguard Worker using android::base::GetExecutablePath;
47*00c7fec1SAndroid Build Coastguard Worker using android::base::GetProperty;
48*00c7fec1SAndroid Build Coastguard Worker using android::base::Join;
49*00c7fec1SAndroid Build Coastguard Worker using android::base::Socketpair;
50*00c7fec1SAndroid Build Coastguard Worker using android::base::Split;
51*00c7fec1SAndroid Build Coastguard Worker using android::base::StartsWith;
52*00c7fec1SAndroid Build Coastguard Worker using android::base::unique_fd;
53*00c7fec1SAndroid Build Coastguard Worker 
54*00c7fec1SAndroid Build Coastguard Worker namespace android {
55*00c7fec1SAndroid Build Coastguard Worker namespace init {
56*00c7fec1SAndroid Build Coastguard Worker namespace {
57*00c7fec1SAndroid Build Coastguard Worker 
58*00c7fec1SAndroid Build Coastguard Worker std::string shutdown_command;
59*00c7fec1SAndroid Build Coastguard Worker static bool subcontext_terminated_by_shutdown;
60*00c7fec1SAndroid Build Coastguard Worker static std::unique_ptr<Subcontext> subcontext;
61*00c7fec1SAndroid Build Coastguard Worker 
62*00c7fec1SAndroid Build Coastguard Worker class SubcontextProcess {
63*00c7fec1SAndroid Build Coastguard Worker   public:
SubcontextProcess(const BuiltinFunctionMap * function_map,std::string context,int init_fd)64*00c7fec1SAndroid Build Coastguard Worker     SubcontextProcess(const BuiltinFunctionMap* function_map, std::string context, int init_fd)
65*00c7fec1SAndroid Build Coastguard Worker         : function_map_(function_map), context_(std::move(context)), init_fd_(init_fd){};
66*00c7fec1SAndroid Build Coastguard Worker     void MainLoop();
67*00c7fec1SAndroid Build Coastguard Worker 
68*00c7fec1SAndroid Build Coastguard Worker   private:
69*00c7fec1SAndroid Build Coastguard Worker     void RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
70*00c7fec1SAndroid Build Coastguard Worker                     SubcontextReply* reply) const;
71*00c7fec1SAndroid Build Coastguard Worker     void ExpandArgs(const SubcontextCommand::ExpandArgsCommand& expand_args_command,
72*00c7fec1SAndroid Build Coastguard Worker                     SubcontextReply* reply) const;
73*00c7fec1SAndroid Build Coastguard Worker 
74*00c7fec1SAndroid Build Coastguard Worker     const BuiltinFunctionMap* function_map_;
75*00c7fec1SAndroid Build Coastguard Worker     const std::string context_;
76*00c7fec1SAndroid Build Coastguard Worker     const int init_fd_;
77*00c7fec1SAndroid Build Coastguard Worker };
78*00c7fec1SAndroid Build Coastguard Worker 
RunCommand(const SubcontextCommand::ExecuteCommand & execute_command,SubcontextReply * reply) const79*00c7fec1SAndroid Build Coastguard Worker void SubcontextProcess::RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
80*00c7fec1SAndroid Build Coastguard Worker                                    SubcontextReply* reply) const {
81*00c7fec1SAndroid Build Coastguard Worker     // Need to use ArraySplice instead of this code.
82*00c7fec1SAndroid Build Coastguard Worker     auto args = std::vector<std::string>();
83*00c7fec1SAndroid Build Coastguard Worker     for (const auto& string : execute_command.args()) {
84*00c7fec1SAndroid Build Coastguard Worker         args.emplace_back(string);
85*00c7fec1SAndroid Build Coastguard Worker     }
86*00c7fec1SAndroid Build Coastguard Worker 
87*00c7fec1SAndroid Build Coastguard Worker     auto map_result = function_map_->Find(args);
88*00c7fec1SAndroid Build Coastguard Worker     Result<void> result;
89*00c7fec1SAndroid Build Coastguard Worker     if (!map_result.ok()) {
90*00c7fec1SAndroid Build Coastguard Worker         result = Error() << "Cannot find command: " << map_result.error();
91*00c7fec1SAndroid Build Coastguard Worker     } else {
92*00c7fec1SAndroid Build Coastguard Worker         result = RunBuiltinFunction(map_result->function, args, context_);
93*00c7fec1SAndroid Build Coastguard Worker     }
94*00c7fec1SAndroid Build Coastguard Worker 
95*00c7fec1SAndroid Build Coastguard Worker     if (result.ok()) {
96*00c7fec1SAndroid Build Coastguard Worker         reply->set_success(true);
97*00c7fec1SAndroid Build Coastguard Worker     } else {
98*00c7fec1SAndroid Build Coastguard Worker         auto* failure = reply->mutable_failure();
99*00c7fec1SAndroid Build Coastguard Worker         failure->set_error_string(result.error().message());
100*00c7fec1SAndroid Build Coastguard Worker         failure->set_error_errno(result.error().code());
101*00c7fec1SAndroid Build Coastguard Worker     }
102*00c7fec1SAndroid Build Coastguard Worker }
103*00c7fec1SAndroid Build Coastguard Worker 
ExpandArgs(const SubcontextCommand::ExpandArgsCommand & expand_args_command,SubcontextReply * reply) const104*00c7fec1SAndroid Build Coastguard Worker void SubcontextProcess::ExpandArgs(const SubcontextCommand::ExpandArgsCommand& expand_args_command,
105*00c7fec1SAndroid Build Coastguard Worker                                    SubcontextReply* reply) const {
106*00c7fec1SAndroid Build Coastguard Worker     for (const auto& arg : expand_args_command.args()) {
107*00c7fec1SAndroid Build Coastguard Worker         auto expanded_arg = ExpandProps(arg);
108*00c7fec1SAndroid Build Coastguard Worker         if (!expanded_arg.ok()) {
109*00c7fec1SAndroid Build Coastguard Worker             auto* failure = reply->mutable_failure();
110*00c7fec1SAndroid Build Coastguard Worker             failure->set_error_string(expanded_arg.error().message());
111*00c7fec1SAndroid Build Coastguard Worker             failure->set_error_errno(0);
112*00c7fec1SAndroid Build Coastguard Worker             return;
113*00c7fec1SAndroid Build Coastguard Worker         } else {
114*00c7fec1SAndroid Build Coastguard Worker             auto* expand_args_reply = reply->mutable_expand_args_reply();
115*00c7fec1SAndroid Build Coastguard Worker             expand_args_reply->add_expanded_args(*expanded_arg);
116*00c7fec1SAndroid Build Coastguard Worker         }
117*00c7fec1SAndroid Build Coastguard Worker     }
118*00c7fec1SAndroid Build Coastguard Worker }
119*00c7fec1SAndroid Build Coastguard Worker 
MainLoop()120*00c7fec1SAndroid Build Coastguard Worker void SubcontextProcess::MainLoop() {
121*00c7fec1SAndroid Build Coastguard Worker     pollfd ufd[1];
122*00c7fec1SAndroid Build Coastguard Worker     ufd[0].events = POLLIN;
123*00c7fec1SAndroid Build Coastguard Worker     ufd[0].fd = init_fd_;
124*00c7fec1SAndroid Build Coastguard Worker 
125*00c7fec1SAndroid Build Coastguard Worker     while (true) {
126*00c7fec1SAndroid Build Coastguard Worker         ufd[0].revents = 0;
127*00c7fec1SAndroid Build Coastguard Worker         int nr = TEMP_FAILURE_RETRY(poll(ufd, arraysize(ufd), -1));
128*00c7fec1SAndroid Build Coastguard Worker         if (nr == 0) continue;
129*00c7fec1SAndroid Build Coastguard Worker         if (nr < 0) {
130*00c7fec1SAndroid Build Coastguard Worker             PLOG(FATAL) << "poll() of subcontext socket failed, continuing";
131*00c7fec1SAndroid Build Coastguard Worker         }
132*00c7fec1SAndroid Build Coastguard Worker 
133*00c7fec1SAndroid Build Coastguard Worker         auto init_message = ReadMessage(init_fd_);
134*00c7fec1SAndroid Build Coastguard Worker         if (!init_message.ok()) {
135*00c7fec1SAndroid Build Coastguard Worker             if (init_message.error().code() == 0) {
136*00c7fec1SAndroid Build Coastguard Worker                 // If the init file descriptor was closed, let's exit quietly. If
137*00c7fec1SAndroid Build Coastguard Worker                 // this was accidental, init will restart us. If init died, this
138*00c7fec1SAndroid Build Coastguard Worker                 // avoids calling abort(3) unnecessarily.
139*00c7fec1SAndroid Build Coastguard Worker                 return;
140*00c7fec1SAndroid Build Coastguard Worker             }
141*00c7fec1SAndroid Build Coastguard Worker             LOG(FATAL) << "Could not read message from init: " << init_message.error();
142*00c7fec1SAndroid Build Coastguard Worker         }
143*00c7fec1SAndroid Build Coastguard Worker 
144*00c7fec1SAndroid Build Coastguard Worker         auto subcontext_command = SubcontextCommand();
145*00c7fec1SAndroid Build Coastguard Worker         if (!subcontext_command.ParseFromString(*init_message)) {
146*00c7fec1SAndroid Build Coastguard Worker             LOG(FATAL) << "Unable to parse message from init";
147*00c7fec1SAndroid Build Coastguard Worker         }
148*00c7fec1SAndroid Build Coastguard Worker 
149*00c7fec1SAndroid Build Coastguard Worker         auto reply = SubcontextReply();
150*00c7fec1SAndroid Build Coastguard Worker         switch (subcontext_command.command_case()) {
151*00c7fec1SAndroid Build Coastguard Worker             case SubcontextCommand::kExecuteCommand: {
152*00c7fec1SAndroid Build Coastguard Worker                 RunCommand(subcontext_command.execute_command(), &reply);
153*00c7fec1SAndroid Build Coastguard Worker                 break;
154*00c7fec1SAndroid Build Coastguard Worker             }
155*00c7fec1SAndroid Build Coastguard Worker             case SubcontextCommand::kExpandArgsCommand: {
156*00c7fec1SAndroid Build Coastguard Worker                 ExpandArgs(subcontext_command.expand_args_command(), &reply);
157*00c7fec1SAndroid Build Coastguard Worker                 break;
158*00c7fec1SAndroid Build Coastguard Worker             }
159*00c7fec1SAndroid Build Coastguard Worker             default:
160*00c7fec1SAndroid Build Coastguard Worker                 LOG(FATAL) << "Unknown message type from init: "
161*00c7fec1SAndroid Build Coastguard Worker                            << subcontext_command.command_case();
162*00c7fec1SAndroid Build Coastguard Worker         }
163*00c7fec1SAndroid Build Coastguard Worker 
164*00c7fec1SAndroid Build Coastguard Worker         if (!shutdown_command.empty()) {
165*00c7fec1SAndroid Build Coastguard Worker             reply.set_trigger_shutdown(shutdown_command);
166*00c7fec1SAndroid Build Coastguard Worker             shutdown_command.clear();
167*00c7fec1SAndroid Build Coastguard Worker         }
168*00c7fec1SAndroid Build Coastguard Worker 
169*00c7fec1SAndroid Build Coastguard Worker         if (auto result = SendMessage(init_fd_, reply); !result.ok()) {
170*00c7fec1SAndroid Build Coastguard Worker             LOG(FATAL) << "Failed to send message to init: " << result.error();
171*00c7fec1SAndroid Build Coastguard Worker         }
172*00c7fec1SAndroid Build Coastguard Worker     }
173*00c7fec1SAndroid Build Coastguard Worker }
174*00c7fec1SAndroid Build Coastguard Worker 
175*00c7fec1SAndroid Build Coastguard Worker }  // namespace
176*00c7fec1SAndroid Build Coastguard Worker 
SubcontextMain(int argc,char ** argv,const BuiltinFunctionMap * function_map)177*00c7fec1SAndroid Build Coastguard Worker int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map) {
178*00c7fec1SAndroid Build Coastguard Worker     if (argc < 4) LOG(FATAL) << "Fewer than 4 args specified to subcontext (" << argc << ")";
179*00c7fec1SAndroid Build Coastguard Worker 
180*00c7fec1SAndroid Build Coastguard Worker     auto context = std::string(argv[2]);
181*00c7fec1SAndroid Build Coastguard Worker     auto init_fd = std::atoi(argv[3]);
182*00c7fec1SAndroid Build Coastguard Worker 
183*00c7fec1SAndroid Build Coastguard Worker     SelabelInitialize();
184*00c7fec1SAndroid Build Coastguard Worker 
185*00c7fec1SAndroid Build Coastguard Worker     trigger_shutdown = [](const std::string& command) { shutdown_command = command; };
186*00c7fec1SAndroid Build Coastguard Worker 
187*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
188*00c7fec1SAndroid Build Coastguard Worker     // Restore prio before main loop
189*00c7fec1SAndroid Build Coastguard Worker     setpriority(PRIO_PROCESS, 0, 0);
190*00c7fec1SAndroid Build Coastguard Worker     subcontext_process.MainLoop();
191*00c7fec1SAndroid Build Coastguard Worker     return 0;
192*00c7fec1SAndroid Build Coastguard Worker }
193*00c7fec1SAndroid Build Coastguard Worker 
Fork()194*00c7fec1SAndroid Build Coastguard Worker void Subcontext::Fork() {
195*00c7fec1SAndroid Build Coastguard Worker     unique_fd subcontext_socket;
196*00c7fec1SAndroid Build Coastguard Worker     if (!Socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, &socket_, &subcontext_socket)) {
197*00c7fec1SAndroid Build Coastguard Worker         LOG(FATAL) << "Could not create socket pair to communicate to subcontext";
198*00c7fec1SAndroid Build Coastguard Worker         return;
199*00c7fec1SAndroid Build Coastguard Worker     }
200*00c7fec1SAndroid Build Coastguard Worker 
201*00c7fec1SAndroid Build Coastguard Worker     auto result = fork();
202*00c7fec1SAndroid Build Coastguard Worker 
203*00c7fec1SAndroid Build Coastguard Worker     if (result == -1) {
204*00c7fec1SAndroid Build Coastguard Worker         LOG(FATAL) << "Could not fork subcontext";
205*00c7fec1SAndroid Build Coastguard Worker     } else if (result == 0) {
206*00c7fec1SAndroid Build Coastguard Worker         socket_.reset();
207*00c7fec1SAndroid Build Coastguard Worker 
208*00c7fec1SAndroid Build Coastguard Worker         // We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
209*00c7fec1SAndroid Build Coastguard Worker         // in the subcontext process after we exec.
210*00c7fec1SAndroid Build Coastguard Worker         int child_fd = dup(subcontext_socket.get());  // NOLINT(android-cloexec-dup)
211*00c7fec1SAndroid Build Coastguard Worker         if (child_fd < 0) {
212*00c7fec1SAndroid Build Coastguard Worker             PLOG(FATAL) << "Could not dup child_fd";
213*00c7fec1SAndroid Build Coastguard Worker         }
214*00c7fec1SAndroid Build Coastguard Worker 
215*00c7fec1SAndroid Build Coastguard Worker         // We don't switch contexts if we're running the unit tests.  We don't use std::optional,
216*00c7fec1SAndroid Build Coastguard Worker         // since we still need a real context string to pass to the builtin functions.
217*00c7fec1SAndroid Build Coastguard Worker         if (context_ != kTestContext) {
218*00c7fec1SAndroid Build Coastguard Worker             if (setexeccon(context_.c_str()) < 0) {
219*00c7fec1SAndroid Build Coastguard Worker                 PLOG(FATAL) << "Could not set execcon for '" << context_ << "'";
220*00c7fec1SAndroid Build Coastguard Worker             }
221*00c7fec1SAndroid Build Coastguard Worker         }
222*00c7fec1SAndroid Build Coastguard Worker #if defined(__ANDROID__)
223*00c7fec1SAndroid Build Coastguard Worker         // subcontext init runs in "default" mount namespace
224*00c7fec1SAndroid Build Coastguard Worker         // so that it can access /apex/*
225*00c7fec1SAndroid Build Coastguard Worker         if (auto result = SwitchToMountNamespaceIfNeeded(NS_DEFAULT); !result.ok()) {
226*00c7fec1SAndroid Build Coastguard Worker             LOG(FATAL) << "Could not switch to \"default\" mount namespace: " << result.error();
227*00c7fec1SAndroid Build Coastguard Worker         }
228*00c7fec1SAndroid Build Coastguard Worker #endif
229*00c7fec1SAndroid Build Coastguard Worker         auto init_path = GetExecutablePath();
230*00c7fec1SAndroid Build Coastguard Worker         auto child_fd_string = std::to_string(child_fd);
231*00c7fec1SAndroid Build Coastguard Worker         const char* args[] = {init_path.c_str(), "subcontext", context_.c_str(),
232*00c7fec1SAndroid Build Coastguard Worker                               child_fd_string.c_str(), nullptr};
233*00c7fec1SAndroid Build Coastguard Worker         execv(init_path.data(), const_cast<char**>(args));
234*00c7fec1SAndroid Build Coastguard Worker 
235*00c7fec1SAndroid Build Coastguard Worker         PLOG(FATAL) << "Could not execv subcontext init";
236*00c7fec1SAndroid Build Coastguard Worker     } else {
237*00c7fec1SAndroid Build Coastguard Worker         subcontext_socket.reset();
238*00c7fec1SAndroid Build Coastguard Worker         pid_ = result;
239*00c7fec1SAndroid Build Coastguard Worker         LOG(INFO) << "Forked subcontext for '" << context_ << "' with pid " << pid_;
240*00c7fec1SAndroid Build Coastguard Worker     }
241*00c7fec1SAndroid Build Coastguard Worker }
242*00c7fec1SAndroid Build Coastguard Worker 
Restart()243*00c7fec1SAndroid Build Coastguard Worker void Subcontext::Restart() {
244*00c7fec1SAndroid Build Coastguard Worker     LOG(ERROR) << "Restarting subcontext '" << context_ << "'";
245*00c7fec1SAndroid Build Coastguard Worker     if (pid_) {
246*00c7fec1SAndroid Build Coastguard Worker         kill(pid_, SIGKILL);
247*00c7fec1SAndroid Build Coastguard Worker     }
248*00c7fec1SAndroid Build Coastguard Worker     pid_ = 0;
249*00c7fec1SAndroid Build Coastguard Worker     socket_.reset();
250*00c7fec1SAndroid Build Coastguard Worker     Fork();
251*00c7fec1SAndroid Build Coastguard Worker }
252*00c7fec1SAndroid Build Coastguard Worker 
PathMatchesSubcontext(const std::string & path) const253*00c7fec1SAndroid Build Coastguard Worker bool Subcontext::PathMatchesSubcontext(const std::string& path) const {
254*00c7fec1SAndroid Build Coastguard Worker     auto apex_name = GetApexNameFromFileName(path);
255*00c7fec1SAndroid Build Coastguard Worker     if (!apex_name.empty()) {
256*00c7fec1SAndroid Build Coastguard Worker         return std::find(apex_list_.begin(), apex_list_.end(), apex_name) != apex_list_.end();
257*00c7fec1SAndroid Build Coastguard Worker     }
258*00c7fec1SAndroid Build Coastguard Worker     for (const auto& prefix : path_prefixes_) {
259*00c7fec1SAndroid Build Coastguard Worker         if (StartsWith(path, prefix)) {
260*00c7fec1SAndroid Build Coastguard Worker             return true;
261*00c7fec1SAndroid Build Coastguard Worker         }
262*00c7fec1SAndroid Build Coastguard Worker     }
263*00c7fec1SAndroid Build Coastguard Worker     return false;
264*00c7fec1SAndroid Build Coastguard Worker }
265*00c7fec1SAndroid Build Coastguard Worker 
PartitionMatchesSubcontext(const std::string & partition) const266*00c7fec1SAndroid Build Coastguard Worker bool Subcontext::PartitionMatchesSubcontext(const std::string& partition) const {
267*00c7fec1SAndroid Build Coastguard Worker     return std::find(partitions_.begin(), partitions_.end(), partition) != partitions_.end();
268*00c7fec1SAndroid Build Coastguard Worker }
269*00c7fec1SAndroid Build Coastguard Worker 
SetApexList(std::vector<std::string> && apex_list)270*00c7fec1SAndroid Build Coastguard Worker void Subcontext::SetApexList(std::vector<std::string>&& apex_list) {
271*00c7fec1SAndroid Build Coastguard Worker     apex_list_ = std::move(apex_list);
272*00c7fec1SAndroid Build Coastguard Worker }
273*00c7fec1SAndroid Build Coastguard Worker 
TransmitMessage(const SubcontextCommand & subcontext_command)274*00c7fec1SAndroid Build Coastguard Worker Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
275*00c7fec1SAndroid Build Coastguard Worker     if (auto result = SendMessage(socket_.get(), subcontext_command); !result.ok()) {
276*00c7fec1SAndroid Build Coastguard Worker         Restart();
277*00c7fec1SAndroid Build Coastguard Worker         return ErrnoError() << "Failed to send message to subcontext";
278*00c7fec1SAndroid Build Coastguard Worker     }
279*00c7fec1SAndroid Build Coastguard Worker 
280*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_message = ReadMessage(socket_.get());
281*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext_message.ok()) {
282*00c7fec1SAndroid Build Coastguard Worker         Restart();
283*00c7fec1SAndroid Build Coastguard Worker         return Error() << "Failed to receive result from subcontext: " << subcontext_message.error();
284*00c7fec1SAndroid Build Coastguard Worker     }
285*00c7fec1SAndroid Build Coastguard Worker 
286*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_reply = SubcontextReply{};
287*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext_reply.ParseFromString(*subcontext_message)) {
288*00c7fec1SAndroid Build Coastguard Worker         Restart();
289*00c7fec1SAndroid Build Coastguard Worker         return Error() << "Unable to parse message from subcontext";
290*00c7fec1SAndroid Build Coastguard Worker     }
291*00c7fec1SAndroid Build Coastguard Worker 
292*00c7fec1SAndroid Build Coastguard Worker     if (subcontext_reply.has_trigger_shutdown()) {
293*00c7fec1SAndroid Build Coastguard Worker         trigger_shutdown(subcontext_reply.trigger_shutdown());
294*00c7fec1SAndroid Build Coastguard Worker     }
295*00c7fec1SAndroid Build Coastguard Worker 
296*00c7fec1SAndroid Build Coastguard Worker     return subcontext_reply;
297*00c7fec1SAndroid Build Coastguard Worker }
298*00c7fec1SAndroid Build Coastguard Worker 
Execute(const std::vector<std::string> & args)299*00c7fec1SAndroid Build Coastguard Worker Result<void> Subcontext::Execute(const std::vector<std::string>& args) {
300*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_command = SubcontextCommand();
301*00c7fec1SAndroid Build Coastguard Worker     std::copy(
302*00c7fec1SAndroid Build Coastguard Worker         args.begin(), args.end(),
303*00c7fec1SAndroid Build Coastguard Worker         RepeatedPtrFieldBackInserter(subcontext_command.mutable_execute_command()->mutable_args()));
304*00c7fec1SAndroid Build Coastguard Worker 
305*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_reply = TransmitMessage(subcontext_command);
306*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext_reply.ok()) {
307*00c7fec1SAndroid Build Coastguard Worker         return subcontext_reply.error();
308*00c7fec1SAndroid Build Coastguard Worker     }
309*00c7fec1SAndroid Build Coastguard Worker 
310*00c7fec1SAndroid Build Coastguard Worker     if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
311*00c7fec1SAndroid Build Coastguard Worker         auto& failure = subcontext_reply->failure();
312*00c7fec1SAndroid Build Coastguard Worker         return ResultError<>(failure.error_string(), failure.error_errno());
313*00c7fec1SAndroid Build Coastguard Worker     }
314*00c7fec1SAndroid Build Coastguard Worker 
315*00c7fec1SAndroid Build Coastguard Worker     if (subcontext_reply->reply_case() != SubcontextReply::kSuccess) {
316*00c7fec1SAndroid Build Coastguard Worker         return Error() << "Unexpected message type from subcontext: "
317*00c7fec1SAndroid Build Coastguard Worker                        << subcontext_reply->reply_case();
318*00c7fec1SAndroid Build Coastguard Worker     }
319*00c7fec1SAndroid Build Coastguard Worker 
320*00c7fec1SAndroid Build Coastguard Worker     return {};
321*00c7fec1SAndroid Build Coastguard Worker }
322*00c7fec1SAndroid Build Coastguard Worker 
ExpandArgs(const std::vector<std::string> & args)323*00c7fec1SAndroid Build Coastguard Worker Result<std::vector<std::string>> Subcontext::ExpandArgs(const std::vector<std::string>& args) {
324*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_command = SubcontextCommand{};
325*00c7fec1SAndroid Build Coastguard Worker     std::copy(args.begin(), args.end(),
326*00c7fec1SAndroid Build Coastguard Worker               RepeatedPtrFieldBackInserter(
327*00c7fec1SAndroid Build Coastguard Worker                   subcontext_command.mutable_expand_args_command()->mutable_args()));
328*00c7fec1SAndroid Build Coastguard Worker 
329*00c7fec1SAndroid Build Coastguard Worker     auto subcontext_reply = TransmitMessage(subcontext_command);
330*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext_reply.ok()) {
331*00c7fec1SAndroid Build Coastguard Worker         return subcontext_reply.error();
332*00c7fec1SAndroid Build Coastguard Worker     }
333*00c7fec1SAndroid Build Coastguard Worker 
334*00c7fec1SAndroid Build Coastguard Worker     if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
335*00c7fec1SAndroid Build Coastguard Worker         auto& failure = subcontext_reply->failure();
336*00c7fec1SAndroid Build Coastguard Worker         return ResultError<>(failure.error_string(), failure.error_errno());
337*00c7fec1SAndroid Build Coastguard Worker     }
338*00c7fec1SAndroid Build Coastguard Worker 
339*00c7fec1SAndroid Build Coastguard Worker     if (subcontext_reply->reply_case() != SubcontextReply::kExpandArgsReply) {
340*00c7fec1SAndroid Build Coastguard Worker         return Error() << "Unexpected message type from subcontext: "
341*00c7fec1SAndroid Build Coastguard Worker                        << subcontext_reply->reply_case();
342*00c7fec1SAndroid Build Coastguard Worker     }
343*00c7fec1SAndroid Build Coastguard Worker 
344*00c7fec1SAndroid Build Coastguard Worker     auto& reply = subcontext_reply->expand_args_reply();
345*00c7fec1SAndroid Build Coastguard Worker     auto expanded_args = std::vector<std::string>{};
346*00c7fec1SAndroid Build Coastguard Worker     for (const auto& string : reply.expanded_args()) {
347*00c7fec1SAndroid Build Coastguard Worker         expanded_args.emplace_back(string);
348*00c7fec1SAndroid Build Coastguard Worker     }
349*00c7fec1SAndroid Build Coastguard Worker     return expanded_args;
350*00c7fec1SAndroid Build Coastguard Worker }
351*00c7fec1SAndroid Build Coastguard Worker 
InitializeSubcontext()352*00c7fec1SAndroid Build Coastguard Worker void InitializeSubcontext() {
353*00c7fec1SAndroid Build Coastguard Worker     if (IsMicrodroid()) {
354*00c7fec1SAndroid Build Coastguard Worker         LOG(INFO) << "Not using subcontext for microdroid";
355*00c7fec1SAndroid Build Coastguard Worker         return;
356*00c7fec1SAndroid Build Coastguard Worker     }
357*00c7fec1SAndroid Build Coastguard Worker 
358*00c7fec1SAndroid Build Coastguard Worker     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
359*00c7fec1SAndroid Build Coastguard Worker         subcontext.reset(new Subcontext(std::vector<std::string>{"/vendor", "/odm"},
360*00c7fec1SAndroid Build Coastguard Worker                                         std::vector<std::string>{"VENDOR", "ODM"}, kVendorContext));
361*00c7fec1SAndroid Build Coastguard Worker     }
362*00c7fec1SAndroid Build Coastguard Worker }
363*00c7fec1SAndroid Build Coastguard Worker 
InitializeHostSubcontext(std::vector<std::string> vendor_prefixes)364*00c7fec1SAndroid Build Coastguard Worker void InitializeHostSubcontext(std::vector<std::string> vendor_prefixes) {
365*00c7fec1SAndroid Build Coastguard Worker     subcontext.reset(new Subcontext(vendor_prefixes, {}, kVendorContext, /*host=*/true));
366*00c7fec1SAndroid Build Coastguard Worker }
367*00c7fec1SAndroid Build Coastguard Worker 
GetSubcontext()368*00c7fec1SAndroid Build Coastguard Worker Subcontext* GetSubcontext() {
369*00c7fec1SAndroid Build Coastguard Worker     return subcontext.get();
370*00c7fec1SAndroid Build Coastguard Worker }
371*00c7fec1SAndroid Build Coastguard Worker 
SubcontextChildReap(pid_t pid)372*00c7fec1SAndroid Build Coastguard Worker bool SubcontextChildReap(pid_t pid) {
373*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext) {
374*00c7fec1SAndroid Build Coastguard Worker         return false;
375*00c7fec1SAndroid Build Coastguard Worker     }
376*00c7fec1SAndroid Build Coastguard Worker     if (subcontext->pid() == pid) {
377*00c7fec1SAndroid Build Coastguard Worker         if (!subcontext_terminated_by_shutdown) {
378*00c7fec1SAndroid Build Coastguard Worker             subcontext->Restart();
379*00c7fec1SAndroid Build Coastguard Worker         }
380*00c7fec1SAndroid Build Coastguard Worker         return true;
381*00c7fec1SAndroid Build Coastguard Worker     }
382*00c7fec1SAndroid Build Coastguard Worker     return false;
383*00c7fec1SAndroid Build Coastguard Worker }
384*00c7fec1SAndroid Build Coastguard Worker 
SubcontextTerminate()385*00c7fec1SAndroid Build Coastguard Worker void SubcontextTerminate() {
386*00c7fec1SAndroid Build Coastguard Worker     if (!subcontext) {
387*00c7fec1SAndroid Build Coastguard Worker         return;
388*00c7fec1SAndroid Build Coastguard Worker     }
389*00c7fec1SAndroid Build Coastguard Worker     subcontext_terminated_by_shutdown = true;
390*00c7fec1SAndroid Build Coastguard Worker     kill(subcontext->pid(), SIGTERM);
391*00c7fec1SAndroid Build Coastguard Worker }
392*00c7fec1SAndroid Build Coastguard Worker 
393*00c7fec1SAndroid Build Coastguard Worker }  // namespace init
394*00c7fec1SAndroid Build Coastguard Worker }  // namespace android
395