xref: /aosp_15_r20/system/core/init/builtins.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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