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