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