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