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