1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2008 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 "builtins.h"
18*00c7fec1SAndroid Build Coastguard Worker
19*00c7fec1SAndroid Build Coastguard Worker #include <android/api-level.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <dirent.h>
21*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
22*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
23*00c7fec1SAndroid Build Coastguard Worker #include <fts.h>
24*00c7fec1SAndroid Build Coastguard Worker #include <glob.h>
25*00c7fec1SAndroid Build Coastguard Worker #include <linux/loop.h>
26*00c7fec1SAndroid Build Coastguard Worker #include <linux/module.h>
27*00c7fec1SAndroid Build Coastguard Worker #include <mntent.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <net/if.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <sched.h>
30*00c7fec1SAndroid Build Coastguard Worker #include <signal.h>
31*00c7fec1SAndroid Build Coastguard Worker #include <stdint.h>
32*00c7fec1SAndroid Build Coastguard Worker #include <stdio.h>
33*00c7fec1SAndroid Build Coastguard Worker #include <stdlib.h>
34*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
35*00c7fec1SAndroid Build Coastguard Worker #include <sys/mount.h>
36*00c7fec1SAndroid Build Coastguard Worker #include <sys/resource.h>
37*00c7fec1SAndroid Build Coastguard Worker #include <sys/socket.h>
38*00c7fec1SAndroid Build Coastguard Worker #include <sys/stat.h>
39*00c7fec1SAndroid Build Coastguard Worker #include <sys/swap.h>
40*00c7fec1SAndroid Build Coastguard Worker #include <sys/syscall.h>
41*00c7fec1SAndroid Build Coastguard Worker #include <sys/system_properties.h>
42*00c7fec1SAndroid Build Coastguard Worker #include <sys/time.h>
43*00c7fec1SAndroid Build Coastguard Worker #include <sys/types.h>
44*00c7fec1SAndroid Build Coastguard Worker #include <sys/wait.h>
45*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
46*00c7fec1SAndroid Build Coastguard Worker
47*00c7fec1SAndroid Build Coastguard Worker #include <map>
48*00c7fec1SAndroid Build Coastguard Worker #include <memory>
49*00c7fec1SAndroid Build Coastguard Worker
50*00c7fec1SAndroid Build Coastguard Worker #include <android-base/chrono_utils.h>
51*00c7fec1SAndroid Build Coastguard Worker #include <android-base/file.h>
52*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
53*00c7fec1SAndroid Build Coastguard Worker #include <android-base/parsedouble.h>
54*00c7fec1SAndroid Build Coastguard Worker #include <android-base/parseint.h>
55*00c7fec1SAndroid Build Coastguard Worker #include <android-base/properties.h>
56*00c7fec1SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
57*00c7fec1SAndroid Build Coastguard Worker #include <android-base/strings.h>
58*00c7fec1SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
59*00c7fec1SAndroid Build Coastguard Worker #include <bootloader_message/bootloader_message.h>
60*00c7fec1SAndroid Build Coastguard Worker #include <cutils/android_reboot.h>
61*00c7fec1SAndroid Build Coastguard Worker #include <fs_mgr.h>
62*00c7fec1SAndroid Build Coastguard Worker #include <fscrypt/fscrypt.h>
63*00c7fec1SAndroid Build Coastguard Worker #include <libdm/dm.h>
64*00c7fec1SAndroid Build Coastguard Worker #include <libdm/loop_control.h>
65*00c7fec1SAndroid Build Coastguard Worker #include <libgsi/libgsi.h>
66*00c7fec1SAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
67*00c7fec1SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
68*00c7fec1SAndroid Build Coastguard Worker #include <selinux/android.h>
69*00c7fec1SAndroid Build Coastguard Worker #include <selinux/label.h>
70*00c7fec1SAndroid Build Coastguard Worker #include <selinux/selinux.h>
71*00c7fec1SAndroid Build Coastguard Worker #include <system/thread_defs.h>
72*00c7fec1SAndroid Build Coastguard Worker
73*00c7fec1SAndroid Build Coastguard Worker #include "action_manager.h"
74*00c7fec1SAndroid Build Coastguard Worker #include "apex_init_util.h"
75*00c7fec1SAndroid Build Coastguard Worker #include "bootchart.h"
76*00c7fec1SAndroid Build Coastguard Worker #include "builtin_arguments.h"
77*00c7fec1SAndroid Build Coastguard Worker #include "fscrypt_init_extensions.h"
78*00c7fec1SAndroid Build Coastguard Worker #include "init.h"
79*00c7fec1SAndroid Build Coastguard Worker #include "mount_namespace.h"
80*00c7fec1SAndroid Build Coastguard Worker #include "parser.h"
81*00c7fec1SAndroid Build Coastguard Worker #include "property_service.h"
82*00c7fec1SAndroid Build Coastguard Worker #include "reboot.h"
83*00c7fec1SAndroid Build Coastguard Worker #include "rlimit_parser.h"
84*00c7fec1SAndroid Build Coastguard Worker #include "selabel.h"
85*00c7fec1SAndroid Build Coastguard Worker #include "selinux.h"
86*00c7fec1SAndroid Build Coastguard Worker #include "service.h"
87*00c7fec1SAndroid Build Coastguard Worker #include "service_list.h"
88*00c7fec1SAndroid Build Coastguard Worker #include "subcontext.h"
89*00c7fec1SAndroid Build Coastguard Worker #include "util.h"
90*00c7fec1SAndroid Build Coastguard Worker
91*00c7fec1SAndroid Build Coastguard Worker using namespace std::literals::string_literals;
92*00c7fec1SAndroid Build Coastguard Worker
93*00c7fec1SAndroid Build Coastguard Worker using android::base::Basename;
94*00c7fec1SAndroid Build Coastguard Worker using android::base::ResultError;
95*00c7fec1SAndroid Build Coastguard Worker using android::base::SetProperty;
96*00c7fec1SAndroid Build Coastguard Worker using android::base::Split;
97*00c7fec1SAndroid Build Coastguard Worker using android::base::StartsWith;
98*00c7fec1SAndroid Build Coastguard Worker using android::base::StringPrintf;
99*00c7fec1SAndroid Build Coastguard Worker using android::base::unique_fd;
100*00c7fec1SAndroid Build Coastguard Worker using android::fs_mgr::Fstab;
101*00c7fec1SAndroid Build Coastguard Worker using android::fs_mgr::ReadFstabFromFile;
102*00c7fec1SAndroid Build Coastguard Worker
103*00c7fec1SAndroid Build Coastguard Worker #define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
104*00c7fec1SAndroid Build Coastguard Worker
105*00c7fec1SAndroid Build Coastguard Worker namespace android {
106*00c7fec1SAndroid Build Coastguard Worker namespace init {
107*00c7fec1SAndroid Build Coastguard Worker
108*00c7fec1SAndroid Build Coastguard Worker // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
109*00c7fec1SAndroid Build Coastguard Worker // device, such as '/sys/class/leds/jogball-backlight/brightness'. As of this writing, there
110*00c7fec1SAndroid Build Coastguard Worker // are 81 such failures on cuttlefish. Instead of spamming the log reporting them, we do not
111*00c7fec1SAndroid Build Coastguard Worker // report such failures unless we're running at the DEBUG log level.
112*00c7fec1SAndroid Build Coastguard Worker class ErrorIgnoreEnoent {
113*00c7fec1SAndroid Build Coastguard Worker public:
ErrorIgnoreEnoent()114*00c7fec1SAndroid Build Coastguard Worker ErrorIgnoreEnoent()
115*00c7fec1SAndroid Build Coastguard Worker : ignore_error_(errno == ENOENT &&
116*00c7fec1SAndroid Build Coastguard Worker android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
ErrorIgnoreEnoent(int errno_to_append)117*00c7fec1SAndroid Build Coastguard Worker explicit ErrorIgnoreEnoent(int errno_to_append)
118*00c7fec1SAndroid Build Coastguard Worker : error_(errno_to_append),
119*00c7fec1SAndroid Build Coastguard Worker ignore_error_(errno_to_append == ENOENT &&
120*00c7fec1SAndroid Build Coastguard Worker android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
121*00c7fec1SAndroid Build Coastguard Worker
122*00c7fec1SAndroid Build Coastguard Worker template <typename T>
operator android::base::expected<T,ResultError<android::base::Errno>>()123*00c7fec1SAndroid Build Coastguard Worker operator android::base::expected<T, ResultError<android::base::Errno>>() {
124*00c7fec1SAndroid Build Coastguard Worker if (ignore_error_) {
125*00c7fec1SAndroid Build Coastguard Worker return {};
126*00c7fec1SAndroid Build Coastguard Worker }
127*00c7fec1SAndroid Build Coastguard Worker return error_;
128*00c7fec1SAndroid Build Coastguard Worker }
129*00c7fec1SAndroid Build Coastguard Worker
130*00c7fec1SAndroid Build Coastguard Worker template <typename T>
operator <<(T && t)131*00c7fec1SAndroid Build Coastguard Worker ErrorIgnoreEnoent& operator<<(T&& t) {
132*00c7fec1SAndroid Build Coastguard Worker error_ << t;
133*00c7fec1SAndroid Build Coastguard Worker return *this;
134*00c7fec1SAndroid Build Coastguard Worker }
135*00c7fec1SAndroid Build Coastguard Worker
136*00c7fec1SAndroid Build Coastguard Worker private:
137*00c7fec1SAndroid Build Coastguard Worker Error<> error_;
138*00c7fec1SAndroid Build Coastguard Worker bool ignore_error_;
139*00c7fec1SAndroid Build Coastguard Worker };
140*00c7fec1SAndroid Build Coastguard Worker
ErrnoErrorIgnoreEnoent()141*00c7fec1SAndroid Build Coastguard Worker inline ErrorIgnoreEnoent ErrnoErrorIgnoreEnoent() {
142*00c7fec1SAndroid Build Coastguard Worker return ErrorIgnoreEnoent(errno);
143*00c7fec1SAndroid Build Coastguard Worker }
144*00c7fec1SAndroid Build Coastguard Worker
145*00c7fec1SAndroid Build Coastguard Worker std::vector<std::string> late_import_paths;
146*00c7fec1SAndroid Build Coastguard Worker
147*00c7fec1SAndroid Build Coastguard Worker static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
148*00c7fec1SAndroid Build Coastguard Worker
reboot_into_recovery(const std::vector<std::string> & options)149*00c7fec1SAndroid Build Coastguard Worker static Result<void> reboot_into_recovery(const std::vector<std::string>& options) {
150*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Rebooting into recovery";
151*00c7fec1SAndroid Build Coastguard Worker std::string err;
152*00c7fec1SAndroid Build Coastguard Worker if (!write_bootloader_message(options, &err)) {
153*00c7fec1SAndroid Build Coastguard Worker return Error() << "Failed to set bootloader message: " << err;
154*00c7fec1SAndroid Build Coastguard Worker }
155*00c7fec1SAndroid Build Coastguard Worker trigger_shutdown("reboot,recovery");
156*00c7fec1SAndroid Build Coastguard Worker return {};
157*00c7fec1SAndroid Build Coastguard Worker }
158*00c7fec1SAndroid Build Coastguard Worker
159*00c7fec1SAndroid Build Coastguard Worker template <typename F>
ForEachServiceInClass(const std::string & classname,F function)160*00c7fec1SAndroid Build Coastguard Worker static void ForEachServiceInClass(const std::string& classname, F function) {
161*00c7fec1SAndroid Build Coastguard Worker for (const auto& service : ServiceList::GetInstance()) {
162*00c7fec1SAndroid Build Coastguard Worker if (service->classnames().count(classname)) std::invoke(function, service);
163*00c7fec1SAndroid Build Coastguard Worker }
164*00c7fec1SAndroid Build Coastguard Worker }
165*00c7fec1SAndroid Build Coastguard Worker
do_class_start(const BuiltinArguments & args)166*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_class_start(const BuiltinArguments& args) {
167*00c7fec1SAndroid Build Coastguard Worker // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.
168*00c7fec1SAndroid Build Coastguard Worker if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
169*00c7fec1SAndroid Build Coastguard Worker return {};
170*00c7fec1SAndroid Build Coastguard Worker // Starting a class does not start services which are explicitly disabled.
171*00c7fec1SAndroid Build Coastguard Worker // They must be started individually.
172*00c7fec1SAndroid Build Coastguard Worker for (const auto& service : ServiceList::GetInstance()) {
173*00c7fec1SAndroid Build Coastguard Worker if (service->classnames().count(args[1])) {
174*00c7fec1SAndroid Build Coastguard Worker if (auto result = service->StartIfNotDisabled(); !result.ok()) {
175*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Could not start service '" << service->name()
176*00c7fec1SAndroid Build Coastguard Worker << "' as part of class '" << args[1] << "': " << result.error();
177*00c7fec1SAndroid Build Coastguard Worker }
178*00c7fec1SAndroid Build Coastguard Worker }
179*00c7fec1SAndroid Build Coastguard Worker }
180*00c7fec1SAndroid Build Coastguard Worker return {};
181*00c7fec1SAndroid Build Coastguard Worker }
182*00c7fec1SAndroid Build Coastguard Worker
do_class_stop(const BuiltinArguments & args)183*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_class_stop(const BuiltinArguments& args) {
184*00c7fec1SAndroid Build Coastguard Worker ForEachServiceInClass(args[1], &Service::Stop);
185*00c7fec1SAndroid Build Coastguard Worker return {};
186*00c7fec1SAndroid Build Coastguard Worker }
187*00c7fec1SAndroid Build Coastguard Worker
do_class_reset(const BuiltinArguments & args)188*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_class_reset(const BuiltinArguments& args) {
189*00c7fec1SAndroid Build Coastguard Worker ForEachServiceInClass(args[1], &Service::Reset);
190*00c7fec1SAndroid Build Coastguard Worker return {};
191*00c7fec1SAndroid Build Coastguard Worker }
192*00c7fec1SAndroid Build Coastguard Worker
do_class_restart(const BuiltinArguments & args)193*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_class_restart(const BuiltinArguments& args) {
194*00c7fec1SAndroid Build Coastguard Worker // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1.
195*00c7fec1SAndroid Build Coastguard Worker if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
196*00c7fec1SAndroid Build Coastguard Worker return {};
197*00c7fec1SAndroid Build Coastguard Worker
198*00c7fec1SAndroid Build Coastguard Worker std::string classname;
199*00c7fec1SAndroid Build Coastguard Worker
200*00c7fec1SAndroid Build Coastguard Worker CHECK(args.size() == 2 || args.size() == 3);
201*00c7fec1SAndroid Build Coastguard Worker
202*00c7fec1SAndroid Build Coastguard Worker bool only_enabled = false;
203*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 3) {
204*00c7fec1SAndroid Build Coastguard Worker if (args[1] != "--only-enabled") {
205*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unexpected argument: " << args[1];
206*00c7fec1SAndroid Build Coastguard Worker }
207*00c7fec1SAndroid Build Coastguard Worker only_enabled = true;
208*00c7fec1SAndroid Build Coastguard Worker classname = args[2];
209*00c7fec1SAndroid Build Coastguard Worker } else if (args.size() == 2) {
210*00c7fec1SAndroid Build Coastguard Worker classname = args[1];
211*00c7fec1SAndroid Build Coastguard Worker }
212*00c7fec1SAndroid Build Coastguard Worker
213*00c7fec1SAndroid Build Coastguard Worker for (const auto& service : ServiceList::GetInstance()) {
214*00c7fec1SAndroid Build Coastguard Worker if (!service->classnames().count(classname)) {
215*00c7fec1SAndroid Build Coastguard Worker continue;
216*00c7fec1SAndroid Build Coastguard Worker }
217*00c7fec1SAndroid Build Coastguard Worker if (only_enabled && !service->IsEnabled()) {
218*00c7fec1SAndroid Build Coastguard Worker continue;
219*00c7fec1SAndroid Build Coastguard Worker }
220*00c7fec1SAndroid Build Coastguard Worker service->Restart();
221*00c7fec1SAndroid Build Coastguard Worker }
222*00c7fec1SAndroid Build Coastguard Worker return {};
223*00c7fec1SAndroid Build Coastguard Worker }
224*00c7fec1SAndroid Build Coastguard Worker
do_domainname(const BuiltinArguments & args)225*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_domainname(const BuiltinArguments& args) {
226*00c7fec1SAndroid Build Coastguard Worker if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result.ok()) {
227*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error();
228*00c7fec1SAndroid Build Coastguard Worker }
229*00c7fec1SAndroid Build Coastguard Worker return {};
230*00c7fec1SAndroid Build Coastguard Worker }
231*00c7fec1SAndroid Build Coastguard Worker
do_enable(const BuiltinArguments & args)232*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_enable(const BuiltinArguments& args) {
233*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindService(args[1]);
234*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "Could not find service";
235*00c7fec1SAndroid Build Coastguard Worker
236*00c7fec1SAndroid Build Coastguard Worker if (auto result = svc->Enable(); !result.ok()) {
237*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not enable service: " << result.error();
238*00c7fec1SAndroid Build Coastguard Worker }
239*00c7fec1SAndroid Build Coastguard Worker
240*00c7fec1SAndroid Build Coastguard Worker return {};
241*00c7fec1SAndroid Build Coastguard Worker }
242*00c7fec1SAndroid Build Coastguard Worker
do_exec(const BuiltinArguments & args)243*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_exec(const BuiltinArguments& args) {
244*00c7fec1SAndroid Build Coastguard Worker auto service = Service::MakeTemporaryOneshotService(args.args);
245*00c7fec1SAndroid Build Coastguard Worker if (!service.ok()) {
246*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not create exec service: " << service.error();
247*00c7fec1SAndroid Build Coastguard Worker }
248*00c7fec1SAndroid Build Coastguard Worker if (auto result = (*service)->ExecStart(); !result.ok()) {
249*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not start exec service: " << result.error();
250*00c7fec1SAndroid Build Coastguard Worker }
251*00c7fec1SAndroid Build Coastguard Worker
252*00c7fec1SAndroid Build Coastguard Worker ServiceList::GetInstance().AddService(std::move(*service));
253*00c7fec1SAndroid Build Coastguard Worker return {};
254*00c7fec1SAndroid Build Coastguard Worker }
255*00c7fec1SAndroid Build Coastguard Worker
do_exec_background(const BuiltinArguments & args)256*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_exec_background(const BuiltinArguments& args) {
257*00c7fec1SAndroid Build Coastguard Worker auto service = Service::MakeTemporaryOneshotService(args.args);
258*00c7fec1SAndroid Build Coastguard Worker if (!service.ok()) {
259*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not create exec background service: " << service.error();
260*00c7fec1SAndroid Build Coastguard Worker }
261*00c7fec1SAndroid Build Coastguard Worker if (auto result = (*service)->Start(); !result.ok()) {
262*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not start exec background service: " << result.error();
263*00c7fec1SAndroid Build Coastguard Worker }
264*00c7fec1SAndroid Build Coastguard Worker
265*00c7fec1SAndroid Build Coastguard Worker ServiceList::GetInstance().AddService(std::move(*service));
266*00c7fec1SAndroid Build Coastguard Worker return {};
267*00c7fec1SAndroid Build Coastguard Worker }
268*00c7fec1SAndroid Build Coastguard Worker
do_exec_start(const BuiltinArguments & args)269*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_exec_start(const BuiltinArguments& args) {
270*00c7fec1SAndroid Build Coastguard Worker Service* service = ServiceList::GetInstance().FindService(args[1]);
271*00c7fec1SAndroid Build Coastguard Worker if (!service) {
272*00c7fec1SAndroid Build Coastguard Worker return Error() << "Service not found";
273*00c7fec1SAndroid Build Coastguard Worker }
274*00c7fec1SAndroid Build Coastguard Worker
275*00c7fec1SAndroid Build Coastguard Worker if (auto result = service->ExecStart(); !result.ok()) {
276*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not start exec service: " << result.error();
277*00c7fec1SAndroid Build Coastguard Worker }
278*00c7fec1SAndroid Build Coastguard Worker
279*00c7fec1SAndroid Build Coastguard Worker return {};
280*00c7fec1SAndroid Build Coastguard Worker }
281*00c7fec1SAndroid Build Coastguard Worker
do_export(const BuiltinArguments & args)282*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_export(const BuiltinArguments& args) {
283*00c7fec1SAndroid Build Coastguard Worker if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
284*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "setenv() failed";
285*00c7fec1SAndroid Build Coastguard Worker }
286*00c7fec1SAndroid Build Coastguard Worker return {};
287*00c7fec1SAndroid Build Coastguard Worker }
288*00c7fec1SAndroid Build Coastguard Worker
do_load_exports(const BuiltinArguments & args)289*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_load_exports(const BuiltinArguments& args) {
290*00c7fec1SAndroid Build Coastguard Worker auto file_contents = ReadFile(args[1]);
291*00c7fec1SAndroid Build Coastguard Worker if (!file_contents.ok()) {
292*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read input file '" << args[1]
293*00c7fec1SAndroid Build Coastguard Worker << "': " << file_contents.error();
294*00c7fec1SAndroid Build Coastguard Worker }
295*00c7fec1SAndroid Build Coastguard Worker
296*00c7fec1SAndroid Build Coastguard Worker auto lines = Split(*file_contents, "\n");
297*00c7fec1SAndroid Build Coastguard Worker for (const auto& line : lines) {
298*00c7fec1SAndroid Build Coastguard Worker if (line.empty()) {
299*00c7fec1SAndroid Build Coastguard Worker continue;
300*00c7fec1SAndroid Build Coastguard Worker }
301*00c7fec1SAndroid Build Coastguard Worker
302*00c7fec1SAndroid Build Coastguard Worker auto env = Split(line, " ");
303*00c7fec1SAndroid Build Coastguard Worker
304*00c7fec1SAndroid Build Coastguard Worker if (env.size() != 3) {
305*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Expected a line as `export <name> <value>`, found: `" << line
306*00c7fec1SAndroid Build Coastguard Worker << "`";
307*00c7fec1SAndroid Build Coastguard Worker }
308*00c7fec1SAndroid Build Coastguard Worker
309*00c7fec1SAndroid Build Coastguard Worker if (env[0] != "export") {
310*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Unknown action: '" << env[0] << "', expected 'export'";
311*00c7fec1SAndroid Build Coastguard Worker }
312*00c7fec1SAndroid Build Coastguard Worker
313*00c7fec1SAndroid Build Coastguard Worker if (setenv(env[1].c_str(), env[2].c_str(), 1) == -1) {
314*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Failed to export '" << line << "' from " << args[1];
315*00c7fec1SAndroid Build Coastguard Worker }
316*00c7fec1SAndroid Build Coastguard Worker }
317*00c7fec1SAndroid Build Coastguard Worker
318*00c7fec1SAndroid Build Coastguard Worker return {};
319*00c7fec1SAndroid Build Coastguard Worker }
320*00c7fec1SAndroid Build Coastguard Worker
do_hostname(const BuiltinArguments & args)321*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_hostname(const BuiltinArguments& args) {
322*00c7fec1SAndroid Build Coastguard Worker if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result.ok()) {
323*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error();
324*00c7fec1SAndroid Build Coastguard Worker }
325*00c7fec1SAndroid Build Coastguard Worker return {};
326*00c7fec1SAndroid Build Coastguard Worker }
327*00c7fec1SAndroid Build Coastguard Worker
do_ifup(const BuiltinArguments & args)328*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_ifup(const BuiltinArguments& args) {
329*00c7fec1SAndroid Build Coastguard Worker struct ifreq ifr;
330*00c7fec1SAndroid Build Coastguard Worker
331*00c7fec1SAndroid Build Coastguard Worker strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
332*00c7fec1SAndroid Build Coastguard Worker
333*00c7fec1SAndroid Build Coastguard Worker unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)));
334*00c7fec1SAndroid Build Coastguard Worker if (s < 0) return ErrnoError() << "opening socket failed";
335*00c7fec1SAndroid Build Coastguard Worker
336*00c7fec1SAndroid Build Coastguard Worker if (ioctl(s.get(), SIOCGIFFLAGS, &ifr) < 0) {
337*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "ioctl(..., SIOCGIFFLAGS, ...) failed";
338*00c7fec1SAndroid Build Coastguard Worker }
339*00c7fec1SAndroid Build Coastguard Worker
340*00c7fec1SAndroid Build Coastguard Worker ifr.ifr_flags |= IFF_UP;
341*00c7fec1SAndroid Build Coastguard Worker
342*00c7fec1SAndroid Build Coastguard Worker if (ioctl(s.get(), SIOCSIFFLAGS, &ifr) < 0) {
343*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "ioctl(..., SIOCSIFFLAGS, ...) failed";
344*00c7fec1SAndroid Build Coastguard Worker }
345*00c7fec1SAndroid Build Coastguard Worker
346*00c7fec1SAndroid Build Coastguard Worker return {};
347*00c7fec1SAndroid Build Coastguard Worker }
348*00c7fec1SAndroid Build Coastguard Worker
do_insmod(const BuiltinArguments & args)349*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_insmod(const BuiltinArguments& args) {
350*00c7fec1SAndroid Build Coastguard Worker int flags = 0;
351*00c7fec1SAndroid Build Coastguard Worker auto it = args.begin() + 1;
352*00c7fec1SAndroid Build Coastguard Worker
353*00c7fec1SAndroid Build Coastguard Worker if (!(*it).compare("-f")) {
354*00c7fec1SAndroid Build Coastguard Worker flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
355*00c7fec1SAndroid Build Coastguard Worker it++;
356*00c7fec1SAndroid Build Coastguard Worker }
357*00c7fec1SAndroid Build Coastguard Worker
358*00c7fec1SAndroid Build Coastguard Worker std::string filename = *it++;
359*00c7fec1SAndroid Build Coastguard Worker std::string options = android::base::Join(std::vector<std::string>(it, args.end()), ' ');
360*00c7fec1SAndroid Build Coastguard Worker
361*00c7fec1SAndroid Build Coastguard Worker unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
362*00c7fec1SAndroid Build Coastguard Worker if (fd == -1) return ErrnoError() << "open(\"" << filename << "\") failed";
363*00c7fec1SAndroid Build Coastguard Worker
364*00c7fec1SAndroid Build Coastguard Worker int rc = syscall(__NR_finit_module, fd.get(), options.c_str(), flags);
365*00c7fec1SAndroid Build Coastguard Worker if (rc == -1) return ErrnoError() << "finit_module for \"" << filename << "\" failed";
366*00c7fec1SAndroid Build Coastguard Worker
367*00c7fec1SAndroid Build Coastguard Worker return {};
368*00c7fec1SAndroid Build Coastguard Worker }
369*00c7fec1SAndroid Build Coastguard Worker
do_interface_restart(const BuiltinArguments & args)370*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_interface_restart(const BuiltinArguments& args) {
371*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
372*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "interface " << args[1] << " not found";
373*00c7fec1SAndroid Build Coastguard Worker svc->Restart();
374*00c7fec1SAndroid Build Coastguard Worker return {};
375*00c7fec1SAndroid Build Coastguard Worker }
376*00c7fec1SAndroid Build Coastguard Worker
do_interface_start(const BuiltinArguments & args)377*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_interface_start(const BuiltinArguments& args) {
378*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
379*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "interface " << args[1] << " not found";
380*00c7fec1SAndroid Build Coastguard Worker if (auto result = svc->Start(); !result.ok()) {
381*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not start interface: " << result.error();
382*00c7fec1SAndroid Build Coastguard Worker }
383*00c7fec1SAndroid Build Coastguard Worker return {};
384*00c7fec1SAndroid Build Coastguard Worker }
385*00c7fec1SAndroid Build Coastguard Worker
do_interface_stop(const BuiltinArguments & args)386*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_interface_stop(const BuiltinArguments& args) {
387*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
388*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "interface " << args[1] << " not found";
389*00c7fec1SAndroid Build Coastguard Worker svc->Stop();
390*00c7fec1SAndroid Build Coastguard Worker return {};
391*00c7fec1SAndroid Build Coastguard Worker }
392*00c7fec1SAndroid Build Coastguard Worker
make_dir_with_options(const MkdirOptions & options)393*00c7fec1SAndroid Build Coastguard Worker static Result<void> make_dir_with_options(const MkdirOptions& options) {
394*00c7fec1SAndroid Build Coastguard Worker std::string ref_basename;
395*00c7fec1SAndroid Build Coastguard Worker if (options.ref_option == "ref") {
396*00c7fec1SAndroid Build Coastguard Worker ref_basename = fscrypt_key_ref;
397*00c7fec1SAndroid Build Coastguard Worker } else if (options.ref_option == "per_boot_ref") {
398*00c7fec1SAndroid Build Coastguard Worker ref_basename = fscrypt_key_per_boot_ref;
399*00c7fec1SAndroid Build Coastguard Worker } else {
400*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unknown key option: '" << options.ref_option << "'";
401*00c7fec1SAndroid Build Coastguard Worker }
402*00c7fec1SAndroid Build Coastguard Worker
403*00c7fec1SAndroid Build Coastguard Worker struct stat mstat;
404*00c7fec1SAndroid Build Coastguard Worker if (lstat(options.target.c_str(), &mstat) != 0) {
405*00c7fec1SAndroid Build Coastguard Worker if (errno != ENOENT) {
406*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "lstat() failed on " << options.target;
407*00c7fec1SAndroid Build Coastguard Worker }
408*00c7fec1SAndroid Build Coastguard Worker if (!make_dir(options.target, options.mode)) {
409*00c7fec1SAndroid Build Coastguard Worker return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options.target;
410*00c7fec1SAndroid Build Coastguard Worker }
411*00c7fec1SAndroid Build Coastguard Worker if (lstat(options.target.c_str(), &mstat) != 0) {
412*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "lstat() failed on new " << options.target;
413*00c7fec1SAndroid Build Coastguard Worker }
414*00c7fec1SAndroid Build Coastguard Worker }
415*00c7fec1SAndroid Build Coastguard Worker if (!S_ISDIR(mstat.st_mode)) {
416*00c7fec1SAndroid Build Coastguard Worker return Error() << "Not a directory on " << options.target;
417*00c7fec1SAndroid Build Coastguard Worker }
418*00c7fec1SAndroid Build Coastguard Worker bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options.mode;
419*00c7fec1SAndroid Build Coastguard Worker if ((options.uid != static_cast<uid_t>(-1) && options.uid != mstat.st_uid) ||
420*00c7fec1SAndroid Build Coastguard Worker (options.gid != static_cast<gid_t>(-1) && options.gid != mstat.st_gid)) {
421*00c7fec1SAndroid Build Coastguard Worker if (lchown(options.target.c_str(), options.uid, options.gid) == -1) {
422*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "lchown failed on " << options.target;
423*00c7fec1SAndroid Build Coastguard Worker }
424*00c7fec1SAndroid Build Coastguard Worker // chown may have cleared S_ISUID and S_ISGID, chmod again
425*00c7fec1SAndroid Build Coastguard Worker needs_chmod = true;
426*00c7fec1SAndroid Build Coastguard Worker }
427*00c7fec1SAndroid Build Coastguard Worker if (needs_chmod) {
428*00c7fec1SAndroid Build Coastguard Worker if (fchmodat(AT_FDCWD, options.target.c_str(), options.mode, AT_SYMLINK_NOFOLLOW) == -1) {
429*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "fchmodat() failed on " << options.target;
430*00c7fec1SAndroid Build Coastguard Worker }
431*00c7fec1SAndroid Build Coastguard Worker }
432*00c7fec1SAndroid Build Coastguard Worker if (IsFbeEnabled()) {
433*00c7fec1SAndroid Build Coastguard Worker if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) {
434*00c7fec1SAndroid Build Coastguard Worker return reboot_into_recovery(
435*00c7fec1SAndroid Build Coastguard Worker {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target});
436*00c7fec1SAndroid Build Coastguard Worker }
437*00c7fec1SAndroid Build Coastguard Worker }
438*00c7fec1SAndroid Build Coastguard Worker return {};
439*00c7fec1SAndroid Build Coastguard Worker }
440*00c7fec1SAndroid Build Coastguard Worker
441*00c7fec1SAndroid Build Coastguard Worker // mkdir <path> [mode] [owner] [group] [<option> ...]
do_mkdir(const BuiltinArguments & args)442*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_mkdir(const BuiltinArguments& args) {
443*00c7fec1SAndroid Build Coastguard Worker auto options = ParseMkdir(args.args);
444*00c7fec1SAndroid Build Coastguard Worker if (!options.ok()) return options.error();
445*00c7fec1SAndroid Build Coastguard Worker return make_dir_with_options(*options);
446*00c7fec1SAndroid Build Coastguard Worker }
447*00c7fec1SAndroid Build Coastguard Worker
448*00c7fec1SAndroid Build Coastguard Worker /* umount <path> */
do_umount(const BuiltinArguments & args)449*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_umount(const BuiltinArguments& args) {
450*00c7fec1SAndroid Build Coastguard Worker if (umount(args[1].c_str()) < 0) {
451*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "umount() failed";
452*00c7fec1SAndroid Build Coastguard Worker }
453*00c7fec1SAndroid Build Coastguard Worker return {};
454*00c7fec1SAndroid Build Coastguard Worker }
455*00c7fec1SAndroid Build Coastguard Worker
456*00c7fec1SAndroid Build Coastguard Worker static struct {
457*00c7fec1SAndroid Build Coastguard Worker const char *name;
458*00c7fec1SAndroid Build Coastguard Worker unsigned flag;
459*00c7fec1SAndroid Build Coastguard Worker } mount_flags[] = {
460*00c7fec1SAndroid Build Coastguard Worker { "noatime", MS_NOATIME },
461*00c7fec1SAndroid Build Coastguard Worker { "noexec", MS_NOEXEC },
462*00c7fec1SAndroid Build Coastguard Worker { "nosuid", MS_NOSUID },
463*00c7fec1SAndroid Build Coastguard Worker { "nodev", MS_NODEV },
464*00c7fec1SAndroid Build Coastguard Worker { "nodiratime", MS_NODIRATIME },
465*00c7fec1SAndroid Build Coastguard Worker { "ro", MS_RDONLY },
466*00c7fec1SAndroid Build Coastguard Worker { "rw", 0 },
467*00c7fec1SAndroid Build Coastguard Worker { "remount", MS_REMOUNT },
468*00c7fec1SAndroid Build Coastguard Worker { "bind", MS_BIND },
469*00c7fec1SAndroid Build Coastguard Worker { "rec", MS_REC },
470*00c7fec1SAndroid Build Coastguard Worker { "unbindable", MS_UNBINDABLE },
471*00c7fec1SAndroid Build Coastguard Worker { "private", MS_PRIVATE },
472*00c7fec1SAndroid Build Coastguard Worker { "slave", MS_SLAVE },
473*00c7fec1SAndroid Build Coastguard Worker { "shared", MS_SHARED },
474*00c7fec1SAndroid Build Coastguard Worker { "nosymfollow", MS_NOSYMFOLLOW },
475*00c7fec1SAndroid Build Coastguard Worker { "defaults", 0 },
476*00c7fec1SAndroid Build Coastguard Worker { 0, 0 },
477*00c7fec1SAndroid Build Coastguard Worker };
478*00c7fec1SAndroid Build Coastguard Worker
479*00c7fec1SAndroid Build Coastguard Worker /* mount <type> <device> <path> <flags ...> <options> */
do_mount(const BuiltinArguments & args)480*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_mount(const BuiltinArguments& args) {
481*00c7fec1SAndroid Build Coastguard Worker const char* options = nullptr;
482*00c7fec1SAndroid Build Coastguard Worker unsigned flags = 0;
483*00c7fec1SAndroid Build Coastguard Worker bool wait = false;
484*00c7fec1SAndroid Build Coastguard Worker
485*00c7fec1SAndroid Build Coastguard Worker for (size_t na = 4; na < args.size(); na++) {
486*00c7fec1SAndroid Build Coastguard Worker size_t i;
487*00c7fec1SAndroid Build Coastguard Worker for (i = 0; mount_flags[i].name; i++) {
488*00c7fec1SAndroid Build Coastguard Worker if (!args[na].compare(mount_flags[i].name)) {
489*00c7fec1SAndroid Build Coastguard Worker flags |= mount_flags[i].flag;
490*00c7fec1SAndroid Build Coastguard Worker break;
491*00c7fec1SAndroid Build Coastguard Worker }
492*00c7fec1SAndroid Build Coastguard Worker }
493*00c7fec1SAndroid Build Coastguard Worker
494*00c7fec1SAndroid Build Coastguard Worker if (!mount_flags[i].name) {
495*00c7fec1SAndroid Build Coastguard Worker if (!args[na].compare("wait")) {
496*00c7fec1SAndroid Build Coastguard Worker wait = true;
497*00c7fec1SAndroid Build Coastguard Worker // If our last argument isn't a flag, wolf it up as an option string.
498*00c7fec1SAndroid Build Coastguard Worker } else if (na + 1 == args.size()) {
499*00c7fec1SAndroid Build Coastguard Worker options = args[na].c_str();
500*00c7fec1SAndroid Build Coastguard Worker }
501*00c7fec1SAndroid Build Coastguard Worker }
502*00c7fec1SAndroid Build Coastguard Worker }
503*00c7fec1SAndroid Build Coastguard Worker
504*00c7fec1SAndroid Build Coastguard Worker const char* system = args[1].c_str();
505*00c7fec1SAndroid Build Coastguard Worker const char* source = args[2].c_str();
506*00c7fec1SAndroid Build Coastguard Worker const char* target = args[3].c_str();
507*00c7fec1SAndroid Build Coastguard Worker
508*00c7fec1SAndroid Build Coastguard Worker if (android::base::StartsWith(source, "loop@")) {
509*00c7fec1SAndroid Build Coastguard Worker int mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
510*00c7fec1SAndroid Build Coastguard Worker const char* file_path = source + strlen("loop@");
511*00c7fec1SAndroid Build Coastguard Worker
512*00c7fec1SAndroid Build Coastguard Worker // Open source file
513*00c7fec1SAndroid Build Coastguard Worker if (wait) {
514*00c7fec1SAndroid Build Coastguard Worker wait_for_file(file_path, kCommandRetryTimeout);
515*00c7fec1SAndroid Build Coastguard Worker }
516*00c7fec1SAndroid Build Coastguard Worker
517*00c7fec1SAndroid Build Coastguard Worker unique_fd fd(TEMP_FAILURE_RETRY(open(file_path, mode | O_CLOEXEC)));
518*00c7fec1SAndroid Build Coastguard Worker if (fd < 0) {
519*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "open(" << file_path << ", " << mode << ") failed";
520*00c7fec1SAndroid Build Coastguard Worker }
521*00c7fec1SAndroid Build Coastguard Worker
522*00c7fec1SAndroid Build Coastguard Worker // Allocate loop device and attach it to file_path.
523*00c7fec1SAndroid Build Coastguard Worker android::dm::LoopControl loop_control;
524*00c7fec1SAndroid Build Coastguard Worker std::string loop_device;
525*00c7fec1SAndroid Build Coastguard Worker if (!loop_control.Attach(fd.get(), 5s, &loop_device)) {
526*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "loop_control.Attach " << file_path << " failed";
527*00c7fec1SAndroid Build Coastguard Worker }
528*00c7fec1SAndroid Build Coastguard Worker
529*00c7fec1SAndroid Build Coastguard Worker if (mount(loop_device.c_str(), target, system, flags, options) < 0) {
530*00c7fec1SAndroid Build Coastguard Worker loop_control.Detach(loop_device);
531*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "mount() failed";
532*00c7fec1SAndroid Build Coastguard Worker }
533*00c7fec1SAndroid Build Coastguard Worker } else {
534*00c7fec1SAndroid Build Coastguard Worker if (wait)
535*00c7fec1SAndroid Build Coastguard Worker wait_for_file(source, kCommandRetryTimeout);
536*00c7fec1SAndroid Build Coastguard Worker if (mount(source, target, system, flags, options) < 0) {
537*00c7fec1SAndroid Build Coastguard Worker return ErrnoErrorIgnoreEnoent() << "mount() failed";
538*00c7fec1SAndroid Build Coastguard Worker }
539*00c7fec1SAndroid Build Coastguard Worker
540*00c7fec1SAndroid Build Coastguard Worker }
541*00c7fec1SAndroid Build Coastguard Worker
542*00c7fec1SAndroid Build Coastguard Worker return {};
543*00c7fec1SAndroid Build Coastguard Worker }
544*00c7fec1SAndroid Build Coastguard Worker
545*00c7fec1SAndroid Build Coastguard Worker /* Imports .rc files from the specified paths. Default ones are applied if none is given.
546*00c7fec1SAndroid Build Coastguard Worker *
547*00c7fec1SAndroid Build Coastguard Worker * rc_paths: list of paths to rc files to import
548*00c7fec1SAndroid Build Coastguard Worker */
import_late(const std::vector<std::string> & rc_paths)549*00c7fec1SAndroid Build Coastguard Worker static void import_late(const std::vector<std::string>& rc_paths) {
550*00c7fec1SAndroid Build Coastguard Worker auto& action_manager = ActionManager::GetInstance();
551*00c7fec1SAndroid Build Coastguard Worker auto& service_list = ServiceList::GetInstance();
552*00c7fec1SAndroid Build Coastguard Worker Parser parser = CreateParser(action_manager, service_list);
553*00c7fec1SAndroid Build Coastguard Worker if (rc_paths.empty()) {
554*00c7fec1SAndroid Build Coastguard Worker // Fallbacks for partitions on which early mount isn't enabled.
555*00c7fec1SAndroid Build Coastguard Worker for (const auto& path : late_import_paths) {
556*00c7fec1SAndroid Build Coastguard Worker parser.ParseConfig(path);
557*00c7fec1SAndroid Build Coastguard Worker }
558*00c7fec1SAndroid Build Coastguard Worker late_import_paths.clear();
559*00c7fec1SAndroid Build Coastguard Worker } else {
560*00c7fec1SAndroid Build Coastguard Worker for (const auto& rc_path : rc_paths) {
561*00c7fec1SAndroid Build Coastguard Worker parser.ParseConfig(rc_path);
562*00c7fec1SAndroid Build Coastguard Worker }
563*00c7fec1SAndroid Build Coastguard Worker }
564*00c7fec1SAndroid Build Coastguard Worker
565*00c7fec1SAndroid Build Coastguard Worker // Turning this on and letting the INFO logging be discarded adds 0.2s to
566*00c7fec1SAndroid Build Coastguard Worker // Nexus 9 boot time, so it's disabled by default.
567*00c7fec1SAndroid Build Coastguard Worker if (false) DumpState();
568*00c7fec1SAndroid Build Coastguard Worker }
569*00c7fec1SAndroid Build Coastguard Worker
570*00c7fec1SAndroid Build Coastguard Worker /* Queue event based on fs_mgr return code.
571*00c7fec1SAndroid Build Coastguard Worker *
572*00c7fec1SAndroid Build Coastguard Worker * code: return code of fs_mgr_mount_all
573*00c7fec1SAndroid Build Coastguard Worker *
574*00c7fec1SAndroid Build Coastguard Worker * This function might request a reboot, in which case it will
575*00c7fec1SAndroid Build Coastguard Worker * not return.
576*00c7fec1SAndroid Build Coastguard Worker *
577*00c7fec1SAndroid Build Coastguard Worker * return code is processed based on input code
578*00c7fec1SAndroid Build Coastguard Worker */
queue_fs_event(int code)579*00c7fec1SAndroid Build Coastguard Worker static Result<void> queue_fs_event(int code) {
580*00c7fec1SAndroid Build Coastguard Worker if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
581*00c7fec1SAndroid Build Coastguard Worker SetProperty("ro.crypto.state", "unsupported");
582*00c7fec1SAndroid Build Coastguard Worker ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
583*00c7fec1SAndroid Build Coastguard Worker return {};
584*00c7fec1SAndroid Build Coastguard Worker } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
585*00c7fec1SAndroid Build Coastguard Worker /* Setup a wipe via recovery, and reboot into recovery */
586*00c7fec1SAndroid Build Coastguard Worker if (android::gsi::IsGsiRunning()) {
587*00c7fec1SAndroid Build Coastguard Worker return Error() << "cannot wipe within GSI";
588*00c7fec1SAndroid Build Coastguard Worker }
589*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
590*00c7fec1SAndroid Build Coastguard Worker const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
591*00c7fec1SAndroid Build Coastguard Worker return reboot_into_recovery(options);
592*00c7fec1SAndroid Build Coastguard Worker /* If reboot worked, there is no return. */
593*00c7fec1SAndroid Build Coastguard Worker } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED ||
594*00c7fec1SAndroid Build Coastguard Worker code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED ||
595*00c7fec1SAndroid Build Coastguard Worker code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
596*00c7fec1SAndroid Build Coastguard Worker SetProperty("ro.crypto.state", "encrypted");
597*00c7fec1SAndroid Build Coastguard Worker
598*00c7fec1SAndroid Build Coastguard Worker // Although encrypted, vold has already set the device up, so we do not need to
599*00c7fec1SAndroid Build Coastguard Worker // do anything different from the nonencrypted case.
600*00c7fec1SAndroid Build Coastguard Worker ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
601*00c7fec1SAndroid Build Coastguard Worker return {};
602*00c7fec1SAndroid Build Coastguard Worker } else if (code > 0) {
603*00c7fec1SAndroid Build Coastguard Worker Error() << "fs_mgr_mount_all() returned unexpected error " << code;
604*00c7fec1SAndroid Build Coastguard Worker }
605*00c7fec1SAndroid Build Coastguard Worker /* else ... < 0: error */
606*00c7fec1SAndroid Build Coastguard Worker
607*00c7fec1SAndroid Build Coastguard Worker return Error() << "Invalid code: " << code;
608*00c7fec1SAndroid Build Coastguard Worker }
609*00c7fec1SAndroid Build Coastguard Worker
610*00c7fec1SAndroid Build Coastguard Worker /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]*
611*00c7fec1SAndroid Build Coastguard Worker * >= R: mount_all [ <fstab> ] [--<options>]*
612*00c7fec1SAndroid Build Coastguard Worker *
613*00c7fec1SAndroid Build Coastguard Worker * This function might request a reboot, in which case it will
614*00c7fec1SAndroid Build Coastguard Worker * not return.
615*00c7fec1SAndroid Build Coastguard Worker */
do_mount_all(const BuiltinArguments & args)616*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_mount_all(const BuiltinArguments& args) {
617*00c7fec1SAndroid Build Coastguard Worker auto mount_all = ParseMountAll(args.args);
618*00c7fec1SAndroid Build Coastguard Worker if (!mount_all.ok()) return mount_all.error();
619*00c7fec1SAndroid Build Coastguard Worker
620*00c7fec1SAndroid Build Coastguard Worker const char* prop_post_fix = "default";
621*00c7fec1SAndroid Build Coastguard Worker bool queue_event = true;
622*00c7fec1SAndroid Build Coastguard Worker if (mount_all->mode == MOUNT_MODE_EARLY) {
623*00c7fec1SAndroid Build Coastguard Worker prop_post_fix = "early";
624*00c7fec1SAndroid Build Coastguard Worker queue_event = false;
625*00c7fec1SAndroid Build Coastguard Worker } else if (mount_all->mode == MOUNT_MODE_LATE) {
626*00c7fec1SAndroid Build Coastguard Worker prop_post_fix = "late";
627*00c7fec1SAndroid Build Coastguard Worker }
628*00c7fec1SAndroid Build Coastguard Worker
629*00c7fec1SAndroid Build Coastguard Worker std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
630*00c7fec1SAndroid Build Coastguard Worker android::base::Timer t;
631*00c7fec1SAndroid Build Coastguard Worker
632*00c7fec1SAndroid Build Coastguard Worker Fstab fstab;
633*00c7fec1SAndroid Build Coastguard Worker if (mount_all->fstab_path.empty()) {
634*00c7fec1SAndroid Build Coastguard Worker if (!ReadDefaultFstab(&fstab)) {
635*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read default fstab";
636*00c7fec1SAndroid Build Coastguard Worker }
637*00c7fec1SAndroid Build Coastguard Worker } else {
638*00c7fec1SAndroid Build Coastguard Worker if (!ReadFstabFromFile(mount_all->fstab_path, &fstab)) {
639*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read fstab";
640*00c7fec1SAndroid Build Coastguard Worker }
641*00c7fec1SAndroid Build Coastguard Worker }
642*00c7fec1SAndroid Build Coastguard Worker
643*00c7fec1SAndroid Build Coastguard Worker auto mount_fstab_result = fs_mgr_mount_all(&fstab, mount_all->mode);
644*00c7fec1SAndroid Build Coastguard Worker SetProperty(prop_name, std::to_string(t.duration().count()));
645*00c7fec1SAndroid Build Coastguard Worker
646*00c7fec1SAndroid Build Coastguard Worker if (mount_all->import_rc) {
647*00c7fec1SAndroid Build Coastguard Worker import_late(mount_all->rc_paths);
648*00c7fec1SAndroid Build Coastguard Worker }
649*00c7fec1SAndroid Build Coastguard Worker
650*00c7fec1SAndroid Build Coastguard Worker if (queue_event) {
651*00c7fec1SAndroid Build Coastguard Worker /* queue_fs_event will queue event based on mount_fstab return code
652*00c7fec1SAndroid Build Coastguard Worker * and return processed return code*/
653*00c7fec1SAndroid Build Coastguard Worker auto queue_fs_result = queue_fs_event(mount_fstab_result);
654*00c7fec1SAndroid Build Coastguard Worker if (!queue_fs_result.ok()) {
655*00c7fec1SAndroid Build Coastguard Worker return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
656*00c7fec1SAndroid Build Coastguard Worker }
657*00c7fec1SAndroid Build Coastguard Worker }
658*00c7fec1SAndroid Build Coastguard Worker
659*00c7fec1SAndroid Build Coastguard Worker return {};
660*00c7fec1SAndroid Build Coastguard Worker }
661*00c7fec1SAndroid Build Coastguard Worker
662*00c7fec1SAndroid Build Coastguard Worker /* umount_all [ <fstab> ] */
do_umount_all(const BuiltinArguments & args)663*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_umount_all(const BuiltinArguments& args) {
664*00c7fec1SAndroid Build Coastguard Worker auto umount_all = ParseUmountAll(args.args);
665*00c7fec1SAndroid Build Coastguard Worker if (!umount_all.ok()) return umount_all.error();
666*00c7fec1SAndroid Build Coastguard Worker
667*00c7fec1SAndroid Build Coastguard Worker Fstab fstab;
668*00c7fec1SAndroid Build Coastguard Worker if (umount_all->empty()) {
669*00c7fec1SAndroid Build Coastguard Worker if (!ReadDefaultFstab(&fstab)) {
670*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read default fstab";
671*00c7fec1SAndroid Build Coastguard Worker }
672*00c7fec1SAndroid Build Coastguard Worker } else {
673*00c7fec1SAndroid Build Coastguard Worker if (!ReadFstabFromFile(*umount_all, &fstab)) {
674*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read fstab";
675*00c7fec1SAndroid Build Coastguard Worker }
676*00c7fec1SAndroid Build Coastguard Worker }
677*00c7fec1SAndroid Build Coastguard Worker
678*00c7fec1SAndroid Build Coastguard Worker if (auto result = fs_mgr_umount_all(&fstab); result != 0) {
679*00c7fec1SAndroid Build Coastguard Worker return Error() << "umount_fstab() failed " << result;
680*00c7fec1SAndroid Build Coastguard Worker }
681*00c7fec1SAndroid Build Coastguard Worker return {};
682*00c7fec1SAndroid Build Coastguard Worker }
683*00c7fec1SAndroid Build Coastguard Worker
684*00c7fec1SAndroid Build Coastguard Worker /* swapon_all [ <fstab> ] */
do_swapon_all(const BuiltinArguments & args)685*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_swapon_all(const BuiltinArguments& args) {
686*00c7fec1SAndroid Build Coastguard Worker auto swapon_all = ParseSwaponAll(args.args);
687*00c7fec1SAndroid Build Coastguard Worker if (!swapon_all.ok()) return swapon_all.error();
688*00c7fec1SAndroid Build Coastguard Worker
689*00c7fec1SAndroid Build Coastguard Worker Fstab fstab;
690*00c7fec1SAndroid Build Coastguard Worker if (swapon_all->empty()) {
691*00c7fec1SAndroid Build Coastguard Worker if (!ReadDefaultFstab(&fstab)) {
692*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read default fstab";
693*00c7fec1SAndroid Build Coastguard Worker }
694*00c7fec1SAndroid Build Coastguard Worker } else {
695*00c7fec1SAndroid Build Coastguard Worker if (!ReadFstabFromFile(*swapon_all, &fstab)) {
696*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read fstab '" << *swapon_all << "'";
697*00c7fec1SAndroid Build Coastguard Worker }
698*00c7fec1SAndroid Build Coastguard Worker }
699*00c7fec1SAndroid Build Coastguard Worker
700*00c7fec1SAndroid Build Coastguard Worker if (!fs_mgr_swapon_all(fstab)) {
701*00c7fec1SAndroid Build Coastguard Worker return Error() << "fs_mgr_swapon_all() failed";
702*00c7fec1SAndroid Build Coastguard Worker }
703*00c7fec1SAndroid Build Coastguard Worker
704*00c7fec1SAndroid Build Coastguard Worker return {};
705*00c7fec1SAndroid Build Coastguard Worker }
706*00c7fec1SAndroid Build Coastguard Worker
do_setprop(const BuiltinArguments & args)707*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_setprop(const BuiltinArguments& args) {
708*00c7fec1SAndroid Build Coastguard Worker if (StartsWith(args[1], "ctl.")) {
709*00c7fec1SAndroid Build Coastguard Worker return Error()
710*00c7fec1SAndroid Build Coastguard Worker << "Cannot set ctl. properties from init; call the Service functions directly";
711*00c7fec1SAndroid Build Coastguard Worker }
712*00c7fec1SAndroid Build Coastguard Worker if (args[1] == kRestoreconProperty) {
713*00c7fec1SAndroid Build Coastguard Worker return Error() << "Cannot set '" << kRestoreconProperty
714*00c7fec1SAndroid Build Coastguard Worker << "' from init; use the restorecon builtin directly";
715*00c7fec1SAndroid Build Coastguard Worker }
716*00c7fec1SAndroid Build Coastguard Worker
717*00c7fec1SAndroid Build Coastguard Worker SetProperty(args[1], args[2]);
718*00c7fec1SAndroid Build Coastguard Worker return {};
719*00c7fec1SAndroid Build Coastguard Worker }
720*00c7fec1SAndroid Build Coastguard Worker
do_setrlimit(const BuiltinArguments & args)721*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_setrlimit(const BuiltinArguments& args) {
722*00c7fec1SAndroid Build Coastguard Worker auto rlimit = ParseRlimit(args.args);
723*00c7fec1SAndroid Build Coastguard Worker if (!rlimit.ok()) return rlimit.error();
724*00c7fec1SAndroid Build Coastguard Worker
725*00c7fec1SAndroid Build Coastguard Worker if (setrlimit(rlimit->first, &rlimit->second) == -1) {
726*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "setrlimit failed";
727*00c7fec1SAndroid Build Coastguard Worker }
728*00c7fec1SAndroid Build Coastguard Worker return {};
729*00c7fec1SAndroid Build Coastguard Worker }
730*00c7fec1SAndroid Build Coastguard Worker
do_start(const BuiltinArguments & args)731*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_start(const BuiltinArguments& args) {
732*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindService(args[1]);
733*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "service " << args[1] << " not found";
734*00c7fec1SAndroid Build Coastguard Worker errno = 0;
735*00c7fec1SAndroid Build Coastguard Worker if (auto result = svc->Start(); !result.ok()) {
736*00c7fec1SAndroid Build Coastguard Worker return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
737*00c7fec1SAndroid Build Coastguard Worker }
738*00c7fec1SAndroid Build Coastguard Worker return {};
739*00c7fec1SAndroid Build Coastguard Worker }
740*00c7fec1SAndroid Build Coastguard Worker
do_stop(const BuiltinArguments & args)741*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_stop(const BuiltinArguments& args) {
742*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindService(args[1]);
743*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "service " << args[1] << " not found";
744*00c7fec1SAndroid Build Coastguard Worker svc->Stop();
745*00c7fec1SAndroid Build Coastguard Worker return {};
746*00c7fec1SAndroid Build Coastguard Worker }
747*00c7fec1SAndroid Build Coastguard Worker
do_restart(const BuiltinArguments & args)748*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_restart(const BuiltinArguments& args) {
749*00c7fec1SAndroid Build Coastguard Worker bool only_if_running = false;
750*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 3) {
751*00c7fec1SAndroid Build Coastguard Worker if (args[1] == "--only-if-running") {
752*00c7fec1SAndroid Build Coastguard Worker only_if_running = true;
753*00c7fec1SAndroid Build Coastguard Worker } else {
754*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unknown argument to restart: " << args[1];
755*00c7fec1SAndroid Build Coastguard Worker }
756*00c7fec1SAndroid Build Coastguard Worker }
757*00c7fec1SAndroid Build Coastguard Worker
758*00c7fec1SAndroid Build Coastguard Worker const auto& classname = args[args.size() - 1];
759*00c7fec1SAndroid Build Coastguard Worker Service* svc = ServiceList::GetInstance().FindService(classname);
760*00c7fec1SAndroid Build Coastguard Worker if (!svc) return Error() << "service " << classname << " not found";
761*00c7fec1SAndroid Build Coastguard Worker if (only_if_running && !svc->IsRunning()) {
762*00c7fec1SAndroid Build Coastguard Worker return {};
763*00c7fec1SAndroid Build Coastguard Worker }
764*00c7fec1SAndroid Build Coastguard Worker svc->Restart();
765*00c7fec1SAndroid Build Coastguard Worker return {};
766*00c7fec1SAndroid Build Coastguard Worker }
767*00c7fec1SAndroid Build Coastguard Worker
do_trigger(const BuiltinArguments & args)768*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_trigger(const BuiltinArguments& args) {
769*00c7fec1SAndroid Build Coastguard Worker ActionManager::GetInstance().QueueEventTrigger(args[1]);
770*00c7fec1SAndroid Build Coastguard Worker return {};
771*00c7fec1SAndroid Build Coastguard Worker }
772*00c7fec1SAndroid Build Coastguard Worker
MakeSymlink(const std::string & target,const std::string & linkpath)773*00c7fec1SAndroid Build Coastguard Worker static int MakeSymlink(const std::string& target, const std::string& linkpath) {
774*00c7fec1SAndroid Build Coastguard Worker std::string secontext;
775*00c7fec1SAndroid Build Coastguard Worker // Passing 0 for mode should work.
776*00c7fec1SAndroid Build Coastguard Worker if (SelabelLookupFileContext(linkpath, 0, &secontext) && !secontext.empty()) {
777*00c7fec1SAndroid Build Coastguard Worker setfscreatecon(secontext.c_str());
778*00c7fec1SAndroid Build Coastguard Worker }
779*00c7fec1SAndroid Build Coastguard Worker
780*00c7fec1SAndroid Build Coastguard Worker int rc = symlink(target.c_str(), linkpath.c_str());
781*00c7fec1SAndroid Build Coastguard Worker
782*00c7fec1SAndroid Build Coastguard Worker if (!secontext.empty()) {
783*00c7fec1SAndroid Build Coastguard Worker int save_errno = errno;
784*00c7fec1SAndroid Build Coastguard Worker setfscreatecon(nullptr);
785*00c7fec1SAndroid Build Coastguard Worker errno = save_errno;
786*00c7fec1SAndroid Build Coastguard Worker }
787*00c7fec1SAndroid Build Coastguard Worker
788*00c7fec1SAndroid Build Coastguard Worker return rc;
789*00c7fec1SAndroid Build Coastguard Worker }
790*00c7fec1SAndroid Build Coastguard Worker
do_symlink(const BuiltinArguments & args)791*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_symlink(const BuiltinArguments& args) {
792*00c7fec1SAndroid Build Coastguard Worker if (MakeSymlink(args[1], args[2]) < 0) {
793*00c7fec1SAndroid Build Coastguard Worker // The symlink builtin is often used to create symlinks for older devices to be backwards
794*00c7fec1SAndroid Build Coastguard Worker // compatible with new paths, therefore we skip reporting this error.
795*00c7fec1SAndroid Build Coastguard Worker return ErrnoErrorIgnoreEnoent() << "symlink() failed";
796*00c7fec1SAndroid Build Coastguard Worker }
797*00c7fec1SAndroid Build Coastguard Worker return {};
798*00c7fec1SAndroid Build Coastguard Worker }
799*00c7fec1SAndroid Build Coastguard Worker
do_rm(const BuiltinArguments & args)800*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_rm(const BuiltinArguments& args) {
801*00c7fec1SAndroid Build Coastguard Worker if (unlink(args[1].c_str()) < 0) {
802*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "unlink() failed";
803*00c7fec1SAndroid Build Coastguard Worker }
804*00c7fec1SAndroid Build Coastguard Worker return {};
805*00c7fec1SAndroid Build Coastguard Worker }
806*00c7fec1SAndroid Build Coastguard Worker
do_rmdir(const BuiltinArguments & args)807*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_rmdir(const BuiltinArguments& args) {
808*00c7fec1SAndroid Build Coastguard Worker if (rmdir(args[1].c_str()) < 0) {
809*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "rmdir() failed";
810*00c7fec1SAndroid Build Coastguard Worker }
811*00c7fec1SAndroid Build Coastguard Worker return {};
812*00c7fec1SAndroid Build Coastguard Worker }
813*00c7fec1SAndroid Build Coastguard Worker
do_sysclktz(const BuiltinArguments & args)814*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_sysclktz(const BuiltinArguments& args) {
815*00c7fec1SAndroid Build Coastguard Worker struct timezone tz = {};
816*00c7fec1SAndroid Build Coastguard Worker if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
817*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unable to parse mins_west_of_gmt";
818*00c7fec1SAndroid Build Coastguard Worker }
819*00c7fec1SAndroid Build Coastguard Worker
820*00c7fec1SAndroid Build Coastguard Worker if (settimeofday(nullptr, &tz) == -1) {
821*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "settimeofday() failed";
822*00c7fec1SAndroid Build Coastguard Worker }
823*00c7fec1SAndroid Build Coastguard Worker return {};
824*00c7fec1SAndroid Build Coastguard Worker }
825*00c7fec1SAndroid Build Coastguard Worker
do_verity_update_state(const BuiltinArguments & args)826*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_verity_update_state(const BuiltinArguments& args) {
827*00c7fec1SAndroid Build Coastguard Worker int mode;
828*00c7fec1SAndroid Build Coastguard Worker if (!fs_mgr_load_verity_state(&mode)) {
829*00c7fec1SAndroid Build Coastguard Worker return Error() << "fs_mgr_load_verity_state() failed";
830*00c7fec1SAndroid Build Coastguard Worker }
831*00c7fec1SAndroid Build Coastguard Worker
832*00c7fec1SAndroid Build Coastguard Worker Fstab fstab;
833*00c7fec1SAndroid Build Coastguard Worker if (!ReadDefaultFstab(&fstab)) {
834*00c7fec1SAndroid Build Coastguard Worker return Error() << "Failed to read default fstab";
835*00c7fec1SAndroid Build Coastguard Worker }
836*00c7fec1SAndroid Build Coastguard Worker
837*00c7fec1SAndroid Build Coastguard Worker for (const auto& entry : fstab) {
838*00c7fec1SAndroid Build Coastguard Worker if (!fs_mgr_is_verity_enabled(entry)) {
839*00c7fec1SAndroid Build Coastguard Worker continue;
840*00c7fec1SAndroid Build Coastguard Worker }
841*00c7fec1SAndroid Build Coastguard Worker
842*00c7fec1SAndroid Build Coastguard Worker // To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
843*00c7fec1SAndroid Build Coastguard Worker // for system as root, so it has property [partition.system.verified].
844*00c7fec1SAndroid Build Coastguard Worker std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
845*00c7fec1SAndroid Build Coastguard Worker SetProperty("partition." + partition + ".verified", std::to_string(mode));
846*00c7fec1SAndroid Build Coastguard Worker
847*00c7fec1SAndroid Build Coastguard Worker auto hashtree_info = fs_mgr_get_hashtree_info(entry);
848*00c7fec1SAndroid Build Coastguard Worker if (hashtree_info) {
849*00c7fec1SAndroid Build Coastguard Worker SetProperty("partition." + partition + ".verified.hash_alg", hashtree_info->algorithm);
850*00c7fec1SAndroid Build Coastguard Worker SetProperty("partition." + partition + ".verified.root_digest",
851*00c7fec1SAndroid Build Coastguard Worker hashtree_info->root_digest);
852*00c7fec1SAndroid Build Coastguard Worker SetProperty("partition." + partition + ".verified.check_at_most_once",
853*00c7fec1SAndroid Build Coastguard Worker hashtree_info->check_at_most_once ? "1" : "0");
854*00c7fec1SAndroid Build Coastguard Worker }
855*00c7fec1SAndroid Build Coastguard Worker }
856*00c7fec1SAndroid Build Coastguard Worker
857*00c7fec1SAndroid Build Coastguard Worker return {};
858*00c7fec1SAndroid Build Coastguard Worker }
859*00c7fec1SAndroid Build Coastguard Worker
do_write(const BuiltinArguments & args)860*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_write(const BuiltinArguments& args) {
861*00c7fec1SAndroid Build Coastguard Worker if (auto result = WriteFile(args[1], args[2]); !result.ok()) {
862*00c7fec1SAndroid Build Coastguard Worker return ErrorIgnoreEnoent()
863*00c7fec1SAndroid Build Coastguard Worker << "Unable to write to file '" << args[1] << "': " << result.error();
864*00c7fec1SAndroid Build Coastguard Worker }
865*00c7fec1SAndroid Build Coastguard Worker
866*00c7fec1SAndroid Build Coastguard Worker return {};
867*00c7fec1SAndroid Build Coastguard Worker }
868*00c7fec1SAndroid Build Coastguard Worker
readahead_file(const std::string & filename,bool fully)869*00c7fec1SAndroid Build Coastguard Worker static Result<void> readahead_file(const std::string& filename, bool fully) {
870*00c7fec1SAndroid Build Coastguard Worker android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_CLOEXEC)));
871*00c7fec1SAndroid Build Coastguard Worker if (fd == -1) {
872*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Error opening file";
873*00c7fec1SAndroid Build Coastguard Worker }
874*00c7fec1SAndroid Build Coastguard Worker if (posix_fadvise(fd.get(), 0, 0, POSIX_FADV_WILLNEED)) {
875*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Error posix_fadvise file";
876*00c7fec1SAndroid Build Coastguard Worker }
877*00c7fec1SAndroid Build Coastguard Worker if (readahead(fd.get(), 0, std::numeric_limits<size_t>::max())) {
878*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Error readahead file";
879*00c7fec1SAndroid Build Coastguard Worker }
880*00c7fec1SAndroid Build Coastguard Worker if (fully) {
881*00c7fec1SAndroid Build Coastguard Worker char buf[BUFSIZ];
882*00c7fec1SAndroid Build Coastguard Worker ssize_t n;
883*00c7fec1SAndroid Build Coastguard Worker while ((n = TEMP_FAILURE_RETRY(read(fd.get(), &buf[0], sizeof(buf)))) > 0) {
884*00c7fec1SAndroid Build Coastguard Worker }
885*00c7fec1SAndroid Build Coastguard Worker if (n != 0) {
886*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Error reading file";
887*00c7fec1SAndroid Build Coastguard Worker }
888*00c7fec1SAndroid Build Coastguard Worker }
889*00c7fec1SAndroid Build Coastguard Worker return {};
890*00c7fec1SAndroid Build Coastguard Worker }
891*00c7fec1SAndroid Build Coastguard Worker
do_readahead(const BuiltinArguments & args)892*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_readahead(const BuiltinArguments& args) {
893*00c7fec1SAndroid Build Coastguard Worker struct stat sb;
894*00c7fec1SAndroid Build Coastguard Worker
895*00c7fec1SAndroid Build Coastguard Worker if (stat(args[1].c_str(), &sb)) {
896*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Error opening " << args[1];
897*00c7fec1SAndroid Build Coastguard Worker }
898*00c7fec1SAndroid Build Coastguard Worker
899*00c7fec1SAndroid Build Coastguard Worker bool readfully = false;
900*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 3 && args[2] == "--fully") {
901*00c7fec1SAndroid Build Coastguard Worker readfully = true;
902*00c7fec1SAndroid Build Coastguard Worker }
903*00c7fec1SAndroid Build Coastguard Worker // We will do readahead in a forked process in order not to block init
904*00c7fec1SAndroid Build Coastguard Worker // since it may block while it reads the
905*00c7fec1SAndroid Build Coastguard Worker // filesystem metadata needed to locate the requested blocks. This
906*00c7fec1SAndroid Build Coastguard Worker // occurs frequently with ext[234] on large files using indirect blocks
907*00c7fec1SAndroid Build Coastguard Worker // instead of extents, giving the appearance that the call blocks until
908*00c7fec1SAndroid Build Coastguard Worker // the requested data has been read.
909*00c7fec1SAndroid Build Coastguard Worker pid_t pid = fork();
910*00c7fec1SAndroid Build Coastguard Worker if (pid == 0) {
911*00c7fec1SAndroid Build Coastguard Worker if (setpriority(PRIO_PROCESS, 0, static_cast<int>(ANDROID_PRIORITY_LOWEST)) != 0) {
912*00c7fec1SAndroid Build Coastguard Worker PLOG(WARNING) << "setpriority failed";
913*00c7fec1SAndroid Build Coastguard Worker }
914*00c7fec1SAndroid Build Coastguard Worker if (android_set_ioprio(0, IoSchedClass_IDLE, 7)) {
915*00c7fec1SAndroid Build Coastguard Worker PLOG(WARNING) << "ioprio_get failed";
916*00c7fec1SAndroid Build Coastguard Worker }
917*00c7fec1SAndroid Build Coastguard Worker android::base::Timer t;
918*00c7fec1SAndroid Build Coastguard Worker if (S_ISREG(sb.st_mode)) {
919*00c7fec1SAndroid Build Coastguard Worker if (auto result = readahead_file(args[1], readfully); !result.ok()) {
920*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "Unable to readahead '" << args[1] << "': " << result.error();
921*00c7fec1SAndroid Build Coastguard Worker _exit(EXIT_FAILURE);
922*00c7fec1SAndroid Build Coastguard Worker }
923*00c7fec1SAndroid Build Coastguard Worker } else if (S_ISDIR(sb.st_mode)) {
924*00c7fec1SAndroid Build Coastguard Worker char* paths[] = {const_cast<char*>(args[1].data()), nullptr};
925*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<FTS, decltype(&fts_close)> fts(
926*00c7fec1SAndroid Build Coastguard Worker fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr), fts_close);
927*00c7fec1SAndroid Build Coastguard Worker if (!fts) {
928*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "Error opening directory: " << args[1];
929*00c7fec1SAndroid Build Coastguard Worker _exit(EXIT_FAILURE);
930*00c7fec1SAndroid Build Coastguard Worker }
931*00c7fec1SAndroid Build Coastguard Worker // Traverse the entire hierarchy and do readahead
932*00c7fec1SAndroid Build Coastguard Worker for (FTSENT* ftsent = fts_read(fts.get()); ftsent != nullptr;
933*00c7fec1SAndroid Build Coastguard Worker ftsent = fts_read(fts.get())) {
934*00c7fec1SAndroid Build Coastguard Worker if (ftsent->fts_info & FTS_F) {
935*00c7fec1SAndroid Build Coastguard Worker const std::string filename = ftsent->fts_accpath;
936*00c7fec1SAndroid Build Coastguard Worker if (auto result = readahead_file(filename, readfully); !result.ok()) {
937*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING)
938*00c7fec1SAndroid Build Coastguard Worker << "Unable to readahead '" << filename << "': " << result.error();
939*00c7fec1SAndroid Build Coastguard Worker }
940*00c7fec1SAndroid Build Coastguard Worker }
941*00c7fec1SAndroid Build Coastguard Worker }
942*00c7fec1SAndroid Build Coastguard Worker }
943*00c7fec1SAndroid Build Coastguard Worker LOG(INFO) << "Readahead " << args[1] << " took " << t << " asynchronously";
944*00c7fec1SAndroid Build Coastguard Worker _exit(0);
945*00c7fec1SAndroid Build Coastguard Worker } else if (pid < 0) {
946*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Fork failed";
947*00c7fec1SAndroid Build Coastguard Worker }
948*00c7fec1SAndroid Build Coastguard Worker return {};
949*00c7fec1SAndroid Build Coastguard Worker }
950*00c7fec1SAndroid Build Coastguard Worker
do_copy(const BuiltinArguments & args)951*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_copy(const BuiltinArguments& args) {
952*00c7fec1SAndroid Build Coastguard Worker auto file_contents = ReadFile(args[1]);
953*00c7fec1SAndroid Build Coastguard Worker if (!file_contents.ok()) {
954*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error();
955*00c7fec1SAndroid Build Coastguard Worker }
956*00c7fec1SAndroid Build Coastguard Worker if (auto result = WriteFile(args[2], *file_contents); !result.ok()) {
957*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not write to output file '" << args[2] << "': " << result.error();
958*00c7fec1SAndroid Build Coastguard Worker }
959*00c7fec1SAndroid Build Coastguard Worker
960*00c7fec1SAndroid Build Coastguard Worker return {};
961*00c7fec1SAndroid Build Coastguard Worker }
962*00c7fec1SAndroid Build Coastguard Worker
do_copy_per_line(const BuiltinArguments & args)963*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_copy_per_line(const BuiltinArguments& args) {
964*00c7fec1SAndroid Build Coastguard Worker std::string file_contents;
965*00c7fec1SAndroid Build Coastguard Worker if (!android::base::ReadFileToString(args[1], &file_contents, true)) {
966*00c7fec1SAndroid Build Coastguard Worker return Error() << "Could not read input file '" << args[1] << "'";
967*00c7fec1SAndroid Build Coastguard Worker }
968*00c7fec1SAndroid Build Coastguard Worker auto lines = Split(file_contents, "\n");
969*00c7fec1SAndroid Build Coastguard Worker for (const auto& line : lines) {
970*00c7fec1SAndroid Build Coastguard Worker auto result = WriteFile(args[2], line);
971*00c7fec1SAndroid Build Coastguard Worker if (!result.ok()) {
972*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "Could not write to output file '" << args[2] << "' with '" << line
973*00c7fec1SAndroid Build Coastguard Worker << "' : " << result.error();
974*00c7fec1SAndroid Build Coastguard Worker }
975*00c7fec1SAndroid Build Coastguard Worker }
976*00c7fec1SAndroid Build Coastguard Worker
977*00c7fec1SAndroid Build Coastguard Worker return {};
978*00c7fec1SAndroid Build Coastguard Worker }
979*00c7fec1SAndroid Build Coastguard Worker
do_chown(const BuiltinArguments & args)980*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_chown(const BuiltinArguments& args) {
981*00c7fec1SAndroid Build Coastguard Worker auto uid = DecodeUid(args[1]);
982*00c7fec1SAndroid Build Coastguard Worker if (!uid.ok()) {
983*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
984*00c7fec1SAndroid Build Coastguard Worker }
985*00c7fec1SAndroid Build Coastguard Worker
986*00c7fec1SAndroid Build Coastguard Worker // GID is optional and pushes the index of path out by one if specified.
987*00c7fec1SAndroid Build Coastguard Worker const std::string& path = (args.size() == 4) ? args[3] : args[2];
988*00c7fec1SAndroid Build Coastguard Worker Result<gid_t> gid = -1;
989*00c7fec1SAndroid Build Coastguard Worker
990*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 4) {
991*00c7fec1SAndroid Build Coastguard Worker gid = DecodeUid(args[2]);
992*00c7fec1SAndroid Build Coastguard Worker if (!gid.ok()) {
993*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
994*00c7fec1SAndroid Build Coastguard Worker }
995*00c7fec1SAndroid Build Coastguard Worker }
996*00c7fec1SAndroid Build Coastguard Worker
997*00c7fec1SAndroid Build Coastguard Worker if (lchown(path.c_str(), *uid, *gid) == -1) {
998*00c7fec1SAndroid Build Coastguard Worker return ErrnoErrorIgnoreEnoent() << "lchown() failed";
999*00c7fec1SAndroid Build Coastguard Worker }
1000*00c7fec1SAndroid Build Coastguard Worker
1001*00c7fec1SAndroid Build Coastguard Worker return {};
1002*00c7fec1SAndroid Build Coastguard Worker }
1003*00c7fec1SAndroid Build Coastguard Worker
get_mode(const char * s)1004*00c7fec1SAndroid Build Coastguard Worker static mode_t get_mode(const char *s) {
1005*00c7fec1SAndroid Build Coastguard Worker mode_t mode = 0;
1006*00c7fec1SAndroid Build Coastguard Worker while (*s) {
1007*00c7fec1SAndroid Build Coastguard Worker if (*s >= '0' && *s <= '7') {
1008*00c7fec1SAndroid Build Coastguard Worker mode = (mode<<3) | (*s-'0');
1009*00c7fec1SAndroid Build Coastguard Worker } else {
1010*00c7fec1SAndroid Build Coastguard Worker return -1;
1011*00c7fec1SAndroid Build Coastguard Worker }
1012*00c7fec1SAndroid Build Coastguard Worker s++;
1013*00c7fec1SAndroid Build Coastguard Worker }
1014*00c7fec1SAndroid Build Coastguard Worker return mode;
1015*00c7fec1SAndroid Build Coastguard Worker }
1016*00c7fec1SAndroid Build Coastguard Worker
do_chmod(const BuiltinArguments & args)1017*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_chmod(const BuiltinArguments& args) {
1018*00c7fec1SAndroid Build Coastguard Worker mode_t mode = get_mode(args[1].c_str());
1019*00c7fec1SAndroid Build Coastguard Worker if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
1020*00c7fec1SAndroid Build Coastguard Worker return ErrnoErrorIgnoreEnoent() << "fchmodat() failed";
1021*00c7fec1SAndroid Build Coastguard Worker }
1022*00c7fec1SAndroid Build Coastguard Worker return {};
1023*00c7fec1SAndroid Build Coastguard Worker }
1024*00c7fec1SAndroid Build Coastguard Worker
do_restorecon(const BuiltinArguments & args)1025*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_restorecon(const BuiltinArguments& args) {
1026*00c7fec1SAndroid Build Coastguard Worker auto restorecon_info = ParseRestorecon(args.args);
1027*00c7fec1SAndroid Build Coastguard Worker if (!restorecon_info.ok()) {
1028*00c7fec1SAndroid Build Coastguard Worker return restorecon_info.error();
1029*00c7fec1SAndroid Build Coastguard Worker }
1030*00c7fec1SAndroid Build Coastguard Worker
1031*00c7fec1SAndroid Build Coastguard Worker const auto& [flag, paths] = *restorecon_info;
1032*00c7fec1SAndroid Build Coastguard Worker
1033*00c7fec1SAndroid Build Coastguard Worker int ret = 0;
1034*00c7fec1SAndroid Build Coastguard Worker for (const auto& path : paths) {
1035*00c7fec1SAndroid Build Coastguard Worker if (selinux_android_restorecon(path.c_str(), flag) < 0) {
1036*00c7fec1SAndroid Build Coastguard Worker ret = errno;
1037*00c7fec1SAndroid Build Coastguard Worker }
1038*00c7fec1SAndroid Build Coastguard Worker }
1039*00c7fec1SAndroid Build Coastguard Worker
1040*00c7fec1SAndroid Build Coastguard Worker if (ret) return ErrnoErrorIgnoreEnoent() << "selinux_android_restorecon() failed";
1041*00c7fec1SAndroid Build Coastguard Worker return {};
1042*00c7fec1SAndroid Build Coastguard Worker }
1043*00c7fec1SAndroid Build Coastguard Worker
do_restorecon_recursive(const BuiltinArguments & args)1044*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_restorecon_recursive(const BuiltinArguments& args) {
1045*00c7fec1SAndroid Build Coastguard Worker std::vector<std::string> non_const_args(args.args);
1046*00c7fec1SAndroid Build Coastguard Worker non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
1047*00c7fec1SAndroid Build Coastguard Worker return do_restorecon({.args = std::move(non_const_args), .context = args.context});
1048*00c7fec1SAndroid Build Coastguard Worker }
1049*00c7fec1SAndroid Build Coastguard Worker
do_loglevel(const BuiltinArguments & args)1050*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_loglevel(const BuiltinArguments& args) {
1051*00c7fec1SAndroid Build Coastguard Worker // TODO: support names instead/as well?
1052*00c7fec1SAndroid Build Coastguard Worker int log_level = -1;
1053*00c7fec1SAndroid Build Coastguard Worker android::base::ParseInt(args[1], &log_level);
1054*00c7fec1SAndroid Build Coastguard Worker android::base::LogSeverity severity;
1055*00c7fec1SAndroid Build Coastguard Worker switch (log_level) {
1056*00c7fec1SAndroid Build Coastguard Worker case 7: severity = android::base::DEBUG; break;
1057*00c7fec1SAndroid Build Coastguard Worker case 6: severity = android::base::INFO; break;
1058*00c7fec1SAndroid Build Coastguard Worker case 5:
1059*00c7fec1SAndroid Build Coastguard Worker case 4: severity = android::base::WARNING; break;
1060*00c7fec1SAndroid Build Coastguard Worker case 3: severity = android::base::ERROR; break;
1061*00c7fec1SAndroid Build Coastguard Worker case 2:
1062*00c7fec1SAndroid Build Coastguard Worker case 1:
1063*00c7fec1SAndroid Build Coastguard Worker case 0: severity = android::base::FATAL; break;
1064*00c7fec1SAndroid Build Coastguard Worker default:
1065*00c7fec1SAndroid Build Coastguard Worker return Error() << "invalid log level " << log_level;
1066*00c7fec1SAndroid Build Coastguard Worker }
1067*00c7fec1SAndroid Build Coastguard Worker android::base::SetMinimumLogSeverity(severity);
1068*00c7fec1SAndroid Build Coastguard Worker return {};
1069*00c7fec1SAndroid Build Coastguard Worker }
1070*00c7fec1SAndroid Build Coastguard Worker
do_load_persist_props(const BuiltinArguments & args)1071*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_load_persist_props(const BuiltinArguments& args) {
1072*00c7fec1SAndroid Build Coastguard Worker SendLoadPersistentPropertiesMessage();
1073*00c7fec1SAndroid Build Coastguard Worker
1074*00c7fec1SAndroid Build Coastguard Worker start_waiting_for_property("ro.persistent_properties.ready", "true");
1075*00c7fec1SAndroid Build Coastguard Worker return {};
1076*00c7fec1SAndroid Build Coastguard Worker }
1077*00c7fec1SAndroid Build Coastguard Worker
do_load_system_props(const BuiltinArguments & args)1078*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_load_system_props(const BuiltinArguments& args) {
1079*00c7fec1SAndroid Build Coastguard Worker LOG(INFO) << "deprecated action `load_system_props` called.";
1080*00c7fec1SAndroid Build Coastguard Worker return {};
1081*00c7fec1SAndroid Build Coastguard Worker }
1082*00c7fec1SAndroid Build Coastguard Worker
do_wait(const BuiltinArguments & args)1083*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_wait(const BuiltinArguments& args) {
1084*00c7fec1SAndroid Build Coastguard Worker auto timeout = kCommandRetryTimeout;
1085*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 3) {
1086*00c7fec1SAndroid Build Coastguard Worker double timeout_double;
1087*00c7fec1SAndroid Build Coastguard Worker if (!android::base::ParseDouble(args[2], &timeout_double, 0)) {
1088*00c7fec1SAndroid Build Coastguard Worker return Error() << "failed to parse timeout";
1089*00c7fec1SAndroid Build Coastguard Worker }
1090*00c7fec1SAndroid Build Coastguard Worker timeout = std::chrono::duration_cast<std::chrono::nanoseconds>(
1091*00c7fec1SAndroid Build Coastguard Worker std::chrono::duration<double>(timeout_double));
1092*00c7fec1SAndroid Build Coastguard Worker }
1093*00c7fec1SAndroid Build Coastguard Worker
1094*00c7fec1SAndroid Build Coastguard Worker if (wait_for_file(args[1].c_str(), timeout) != 0) {
1095*00c7fec1SAndroid Build Coastguard Worker return Error() << "wait_for_file() failed";
1096*00c7fec1SAndroid Build Coastguard Worker }
1097*00c7fec1SAndroid Build Coastguard Worker
1098*00c7fec1SAndroid Build Coastguard Worker return {};
1099*00c7fec1SAndroid Build Coastguard Worker }
1100*00c7fec1SAndroid Build Coastguard Worker
do_wait_for_prop(const BuiltinArguments & args)1101*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_wait_for_prop(const BuiltinArguments& args) {
1102*00c7fec1SAndroid Build Coastguard Worker const char* name = args[1].c_str();
1103*00c7fec1SAndroid Build Coastguard Worker const char* value = args[2].c_str();
1104*00c7fec1SAndroid Build Coastguard Worker size_t value_len = strlen(value);
1105*00c7fec1SAndroid Build Coastguard Worker
1106*00c7fec1SAndroid Build Coastguard Worker if (!IsLegalPropertyName(name)) {
1107*00c7fec1SAndroid Build Coastguard Worker return Error() << "IsLegalPropertyName(" << name << ") failed";
1108*00c7fec1SAndroid Build Coastguard Worker }
1109*00c7fec1SAndroid Build Coastguard Worker if (value_len >= PROP_VALUE_MAX) {
1110*00c7fec1SAndroid Build Coastguard Worker return Error() << "value too long";
1111*00c7fec1SAndroid Build Coastguard Worker }
1112*00c7fec1SAndroid Build Coastguard Worker if (!start_waiting_for_property(name, value)) {
1113*00c7fec1SAndroid Build Coastguard Worker return Error() << "already waiting for a property";
1114*00c7fec1SAndroid Build Coastguard Worker }
1115*00c7fec1SAndroid Build Coastguard Worker return {};
1116*00c7fec1SAndroid Build Coastguard Worker }
1117*00c7fec1SAndroid Build Coastguard Worker
is_file_crypto()1118*00c7fec1SAndroid Build Coastguard Worker static bool is_file_crypto() {
1119*00c7fec1SAndroid Build Coastguard Worker return android::base::GetProperty("ro.crypto.type", "") == "file";
1120*00c7fec1SAndroid Build Coastguard Worker }
1121*00c7fec1SAndroid Build Coastguard Worker
ExecWithFunctionOnFailure(const std::vector<std::string> & args,std::function<void (const std::string &)> function)1122*00c7fec1SAndroid Build Coastguard Worker static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& args,
1123*00c7fec1SAndroid Build Coastguard Worker std::function<void(const std::string&)> function) {
1124*00c7fec1SAndroid Build Coastguard Worker auto service = Service::MakeTemporaryOneshotService(args);
1125*00c7fec1SAndroid Build Coastguard Worker if (!service.ok()) {
1126*00c7fec1SAndroid Build Coastguard Worker function("MakeTemporaryOneshotService failed: " + service.error().message());
1127*00c7fec1SAndroid Build Coastguard Worker }
1128*00c7fec1SAndroid Build Coastguard Worker (*service)->AddReapCallback([function](const siginfo_t& siginfo) {
1129*00c7fec1SAndroid Build Coastguard Worker if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
1130*00c7fec1SAndroid Build Coastguard Worker function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
1131*00c7fec1SAndroid Build Coastguard Worker }
1132*00c7fec1SAndroid Build Coastguard Worker });
1133*00c7fec1SAndroid Build Coastguard Worker if (auto result = (*service)->ExecStart(); !result.ok()) {
1134*00c7fec1SAndroid Build Coastguard Worker function("ExecStart failed: " + result.error().message());
1135*00c7fec1SAndroid Build Coastguard Worker }
1136*00c7fec1SAndroid Build Coastguard Worker ServiceList::GetInstance().AddService(std::move(*service));
1137*00c7fec1SAndroid Build Coastguard Worker return {};
1138*00c7fec1SAndroid Build Coastguard Worker }
1139*00c7fec1SAndroid Build Coastguard Worker
ExecVdcRebootOnFailure(const std::string & vdc_arg)1140*00c7fec1SAndroid Build Coastguard Worker static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) {
1141*00c7fec1SAndroid Build Coastguard Worker auto reboot_reason = vdc_arg + "_failed";
1142*00c7fec1SAndroid Build Coastguard Worker
1143*00c7fec1SAndroid Build Coastguard Worker auto reboot = [reboot_reason](const std::string& message) {
1144*00c7fec1SAndroid Build Coastguard Worker // TODO (b/122850122): support this in gsi
1145*00c7fec1SAndroid Build Coastguard Worker if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) {
1146*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
1147*00c7fec1SAndroid Build Coastguard Worker if (auto result = reboot_into_recovery(
1148*00c7fec1SAndroid Build Coastguard Worker {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
1149*00c7fec1SAndroid Build Coastguard Worker !result.ok()) {
1150*00c7fec1SAndroid Build Coastguard Worker LOG(FATAL) << "Could not reboot into recovery: " << result.error();
1151*00c7fec1SAndroid Build Coastguard Worker }
1152*00c7fec1SAndroid Build Coastguard Worker } else {
1153*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
1154*00c7fec1SAndroid Build Coastguard Worker }
1155*00c7fec1SAndroid Build Coastguard Worker };
1156*00c7fec1SAndroid Build Coastguard Worker
1157*00c7fec1SAndroid Build Coastguard Worker std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg};
1158*00c7fec1SAndroid Build Coastguard Worker return ExecWithFunctionOnFailure(args, reboot);
1159*00c7fec1SAndroid Build Coastguard Worker }
1160*00c7fec1SAndroid Build Coastguard Worker
do_installkey(const BuiltinArguments & args)1161*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_installkey(const BuiltinArguments& args) {
1162*00c7fec1SAndroid Build Coastguard Worker if (!is_file_crypto()) return {};
1163*00c7fec1SAndroid Build Coastguard Worker
1164*00c7fec1SAndroid Build Coastguard Worker auto unencrypted_dir = args[1] + fscrypt_unencrypted_folder;
1165*00c7fec1SAndroid Build Coastguard Worker if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
1166*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Failed to create " << unencrypted_dir;
1167*00c7fec1SAndroid Build Coastguard Worker }
1168*00c7fec1SAndroid Build Coastguard Worker return ExecVdcRebootOnFailure("enablefilecrypto");
1169*00c7fec1SAndroid Build Coastguard Worker }
1170*00c7fec1SAndroid Build Coastguard Worker
do_init_user0(const BuiltinArguments & args)1171*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_init_user0(const BuiltinArguments& args) {
1172*00c7fec1SAndroid Build Coastguard Worker return ExecVdcRebootOnFailure("init_user0");
1173*00c7fec1SAndroid Build Coastguard Worker }
1174*00c7fec1SAndroid Build Coastguard Worker
do_mark_post_data(const BuiltinArguments & args)1175*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_mark_post_data(const BuiltinArguments& args) {
1176*00c7fec1SAndroid Build Coastguard Worker LOG(INFO) << "deprecated action `mark_post_data` called.";
1177*00c7fec1SAndroid Build Coastguard Worker return {};
1178*00c7fec1SAndroid Build Coastguard Worker }
1179*00c7fec1SAndroid Build Coastguard Worker
GenerateLinkerConfiguration()1180*00c7fec1SAndroid Build Coastguard Worker static Result<void> GenerateLinkerConfiguration() {
1181*00c7fec1SAndroid Build Coastguard Worker const char* linkerconfig_binary = "/apex/com.android.runtime/bin/linkerconfig";
1182*00c7fec1SAndroid Build Coastguard Worker const char* linkerconfig_target = "/linkerconfig";
1183*00c7fec1SAndroid Build Coastguard Worker const char* arguments[] = {linkerconfig_binary, "--target", linkerconfig_target};
1184*00c7fec1SAndroid Build Coastguard Worker
1185*00c7fec1SAndroid Build Coastguard Worker if (logwrap_fork_execvp(arraysize(arguments), arguments, nullptr, false, LOG_KLOG, false,
1186*00c7fec1SAndroid Build Coastguard Worker nullptr) != 0) {
1187*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "failed to execute linkerconfig";
1188*00c7fec1SAndroid Build Coastguard Worker }
1189*00c7fec1SAndroid Build Coastguard Worker
1190*00c7fec1SAndroid Build Coastguard Worker auto current_mount_ns = GetCurrentMountNamespace();
1191*00c7fec1SAndroid Build Coastguard Worker if (!current_mount_ns.ok()) {
1192*00c7fec1SAndroid Build Coastguard Worker return current_mount_ns.error();
1193*00c7fec1SAndroid Build Coastguard Worker }
1194*00c7fec1SAndroid Build Coastguard Worker if (*current_mount_ns == NS_DEFAULT) {
1195*00c7fec1SAndroid Build Coastguard Worker SetDefaultMountNamespaceReady();
1196*00c7fec1SAndroid Build Coastguard Worker }
1197*00c7fec1SAndroid Build Coastguard Worker
1198*00c7fec1SAndroid Build Coastguard Worker LOG(INFO) << "linkerconfig generated " << linkerconfig_target
1199*00c7fec1SAndroid Build Coastguard Worker << " with mounted APEX modules info";
1200*00c7fec1SAndroid Build Coastguard Worker
1201*00c7fec1SAndroid Build Coastguard Worker return {};
1202*00c7fec1SAndroid Build Coastguard Worker }
1203*00c7fec1SAndroid Build Coastguard Worker
MountLinkerConfigForDefaultNamespace()1204*00c7fec1SAndroid Build Coastguard Worker static Result<void> MountLinkerConfigForDefaultNamespace() {
1205*00c7fec1SAndroid Build Coastguard Worker // No need to mount linkerconfig for default mount namespace if the path does not exist (which
1206*00c7fec1SAndroid Build Coastguard Worker // would mean it is already mounted)
1207*00c7fec1SAndroid Build Coastguard Worker if (access("/linkerconfig/default", 0) != 0) {
1208*00c7fec1SAndroid Build Coastguard Worker return {};
1209*00c7fec1SAndroid Build Coastguard Worker }
1210*00c7fec1SAndroid Build Coastguard Worker
1211*00c7fec1SAndroid Build Coastguard Worker if (mount("/linkerconfig/default", "/linkerconfig", nullptr, MS_BIND | MS_REC, nullptr) != 0) {
1212*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "Failed to mount linker configuration for default mount namespace.";
1213*00c7fec1SAndroid Build Coastguard Worker }
1214*00c7fec1SAndroid Build Coastguard Worker
1215*00c7fec1SAndroid Build Coastguard Worker return {};
1216*00c7fec1SAndroid Build Coastguard Worker }
do_update_linker_config(const BuiltinArguments &)1217*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_update_linker_config(const BuiltinArguments&) {
1218*00c7fec1SAndroid Build Coastguard Worker return GenerateLinkerConfiguration();
1219*00c7fec1SAndroid Build Coastguard Worker }
1220*00c7fec1SAndroid Build Coastguard Worker
1221*00c7fec1SAndroid Build Coastguard Worker /*
1222*00c7fec1SAndroid Build Coastguard Worker * Creates a directory under /data/misc/apexdata/ for each APEX.
1223*00c7fec1SAndroid Build Coastguard Worker */
create_apex_data_dirs()1224*00c7fec1SAndroid Build Coastguard Worker static void create_apex_data_dirs() {
1225*00c7fec1SAndroid Build Coastguard Worker for (const auto& name : GetApexListFrom("/apex")) {
1226*00c7fec1SAndroid Build Coastguard Worker auto path = "/data/misc/apexdata/" + name;
1227*00c7fec1SAndroid Build Coastguard Worker auto options = MkdirOptions{path, 0771, AID_ROOT, AID_SYSTEM, FscryptAction::kNone, "ref"};
1228*00c7fec1SAndroid Build Coastguard Worker auto result = make_dir_with_options(options);
1229*00c7fec1SAndroid Build Coastguard Worker if (!result.ok()) {
1230*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << result.error();
1231*00c7fec1SAndroid Build Coastguard Worker }
1232*00c7fec1SAndroid Build Coastguard Worker }
1233*00c7fec1SAndroid Build Coastguard Worker }
1234*00c7fec1SAndroid Build Coastguard Worker
do_perform_apex_config(const BuiltinArguments & args)1235*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
1236*00c7fec1SAndroid Build Coastguard Worker bool bootstrap = false;
1237*00c7fec1SAndroid Build Coastguard Worker if (args.size() == 2) {
1238*00c7fec1SAndroid Build Coastguard Worker if (args[1] != "--bootstrap") {
1239*00c7fec1SAndroid Build Coastguard Worker return Error() << "Unexpected argument: " << args[1];
1240*00c7fec1SAndroid Build Coastguard Worker }
1241*00c7fec1SAndroid Build Coastguard Worker bootstrap = true;
1242*00c7fec1SAndroid Build Coastguard Worker }
1243*00c7fec1SAndroid Build Coastguard Worker
1244*00c7fec1SAndroid Build Coastguard Worker if (!bootstrap) {
1245*00c7fec1SAndroid Build Coastguard Worker create_apex_data_dirs();
1246*00c7fec1SAndroid Build Coastguard Worker }
1247*00c7fec1SAndroid Build Coastguard Worker
1248*00c7fec1SAndroid Build Coastguard Worker auto parse_result = ParseRcScriptsFromAllApexes(bootstrap);
1249*00c7fec1SAndroid Build Coastguard Worker if (!parse_result.ok()) {
1250*00c7fec1SAndroid Build Coastguard Worker return parse_result.error();
1251*00c7fec1SAndroid Build Coastguard Worker }
1252*00c7fec1SAndroid Build Coastguard Worker
1253*00c7fec1SAndroid Build Coastguard Worker auto update_linker_config = do_update_linker_config(args);
1254*00c7fec1SAndroid Build Coastguard Worker if (!update_linker_config.ok()) {
1255*00c7fec1SAndroid Build Coastguard Worker return update_linker_config.error();
1256*00c7fec1SAndroid Build Coastguard Worker }
1257*00c7fec1SAndroid Build Coastguard Worker
1258*00c7fec1SAndroid Build Coastguard Worker if (!bootstrap) {
1259*00c7fec1SAndroid Build Coastguard Worker ServiceList::GetInstance().StartDelayedServices();
1260*00c7fec1SAndroid Build Coastguard Worker }
1261*00c7fec1SAndroid Build Coastguard Worker return {};
1262*00c7fec1SAndroid Build Coastguard Worker }
1263*00c7fec1SAndroid Build Coastguard Worker
do_enter_default_mount_ns(const BuiltinArguments & args)1264*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
1265*00c7fec1SAndroid Build Coastguard Worker if (auto result = SwitchToMountNamespaceIfNeeded(NS_DEFAULT); !result.ok()) {
1266*00c7fec1SAndroid Build Coastguard Worker return result.error();
1267*00c7fec1SAndroid Build Coastguard Worker }
1268*00c7fec1SAndroid Build Coastguard Worker if (auto result = MountLinkerConfigForDefaultNamespace(); !result.ok()) {
1269*00c7fec1SAndroid Build Coastguard Worker return result.error();
1270*00c7fec1SAndroid Build Coastguard Worker }
1271*00c7fec1SAndroid Build Coastguard Worker LOG(INFO) << "Switched to default mount namespace";
1272*00c7fec1SAndroid Build Coastguard Worker return {};
1273*00c7fec1SAndroid Build Coastguard Worker }
1274*00c7fec1SAndroid Build Coastguard Worker
do_swapoff(const BuiltinArguments & args)1275*00c7fec1SAndroid Build Coastguard Worker static Result<void> do_swapoff(const BuiltinArguments& args) {
1276*00c7fec1SAndroid Build Coastguard Worker if (!swapoff(args[1].c_str())) {
1277*00c7fec1SAndroid Build Coastguard Worker return ErrnoError() << "swapoff() failed";
1278*00c7fec1SAndroid Build Coastguard Worker }
1279*00c7fec1SAndroid Build Coastguard Worker return {};
1280*00c7fec1SAndroid Build Coastguard Worker }
1281*00c7fec1SAndroid Build Coastguard Worker
1282*00c7fec1SAndroid Build Coastguard Worker // Builtin-function-map start
GetBuiltinFunctionMap()1283*00c7fec1SAndroid Build Coastguard Worker const BuiltinFunctionMap& GetBuiltinFunctionMap() {
1284*00c7fec1SAndroid Build Coastguard Worker constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1285*00c7fec1SAndroid Build Coastguard Worker // clang-format off
1286*00c7fec1SAndroid Build Coastguard Worker static const BuiltinFunctionMap builtin_functions = {
1287*00c7fec1SAndroid Build Coastguard Worker {"bootchart", {1, 1, {false, do_bootchart}}},
1288*00c7fec1SAndroid Build Coastguard Worker {"chmod", {2, 2, {true, do_chmod}}},
1289*00c7fec1SAndroid Build Coastguard Worker {"chown", {2, 3, {true, do_chown}}},
1290*00c7fec1SAndroid Build Coastguard Worker {"class_reset", {1, 1, {false, do_class_reset}}},
1291*00c7fec1SAndroid Build Coastguard Worker {"class_restart", {1, 2, {false, do_class_restart}}},
1292*00c7fec1SAndroid Build Coastguard Worker {"class_start", {1, 1, {false, do_class_start}}},
1293*00c7fec1SAndroid Build Coastguard Worker {"class_stop", {1, 1, {false, do_class_stop}}},
1294*00c7fec1SAndroid Build Coastguard Worker {"copy", {2, 2, {true, do_copy}}},
1295*00c7fec1SAndroid Build Coastguard Worker {"copy_per_line", {2, 2, {true, do_copy_per_line}}},
1296*00c7fec1SAndroid Build Coastguard Worker {"domainname", {1, 1, {true, do_domainname}}},
1297*00c7fec1SAndroid Build Coastguard Worker {"enable", {1, 1, {false, do_enable}}},
1298*00c7fec1SAndroid Build Coastguard Worker {"exec", {1, kMax, {false, do_exec}}},
1299*00c7fec1SAndroid Build Coastguard Worker {"exec_background", {1, kMax, {false, do_exec_background}}},
1300*00c7fec1SAndroid Build Coastguard Worker {"exec_start", {1, 1, {false, do_exec_start}}},
1301*00c7fec1SAndroid Build Coastguard Worker {"export", {2, 2, {false, do_export}}},
1302*00c7fec1SAndroid Build Coastguard Worker {"hostname", {1, 1, {true, do_hostname}}},
1303*00c7fec1SAndroid Build Coastguard Worker {"ifup", {1, 1, {true, do_ifup}}},
1304*00c7fec1SAndroid Build Coastguard Worker {"init_user0", {0, 0, {false, do_init_user0}}},
1305*00c7fec1SAndroid Build Coastguard Worker {"insmod", {1, kMax, {true, do_insmod}}},
1306*00c7fec1SAndroid Build Coastguard Worker {"installkey", {1, 1, {false, do_installkey}}},
1307*00c7fec1SAndroid Build Coastguard Worker {"interface_restart", {1, 1, {false, do_interface_restart}}},
1308*00c7fec1SAndroid Build Coastguard Worker {"interface_start", {1, 1, {false, do_interface_start}}},
1309*00c7fec1SAndroid Build Coastguard Worker {"interface_stop", {1, 1, {false, do_interface_stop}}},
1310*00c7fec1SAndroid Build Coastguard Worker {"load_exports", {1, 1, {false, do_load_exports}}},
1311*00c7fec1SAndroid Build Coastguard Worker {"load_persist_props", {0, 0, {false, do_load_persist_props}}},
1312*00c7fec1SAndroid Build Coastguard Worker {"load_system_props", {0, 0, {false, do_load_system_props}}},
1313*00c7fec1SAndroid Build Coastguard Worker {"loglevel", {1, 1, {false, do_loglevel}}},
1314*00c7fec1SAndroid Build Coastguard Worker {"mark_post_data", {0, 0, {false, do_mark_post_data}}},
1315*00c7fec1SAndroid Build Coastguard Worker {"mkdir", {1, 6, {true, do_mkdir}}},
1316*00c7fec1SAndroid Build Coastguard Worker // TODO: Do mount operations in vendor_init.
1317*00c7fec1SAndroid Build Coastguard Worker // mount_all is currently too complex to run in vendor_init as it queues action triggers,
1318*00c7fec1SAndroid Build Coastguard Worker // imports rc scripts, etc. It should be simplified and run in vendor_init context.
1319*00c7fec1SAndroid Build Coastguard Worker // mount and umount are run in the same context as mount_all for symmetry.
1320*00c7fec1SAndroid Build Coastguard Worker {"mount_all", {0, kMax, {false, do_mount_all}}},
1321*00c7fec1SAndroid Build Coastguard Worker {"mount", {3, kMax, {false, do_mount}}},
1322*00c7fec1SAndroid Build Coastguard Worker {"perform_apex_config", {0, 1, {false, do_perform_apex_config}}},
1323*00c7fec1SAndroid Build Coastguard Worker {"umount", {1, 1, {false, do_umount}}},
1324*00c7fec1SAndroid Build Coastguard Worker {"umount_all", {0, 1, {false, do_umount_all}}},
1325*00c7fec1SAndroid Build Coastguard Worker {"update_linker_config", {0, 0, {false, do_update_linker_config}}},
1326*00c7fec1SAndroid Build Coastguard Worker {"readahead", {1, 2, {true, do_readahead}}},
1327*00c7fec1SAndroid Build Coastguard Worker {"restart", {1, 2, {false, do_restart}}},
1328*00c7fec1SAndroid Build Coastguard Worker {"restorecon", {1, kMax, {true, do_restorecon}}},
1329*00c7fec1SAndroid Build Coastguard Worker {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}},
1330*00c7fec1SAndroid Build Coastguard Worker {"rm", {1, 1, {true, do_rm}}},
1331*00c7fec1SAndroid Build Coastguard Worker {"rmdir", {1, 1, {true, do_rmdir}}},
1332*00c7fec1SAndroid Build Coastguard Worker {"setprop", {2, 2, {true, do_setprop}}},
1333*00c7fec1SAndroid Build Coastguard Worker {"setrlimit", {3, 3, {false, do_setrlimit}}},
1334*00c7fec1SAndroid Build Coastguard Worker {"start", {1, 1, {false, do_start}}},
1335*00c7fec1SAndroid Build Coastguard Worker {"stop", {1, 1, {false, do_stop}}},
1336*00c7fec1SAndroid Build Coastguard Worker {"swapon_all", {0, 1, {false, do_swapon_all}}},
1337*00c7fec1SAndroid Build Coastguard Worker {"swapoff", {1, 1, {false, do_swapoff}}},
1338*00c7fec1SAndroid Build Coastguard Worker {"enter_default_mount_ns", {0, 0, {false, do_enter_default_mount_ns}}},
1339*00c7fec1SAndroid Build Coastguard Worker {"symlink", {2, 2, {true, do_symlink}}},
1340*00c7fec1SAndroid Build Coastguard Worker {"sysclktz", {1, 1, {false, do_sysclktz}}},
1341*00c7fec1SAndroid Build Coastguard Worker {"trigger", {1, 1, {false, do_trigger}}},
1342*00c7fec1SAndroid Build Coastguard Worker {"verity_update_state", {0, 0, {false, do_verity_update_state}}},
1343*00c7fec1SAndroid Build Coastguard Worker {"wait", {1, 2, {true, do_wait}}},
1344*00c7fec1SAndroid Build Coastguard Worker {"wait_for_prop", {2, 2, {false, do_wait_for_prop}}},
1345*00c7fec1SAndroid Build Coastguard Worker {"write", {2, 2, {true, do_write}}},
1346*00c7fec1SAndroid Build Coastguard Worker };
1347*00c7fec1SAndroid Build Coastguard Worker // clang-format on
1348*00c7fec1SAndroid Build Coastguard Worker return builtin_functions;
1349*00c7fec1SAndroid Build Coastguard Worker }
1350*00c7fec1SAndroid Build Coastguard Worker // Builtin-function-map end
1351*00c7fec1SAndroid Build Coastguard Worker
1352*00c7fec1SAndroid Build Coastguard Worker } // namespace init
1353*00c7fec1SAndroid Build Coastguard Worker } // namespace android
1354