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