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 <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <fts.h>
23 #include <linux/loop.h>
24 #include <linux/module.h>
25 #include <mntent.h>
26 #include <net/if.h>
27 #include <sched.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/mount.h>
33 #include <sys/resource.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36 #include <sys/syscall.h>
37 #include <sys/system_properties.h>
38 #include <sys/time.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <unistd.h>
42 
43 #include <android-base/chrono_utils.h>
44 #include <android-base/file.h>
45 #include <android-base/logging.h>
46 #include <android-base/parseint.h>
47 #include <android-base/properties.h>
48 #include <android-base/stringprintf.h>
49 #include <android-base/strings.h>
50 #include <android-base/unique_fd.h>
51 #include <bootloader_message/bootloader_message.h>
52 #include <cutils/android_reboot.h>
53 #include <ext4_utils/ext4_crypt.h>
54 #include <ext4_utils/ext4_crypt_init_extensions.h>
55 #include <fs_mgr.h>
56 #include <selinux/android.h>
57 #include <selinux/label.h>
58 #include <selinux/selinux.h>
59 #include <system/thread_defs.h>
60 
61 #include "action_manager.h"
62 #include "bootchart.h"
63 #include "init.h"
64 #include "parser.h"
65 #include "property_service.h"
66 #include "reboot.h"
67 #include "rlimit_parser.h"
68 #include "selinux.h"
69 #include "service.h"
70 #include "subcontext.h"
71 #include "util.h"
72 
73 using namespace std::literals::string_literals;
74 
75 using android::base::unique_fd;
76 
77 #define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
78 
79 namespace android {
80 namespace init {
81 
82 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
83 
reboot_into_recovery(const std::vector<std::string> & options)84 static Result<Success> reboot_into_recovery(const std::vector<std::string>& options) {
85     LOG(ERROR) << "Rebooting into recovery";
86     std::string err;
87     if (!write_bootloader_message(options, &err)) {
88         return Error() << "Failed to set bootloader message: " << err;
89     }
90     property_set("sys.powerctl", "reboot,recovery");
91     return Success();
92 }
93 
94 template <typename F>
ForEachServiceInClass(const std::string & classname,F function)95 static void ForEachServiceInClass(const std::string& classname, F function) {
96     for (const auto& service : ServiceList::GetInstance()) {
97         if (service->classnames().count(classname)) std::invoke(function, service);
98     }
99 }
100 
do_class_start(const BuiltinArguments & args)101 static Result<Success> do_class_start(const BuiltinArguments& args) {
102     // Starting a class does not start services which are explicitly disabled.
103     // They must  be started individually.
104     for (const auto& service : ServiceList::GetInstance()) {
105         if (service->classnames().count(args[1])) {
106             if (auto result = service->StartIfNotDisabled(); !result) {
107                 LOG(ERROR) << "Could not start service '" << service->name()
108                            << "' as part of class '" << args[1] << "': " << result.error();
109             }
110         }
111     }
112     return Success();
113 }
114 
do_class_stop(const BuiltinArguments & args)115 static Result<Success> do_class_stop(const BuiltinArguments& args) {
116     ForEachServiceInClass(args[1], &Service::Stop);
117     return Success();
118 }
119 
do_class_reset(const BuiltinArguments & args)120 static Result<Success> do_class_reset(const BuiltinArguments& args) {
121     ForEachServiceInClass(args[1], &Service::Reset);
122     return Success();
123 }
124 
do_class_restart(const BuiltinArguments & args)125 static Result<Success> do_class_restart(const BuiltinArguments& args) {
126     ForEachServiceInClass(args[1], &Service::Restart);
127     return Success();
128 }
129 
do_domainname(const BuiltinArguments & args)130 static Result<Success> do_domainname(const BuiltinArguments& args) {
131     if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result) {
132         return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error();
133     }
134     return Success();
135 }
136 
do_enable(const BuiltinArguments & args)137 static Result<Success> do_enable(const BuiltinArguments& args) {
138     Service* svc = ServiceList::GetInstance().FindService(args[1]);
139     if (!svc) return Error() << "Could not find service";
140 
141     if (auto result = svc->Enable(); !result) {
142         return Error() << "Could not enable service: " << result.error();
143     }
144 
145     return Success();
146 }
147 
do_exec(const BuiltinArguments & args)148 static Result<Success> do_exec(const BuiltinArguments& args) {
149     auto service = Service::MakeTemporaryOneshotService(args.args);
150     if (!service) {
151         return Error() << "Could not create exec service";
152     }
153     if (auto result = service->ExecStart(); !result) {
154         return Error() << "Could not start exec service: " << result.error();
155     }
156 
157     ServiceList::GetInstance().AddService(std::move(service));
158     return Success();
159 }
160 
do_exec_background(const BuiltinArguments & args)161 static Result<Success> do_exec_background(const BuiltinArguments& args) {
162     auto service = Service::MakeTemporaryOneshotService(args.args);
163     if (!service) {
164         return Error() << "Could not create exec background service";
165     }
166     if (auto result = service->Start(); !result) {
167         return Error() << "Could not start exec background service: " << result.error();
168     }
169 
170     ServiceList::GetInstance().AddService(std::move(service));
171     return Success();
172 }
173 
do_exec_start(const BuiltinArguments & args)174 static Result<Success> do_exec_start(const BuiltinArguments& args) {
175     Service* service = ServiceList::GetInstance().FindService(args[1]);
176     if (!service) {
177         return Error() << "Service not found";
178     }
179 
180     if (auto result = service->ExecStart(); !result) {
181         return Error() << "Could not start exec service: " << result.error();
182     }
183 
184     return Success();
185 }
186 
do_export(const BuiltinArguments & args)187 static Result<Success> do_export(const BuiltinArguments& args) {
188     if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
189         return ErrnoError() << "setenv() failed";
190     }
191     return Success();
192 }
193 
do_hostname(const BuiltinArguments & args)194 static Result<Success> do_hostname(const BuiltinArguments& args) {
195     if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result) {
196         return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error();
197     }
198     return Success();
199 }
200 
do_ifup(const BuiltinArguments & args)201 static Result<Success> do_ifup(const BuiltinArguments& args) {
202     struct ifreq ifr;
203 
204     strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
205 
206     unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM, 0)));
207     if (s < 0) return ErrnoError() << "opening socket failed";
208 
209     if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
210         return ErrnoError() << "ioctl(..., SIOCGIFFLAGS, ...) failed";
211     }
212 
213     ifr.ifr_flags |= IFF_UP;
214 
215     if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
216         return ErrnoError() << "ioctl(..., SIOCSIFFLAGS, ...) failed";
217     }
218 
219     return Success();
220 }
221 
do_insmod(const BuiltinArguments & args)222 static Result<Success> do_insmod(const BuiltinArguments& args) {
223     int flags = 0;
224     auto it = args.begin() + 1;
225 
226     if (!(*it).compare("-f")) {
227         flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
228         it++;
229     }
230 
231     std::string filename = *it++;
232     std::string options = android::base::Join(std::vector<std::string>(it, args.end()), ' ');
233 
234     unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
235     if (fd == -1) return ErrnoError() << "open(\"" << filename << "\") failed";
236 
237     int rc = syscall(__NR_finit_module, fd.get(), options.c_str(), flags);
238     if (rc == -1) return ErrnoError() << "finit_module for \"" << filename << "\" failed";
239 
240     return Success();
241 }
242 
243 // mkdir <path> [mode] [owner] [group]
do_mkdir(const BuiltinArguments & args)244 static Result<Success> do_mkdir(const BuiltinArguments& args) {
245     mode_t mode = 0755;
246     if (args.size() >= 3) {
247         mode = std::strtoul(args[2].c_str(), 0, 8);
248     }
249 
250     if (!make_dir(args[1], mode)) {
251         /* chmod in case the directory already exists */
252         if (errno == EEXIST) {
253             if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
254                 return ErrnoError() << "fchmodat() failed";
255             }
256         } else {
257             return ErrnoError() << "mkdir() failed";
258         }
259     }
260 
261     if (args.size() >= 4) {
262         auto uid = DecodeUid(args[3]);
263         if (!uid) {
264             return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
265         }
266         Result<gid_t> gid = -1;
267 
268         if (args.size() == 5) {
269             gid = DecodeUid(args[4]);
270             if (!gid) {
271                 return Error() << "Unable to decode GID for '" << args[3] << "': " << gid.error();
272             }
273         }
274 
275         if (lchown(args[1].c_str(), *uid, *gid) == -1) {
276             return ErrnoError() << "lchown failed";
277         }
278 
279         /* chown may have cleared S_ISUID and S_ISGID, chmod again */
280         if (mode & (S_ISUID | S_ISGID)) {
281             if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
282                 return ErrnoError() << "fchmodat failed";
283             }
284         }
285     }
286 
287     if (e4crypt_is_native()) {
288         if (e4crypt_set_directory_policy(args[1].c_str())) {
289             return reboot_into_recovery(
290                 {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
291         }
292     }
293     return Success();
294 }
295 
296 /* umount <path> */
do_umount(const BuiltinArguments & args)297 static Result<Success> do_umount(const BuiltinArguments& args) {
298     if (umount(args[1].c_str()) < 0) {
299         return ErrnoError() << "umount() failed";
300     }
301     return Success();
302 }
303 
304 static struct {
305     const char *name;
306     unsigned flag;
307 } mount_flags[] = {
308     { "noatime",    MS_NOATIME },
309     { "noexec",     MS_NOEXEC },
310     { "nosuid",     MS_NOSUID },
311     { "nodev",      MS_NODEV },
312     { "nodiratime", MS_NODIRATIME },
313     { "ro",         MS_RDONLY },
314     { "rw",         0 },
315     { "remount",    MS_REMOUNT },
316     { "bind",       MS_BIND },
317     { "rec",        MS_REC },
318     { "unbindable", MS_UNBINDABLE },
319     { "private",    MS_PRIVATE },
320     { "slave",      MS_SLAVE },
321     { "shared",     MS_SHARED },
322     { "defaults",   0 },
323     { 0,            0 },
324 };
325 
326 #define DATA_MNT_POINT "/data"
327 
328 /* mount <type> <device> <path> <flags ...> <options> */
do_mount(const BuiltinArguments & args)329 static Result<Success> do_mount(const BuiltinArguments& args) {
330     const char* options = nullptr;
331     unsigned flags = 0;
332     bool wait = false;
333 
334     for (size_t na = 4; na < args.size(); na++) {
335         size_t i;
336         for (i = 0; mount_flags[i].name; i++) {
337             if (!args[na].compare(mount_flags[i].name)) {
338                 flags |= mount_flags[i].flag;
339                 break;
340             }
341         }
342 
343         if (!mount_flags[i].name) {
344             if (!args[na].compare("wait")) {
345                 wait = true;
346                 // If our last argument isn't a flag, wolf it up as an option string.
347             } else if (na + 1 == args.size()) {
348                 options = args[na].c_str();
349             }
350         }
351     }
352 
353     const char* system = args[1].c_str();
354     const char* source = args[2].c_str();
355     const char* target = args[3].c_str();
356 
357     if (android::base::StartsWith(source, "loop@")) {
358         int mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
359         unique_fd fd(TEMP_FAILURE_RETRY(open(source + 5, mode | O_CLOEXEC)));
360         if (fd < 0) return ErrnoError() << "open(" << source + 5 << ", " << mode << ") failed";
361 
362         for (size_t n = 0;; n++) {
363             std::string tmp = android::base::StringPrintf("/dev/block/loop%zu", n);
364             unique_fd loop(TEMP_FAILURE_RETRY(open(tmp.c_str(), mode | O_CLOEXEC)));
365             if (loop < 0) return ErrnoError() << "open(" << tmp << ", " << mode << ") failed";
366 
367             loop_info info;
368             /* if it is a blank loop device */
369             if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
370                 /* if it becomes our loop device */
371                 if (ioctl(loop, LOOP_SET_FD, fd.get()) >= 0) {
372                     if (mount(tmp.c_str(), target, system, flags, options) < 0) {
373                         ioctl(loop, LOOP_CLR_FD, 0);
374                         return ErrnoError() << "mount() failed";
375                     }
376                     return Success();
377                 }
378             }
379         }
380 
381         return Error() << "out of loopback devices";
382     } else {
383         if (wait)
384             wait_for_file(source, kCommandRetryTimeout);
385         if (mount(source, target, system, flags, options) < 0) {
386             return ErrnoError() << "mount() failed";
387         }
388 
389     }
390 
391     return Success();
392 }
393 
394 /* Imports .rc files from the specified paths. Default ones are applied if none is given.
395  *
396  * start_index: index of the first path in the args list
397  */
import_late(const std::vector<std::string> & args,size_t start_index,size_t end_index)398 static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) {
399     auto& action_manager = ActionManager::GetInstance();
400     auto& service_list = ServiceList::GetInstance();
401     Parser parser = CreateParser(action_manager, service_list);
402     if (end_index <= start_index) {
403         // Fallbacks for partitions on which early mount isn't enabled.
404         for (const auto& path : late_import_paths) {
405             parser.ParseConfig(path);
406         }
407         late_import_paths.clear();
408     } else {
409         for (size_t i = start_index; i < end_index; ++i) {
410             parser.ParseConfig(args[i]);
411         }
412     }
413 
414     // Turning this on and letting the INFO logging be discarded adds 0.2s to
415     // Nexus 9 boot time, so it's disabled by default.
416     if (false) DumpState();
417 }
418 
419 /* mount_fstab
420  *
421  *  Call fs_mgr_mount_all() to mount the given fstab
422  */
mount_fstab(const char * fstabfile,int mount_mode)423 static Result<int> mount_fstab(const char* fstabfile, int mount_mode) {
424     /*
425      * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
426      * do the call in the child to provide protection to the main init
427      * process if anything goes wrong (crash or memory leak), and wait for
428      * the child to finish in the parent.
429      */
430     pid_t pid = fork();
431     if (pid > 0) {
432         /* Parent.  Wait for the child to return */
433         int status;
434         int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
435         if (wp_ret == -1) {
436             // Unexpected error code. We will continue anyway.
437             PLOG(WARNING) << "waitpid failed";
438         }
439 
440         if (WIFEXITED(status)) {
441             return WEXITSTATUS(status);
442         } else {
443             return Error() << "child aborted";
444         }
445     } else if (pid == 0) {
446         /* child, call fs_mgr_mount_all() */
447 
448         // So we can always see what fs_mgr_mount_all() does.
449         // Only needed if someone explicitly changes the default log level in their init.rc.
450         android::base::ScopedLogSeverity info(android::base::INFO);
451 
452         struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
453         int child_ret = fs_mgr_mount_all(fstab, mount_mode);
454         fs_mgr_free_fstab(fstab);
455         if (child_ret == -1) {
456             PLOG(ERROR) << "fs_mgr_mount_all returned an error";
457         }
458         _exit(child_ret);
459     } else {
460         return Error() << "fork() failed";
461     }
462 }
463 
464 /* Queue event based on fs_mgr return code.
465  *
466  * code: return code of fs_mgr_mount_all
467  *
468  * This function might request a reboot, in which case it will
469  * not return.
470  *
471  * return code is processed based on input code
472  */
queue_fs_event(int code)473 static Result<Success> queue_fs_event(int code) {
474     if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
475         ActionManager::GetInstance().QueueEventTrigger("encrypt");
476         return Success();
477     } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
478         property_set("ro.crypto.state", "encrypted");
479         property_set("ro.crypto.type", "block");
480         ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
481         return Success();
482     } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
483         property_set("ro.crypto.state", "unencrypted");
484         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
485         return Success();
486     } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
487         property_set("ro.crypto.state", "unsupported");
488         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
489         return Success();
490     } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
491         /* Setup a wipe via recovery, and reboot into recovery */
492         PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
493         const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
494         return reboot_into_recovery(options);
495         /* If reboot worked, there is no return. */
496     } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
497         if (e4crypt_install_keyring()) {
498             return Error() << "e4crypt_install_keyring() failed";
499         }
500         property_set("ro.crypto.state", "encrypted");
501         property_set("ro.crypto.type", "file");
502 
503         // Although encrypted, we have device key, so we do not need to
504         // do anything different from the nonencrypted case.
505         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
506         return Success();
507     } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
508         if (e4crypt_install_keyring()) {
509             return Error() << "e4crypt_install_keyring() failed";
510         }
511         property_set("ro.crypto.state", "encrypted");
512         property_set("ro.crypto.type", "file");
513 
514         // Although encrypted, vold has already set the device up, so we do not need to
515         // do anything different from the nonencrypted case.
516         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
517         return Success();
518     } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
519         if (e4crypt_install_keyring()) {
520             return Error() << "e4crypt_install_keyring() failed";
521         }
522         property_set("ro.crypto.state", "encrypted");
523         property_set("ro.crypto.type", "file");
524 
525         // Although encrypted, vold has already set the device up, so we do not need to
526         // do anything different from the nonencrypted case.
527         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
528         return Success();
529     } else if (code > 0) {
530         Error() << "fs_mgr_mount_all() returned unexpected error " << code;
531     }
532     /* else ... < 0: error */
533 
534     return Error() << "Invalid code: " << code;
535 }
536 
537 /* mount_all <fstab> [ <path> ]* [--<options>]*
538  *
539  * This function might request a reboot, in which case it will
540  * not return.
541  */
do_mount_all(const BuiltinArguments & args)542 static Result<Success> do_mount_all(const BuiltinArguments& args) {
543     std::size_t na = 0;
544     bool import_rc = true;
545     bool queue_event = true;
546     int mount_mode = MOUNT_MODE_DEFAULT;
547     const char* fstabfile = args[1].c_str();
548     std::size_t path_arg_end = args.size();
549     const char* prop_post_fix = "default";
550 
551     for (na = args.size() - 1; na > 1; --na) {
552         if (args[na] == "--early") {
553             path_arg_end = na;
554             queue_event = false;
555             mount_mode = MOUNT_MODE_EARLY;
556             prop_post_fix = "early";
557         } else if (args[na] == "--late") {
558             path_arg_end = na;
559             import_rc = false;
560             mount_mode = MOUNT_MODE_LATE;
561             prop_post_fix = "late";
562         }
563     }
564 
565     std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
566     android::base::Timer t;
567     auto mount_fstab_return_code = mount_fstab(fstabfile, mount_mode);
568     if (!mount_fstab_return_code) {
569         return Error() << "mount_fstab() failed " << mount_fstab_return_code.error();
570     }
571     property_set(prop_name, std::to_string(t.duration().count()));
572 
573     if (import_rc) {
574         /* Paths of .rc files are specified at the 2nd argument and beyond */
575         import_late(args.args, 2, path_arg_end);
576     }
577 
578     if (queue_event) {
579         /* queue_fs_event will queue event based on mount_fstab return code
580          * and return processed return code*/
581         auto queue_fs_result = queue_fs_event(*mount_fstab_return_code);
582         if (!queue_fs_result) {
583             return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
584         }
585     }
586 
587     return Success();
588 }
589 
do_swapon_all(const BuiltinArguments & args)590 static Result<Success> do_swapon_all(const BuiltinArguments& args) {
591     struct fstab *fstab;
592     int ret;
593 
594     fstab = fs_mgr_read_fstab(args[1].c_str());
595     ret = fs_mgr_swapon_all(fstab);
596     fs_mgr_free_fstab(fstab);
597 
598     if (ret != 0) return Error() << "fs_mgr_swapon_all() failed";
599     return Success();
600 }
601 
do_setprop(const BuiltinArguments & args)602 static Result<Success> do_setprop(const BuiltinArguments& args) {
603     property_set(args[1], args[2]);
604     return Success();
605 }
606 
do_setrlimit(const BuiltinArguments & args)607 static Result<Success> do_setrlimit(const BuiltinArguments& args) {
608     auto rlimit = ParseRlimit(args.args);
609     if (!rlimit) return rlimit.error();
610 
611     if (setrlimit(rlimit->first, &rlimit->second) == -1) {
612         return ErrnoError() << "setrlimit failed";
613     }
614     return Success();
615 }
616 
do_start(const BuiltinArguments & args)617 static Result<Success> do_start(const BuiltinArguments& args) {
618     Service* svc = ServiceList::GetInstance().FindService(args[1]);
619     if (!svc) return Error() << "service " << args[1] << " not found";
620     if (auto result = svc->Start(); !result) {
621         return Error() << "Could not start service: " << result.error();
622     }
623     return Success();
624 }
625 
do_stop(const BuiltinArguments & args)626 static Result<Success> do_stop(const BuiltinArguments& args) {
627     Service* svc = ServiceList::GetInstance().FindService(args[1]);
628     if (!svc) return Error() << "service " << args[1] << " not found";
629     svc->Stop();
630     return Success();
631 }
632 
do_restart(const BuiltinArguments & args)633 static Result<Success> do_restart(const BuiltinArguments& args) {
634     Service* svc = ServiceList::GetInstance().FindService(args[1]);
635     if (!svc) return Error() << "service " << args[1] << " not found";
636     svc->Restart();
637     return Success();
638 }
639 
do_trigger(const BuiltinArguments & args)640 static Result<Success> do_trigger(const BuiltinArguments& args) {
641     ActionManager::GetInstance().QueueEventTrigger(args[1]);
642     return Success();
643 }
644 
MakeSymlink(const std::string & target,const std::string & linkpath)645 static int MakeSymlink(const std::string& target, const std::string& linkpath) {
646     std::string secontext;
647     // Passing 0 for mode should work.
648     if (SelabelLookupFileContext(linkpath, 0, &secontext) && !secontext.empty()) {
649         setfscreatecon(secontext.c_str());
650     }
651 
652     int rc = symlink(target.c_str(), linkpath.c_str());
653 
654     if (!secontext.empty()) {
655         int save_errno = errno;
656         setfscreatecon(nullptr);
657         errno = save_errno;
658     }
659 
660     return rc;
661 }
662 
do_symlink(const BuiltinArguments & args)663 static Result<Success> do_symlink(const BuiltinArguments& args) {
664     if (MakeSymlink(args[1], args[2]) < 0) {
665         // The symlink builtin is often used to create symlinks for older devices to be backwards
666         // compatible with new paths, therefore we skip reporting this error.
667         if (errno == EEXIST && android::base::GetMinimumLogSeverity() > android::base::DEBUG) {
668             return Success();
669         }
670         return ErrnoError() << "symlink() failed";
671     }
672     return Success();
673 }
674 
do_rm(const BuiltinArguments & args)675 static Result<Success> do_rm(const BuiltinArguments& args) {
676     if (unlink(args[1].c_str()) < 0) {
677         return ErrnoError() << "unlink() failed";
678     }
679     return Success();
680 }
681 
do_rmdir(const BuiltinArguments & args)682 static Result<Success> do_rmdir(const BuiltinArguments& args) {
683     if (rmdir(args[1].c_str()) < 0) {
684         return ErrnoError() << "rmdir() failed";
685     }
686     return Success();
687 }
688 
do_sysclktz(const BuiltinArguments & args)689 static Result<Success> do_sysclktz(const BuiltinArguments& args) {
690     struct timezone tz = {};
691     if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
692         return Error() << "Unable to parse mins_west_of_gmt";
693     }
694 
695     if (settimeofday(nullptr, &tz) == -1) {
696         return ErrnoError() << "settimeofday() failed";
697     }
698     return Success();
699 }
700 
do_verity_load_state(const BuiltinArguments & args)701 static Result<Success> do_verity_load_state(const BuiltinArguments& args) {
702     int mode = -1;
703     bool loaded = fs_mgr_load_verity_state(&mode);
704     if (loaded && mode != VERITY_MODE_DEFAULT) {
705         ActionManager::GetInstance().QueueEventTrigger("verity-logging");
706     }
707     if (!loaded) return Error() << "Could not load verity state";
708 
709     return Success();
710 }
711 
verity_update_property(fstab_rec * fstab,const char * mount_point,int mode,int status)712 static void verity_update_property(fstab_rec *fstab, const char *mount_point,
713                                    int mode, int status) {
714     property_set("partition."s + mount_point + ".verified", std::to_string(mode));
715 }
716 
do_verity_update_state(const BuiltinArguments & args)717 static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
718     if (!fs_mgr_update_verity_state(verity_update_property)) {
719         return Error() << "fs_mgr_update_verity_state() failed";
720     }
721     return Success();
722 }
723 
do_write(const BuiltinArguments & args)724 static Result<Success> do_write(const BuiltinArguments& args) {
725     if (auto result = WriteFile(args[1], args[2]); !result) {
726         return Error() << "Unable to write to file '" << args[1] << "': " << result.error();
727     }
728 
729     return Success();
730 }
731 
readahead_file(const std::string & filename,bool fully)732 static Result<Success> readahead_file(const std::string& filename, bool fully) {
733     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)));
734     if (fd == -1) {
735         return ErrnoError() << "Error opening file";
736     }
737     if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED)) {
738         return ErrnoError() << "Error posix_fadvise file";
739     }
740     if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
741         return ErrnoError() << "Error readahead file";
742     }
743     if (fully) {
744         char buf[BUFSIZ];
745         ssize_t n;
746         while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
747         }
748         if (n != 0) {
749             return ErrnoError() << "Error reading file";
750         }
751     }
752     return Success();
753 }
754 
do_readahead(const BuiltinArguments & args)755 static Result<Success> do_readahead(const BuiltinArguments& args) {
756     struct stat sb;
757 
758     if (stat(args[1].c_str(), &sb)) {
759         return ErrnoError() << "Error opening " << args[1];
760     }
761 
762     bool readfully = false;
763     if (args.size() == 3 && args[2] == "--fully") {
764         readfully = true;
765     }
766     // We will do readahead in a forked process in order not to block init
767     // since it may block while it reads the
768     // filesystem metadata needed to locate the requested blocks.  This
769     // occurs frequently with ext[234] on large files using indirect blocks
770     // instead of extents, giving the appearance that the call blocks until
771     // the requested data has been read.
772     pid_t pid = fork();
773     if (pid == 0) {
774         if (setpriority(PRIO_PROCESS, 0, static_cast<int>(ANDROID_PRIORITY_LOWEST)) != 0) {
775             PLOG(WARNING) << "setpriority failed";
776         }
777         if (android_set_ioprio(0, IoSchedClass_IDLE, 7)) {
778             PLOG(WARNING) << "ioprio_get failed";
779         }
780         android::base::Timer t;
781         if (S_ISREG(sb.st_mode)) {
782             if (auto result = readahead_file(args[1], readfully); !result) {
783                 LOG(WARNING) << "Unable to readahead '" << args[1] << "': " << result.error();
784                 _exit(EXIT_FAILURE);
785             }
786         } else if (S_ISDIR(sb.st_mode)) {
787             char* paths[] = {const_cast<char*>(args[1].data()), nullptr};
788             std::unique_ptr<FTS, decltype(&fts_close)> fts(
789                 fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr), fts_close);
790             if (!fts) {
791                 PLOG(ERROR) << "Error opening directory: " << args[1];
792                 _exit(EXIT_FAILURE);
793             }
794             // Traverse the entire hierarchy and do readahead
795             for (FTSENT* ftsent = fts_read(fts.get()); ftsent != nullptr;
796                  ftsent = fts_read(fts.get())) {
797                 if (ftsent->fts_info & FTS_F) {
798                     const std::string filename = ftsent->fts_accpath;
799                     if (auto result = readahead_file(filename, readfully); !result) {
800                         LOG(WARNING)
801                             << "Unable to readahead '" << filename << "': " << result.error();
802                     }
803                 }
804             }
805         }
806         LOG(INFO) << "Readahead " << args[1] << " took " << t << " asynchronously";
807         _exit(0);
808     } else if (pid < 0) {
809         return ErrnoError() << "Fork failed";
810     }
811     return Success();
812 }
813 
do_copy(const BuiltinArguments & args)814 static Result<Success> do_copy(const BuiltinArguments& args) {
815     auto file_contents = ReadFile(args[1]);
816     if (!file_contents) {
817         return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error();
818     }
819     if (auto result = WriteFile(args[2], *file_contents); !result) {
820         return Error() << "Could not write to output file '" << args[2] << "': " << result.error();
821     }
822 
823     return Success();
824 }
825 
do_chown(const BuiltinArguments & args)826 static Result<Success> do_chown(const BuiltinArguments& args) {
827     auto uid = DecodeUid(args[1]);
828     if (!uid) {
829         return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
830     }
831 
832     // GID is optional and pushes the index of path out by one if specified.
833     const std::string& path = (args.size() == 4) ? args[3] : args[2];
834     Result<gid_t> gid = -1;
835 
836     if (args.size() == 4) {
837         gid = DecodeUid(args[2]);
838         if (!gid) {
839             return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
840         }
841     }
842 
843     if (lchown(path.c_str(), *uid, *gid) == -1) {
844         return ErrnoError() << "lchown() failed";
845     }
846 
847     return Success();
848 }
849 
get_mode(const char * s)850 static mode_t get_mode(const char *s) {
851     mode_t mode = 0;
852     while (*s) {
853         if (*s >= '0' && *s <= '7') {
854             mode = (mode<<3) | (*s-'0');
855         } else {
856             return -1;
857         }
858         s++;
859     }
860     return mode;
861 }
862 
do_chmod(const BuiltinArguments & args)863 static Result<Success> do_chmod(const BuiltinArguments& args) {
864     mode_t mode = get_mode(args[1].c_str());
865     if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
866         return ErrnoError() << "fchmodat() failed";
867     }
868     return Success();
869 }
870 
do_restorecon(const BuiltinArguments & args)871 static Result<Success> do_restorecon(const BuiltinArguments& args) {
872     int ret = 0;
873 
874     struct flag_type {const char* name; int value;};
875     static const flag_type flags[] = {
876         {"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
877         {"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
878         {"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
879         {0, 0}
880     };
881 
882     int flag = 0;
883 
884     bool in_flags = true;
885     for (size_t i = 1; i < args.size(); ++i) {
886         if (android::base::StartsWith(args[i], "--")) {
887             if (!in_flags) {
888                 return Error() << "flags must precede paths";
889             }
890             bool found = false;
891             for (size_t j = 0; flags[j].name; ++j) {
892                 if (args[i] == flags[j].name) {
893                     flag |= flags[j].value;
894                     found = true;
895                     break;
896                 }
897             }
898             if (!found) {
899                 return Error() << "bad flag " << args[i];
900             }
901         } else {
902             in_flags = false;
903             if (selinux_android_restorecon(args[i].c_str(), flag) < 0) {
904                 ret = errno;
905             }
906         }
907     }
908 
909     if (ret) return ErrnoError() << "selinux_android_restorecon() failed";
910     return Success();
911 }
912 
do_restorecon_recursive(const BuiltinArguments & args)913 static Result<Success> do_restorecon_recursive(const BuiltinArguments& args) {
914     std::vector<std::string> non_const_args(args.args);
915     non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
916     return do_restorecon({std::move(non_const_args), args.context});
917 }
918 
do_loglevel(const BuiltinArguments & args)919 static Result<Success> do_loglevel(const BuiltinArguments& args) {
920     // TODO: support names instead/as well?
921     int log_level = -1;
922     android::base::ParseInt(args[1], &log_level);
923     android::base::LogSeverity severity;
924     switch (log_level) {
925         case 7: severity = android::base::DEBUG; break;
926         case 6: severity = android::base::INFO; break;
927         case 5:
928         case 4: severity = android::base::WARNING; break;
929         case 3: severity = android::base::ERROR; break;
930         case 2:
931         case 1:
932         case 0: severity = android::base::FATAL; break;
933         default:
934             return Error() << "invalid log level " << log_level;
935     }
936     android::base::SetMinimumLogSeverity(severity);
937     return Success();
938 }
939 
do_load_persist_props(const BuiltinArguments & args)940 static Result<Success> do_load_persist_props(const BuiltinArguments& args) {
941     load_persist_props();
942     return Success();
943 }
944 
do_load_system_props(const BuiltinArguments & args)945 static Result<Success> do_load_system_props(const BuiltinArguments& args) {
946     load_system_props();
947     return Success();
948 }
949 
do_wait(const BuiltinArguments & args)950 static Result<Success> do_wait(const BuiltinArguments& args) {
951     auto timeout = kCommandRetryTimeout;
952     if (args.size() == 3) {
953         int timeout_int;
954         if (!android::base::ParseInt(args[2], &timeout_int)) {
955             return Error() << "failed to parse timeout";
956         }
957         timeout = std::chrono::seconds(timeout_int);
958     }
959 
960     if (wait_for_file(args[1].c_str(), timeout) != 0) {
961         return Error() << "wait_for_file() failed";
962     }
963 
964     return Success();
965 }
966 
do_wait_for_prop(const BuiltinArguments & args)967 static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
968     const char* name = args[1].c_str();
969     const char* value = args[2].c_str();
970     size_t value_len = strlen(value);
971 
972     if (!IsLegalPropertyName(name)) {
973         return Error() << "IsLegalPropertyName(" << name << ") failed";
974     }
975     if (value_len >= PROP_VALUE_MAX) {
976         return Error() << "value too long";
977     }
978     if (!start_waiting_for_property(name, value)) {
979         return Error() << "already waiting for a property";
980     }
981     return Success();
982 }
983 
is_file_crypto()984 static bool is_file_crypto() {
985     return android::base::GetProperty("ro.crypto.type", "") == "file";
986 }
987 
ExecWithRebootOnFailure(const std::string & reboot_reason,const BuiltinArguments & args)988 static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
989                                                const BuiltinArguments& args) {
990     auto service = Service::MakeTemporaryOneshotService(args.args);
991     if (!service) {
992         return Error() << "Could not create exec service";
993     }
994     service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
995         if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
996             if (e4crypt_is_native()) {
997                 LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
998                 reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + reboot_reason});
999             } else {
1000                 LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
1001             }
1002         }
1003     });
1004     if (auto result = service->ExecStart(); !result) {
1005         return Error() << "Could not start exec service: " << result.error();
1006     }
1007     ServiceList::GetInstance().AddService(std::move(service));
1008     return Success();
1009 }
1010 
do_installkey(const BuiltinArguments & args)1011 static Result<Success> do_installkey(const BuiltinArguments& args) {
1012     if (!is_file_crypto()) return Success();
1013 
1014     auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder;
1015     if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
1016         return ErrnoError() << "Failed to create " << unencrypted_dir;
1017     }
1018     return ExecWithRebootOnFailure(
1019         "enablefilecrypto_failed",
1020         {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context});
1021 }
1022 
do_init_user0(const BuiltinArguments & args)1023 static Result<Success> do_init_user0(const BuiltinArguments& args) {
1024     return ExecWithRebootOnFailure(
1025         "init_user0_failed",
1026         {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
1027 }
1028 
1029 // Builtin-function-map start
map() const1030 const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
1031     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1032     // clang-format off
1033     static const Map builtin_functions = {
1034         {"bootchart",               {1,     1,    {false,  do_bootchart}}},
1035         {"chmod",                   {2,     2,    {true,   do_chmod}}},
1036         {"chown",                   {2,     3,    {true,   do_chown}}},
1037         {"class_reset",             {1,     1,    {false,  do_class_reset}}},
1038         {"class_restart",           {1,     1,    {false,  do_class_restart}}},
1039         {"class_start",             {1,     1,    {false,  do_class_start}}},
1040         {"class_stop",              {1,     1,    {false,  do_class_stop}}},
1041         {"copy",                    {2,     2,    {true,   do_copy}}},
1042         {"domainname",              {1,     1,    {true,   do_domainname}}},
1043         {"enable",                  {1,     1,    {false,  do_enable}}},
1044         {"exec",                    {1,     kMax, {false,  do_exec}}},
1045         {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
1046         {"exec_start",              {1,     1,    {false,  do_exec_start}}},
1047         {"export",                  {2,     2,    {false,  do_export}}},
1048         {"hostname",                {1,     1,    {true,   do_hostname}}},
1049         {"ifup",                    {1,     1,    {true,   do_ifup}}},
1050         {"init_user0",              {0,     0,    {false,  do_init_user0}}},
1051         {"insmod",                  {1,     kMax, {true,   do_insmod}}},
1052         {"installkey",              {1,     1,    {false,  do_installkey}}},
1053         {"load_persist_props",      {0,     0,    {false,  do_load_persist_props}}},
1054         {"load_system_props",       {0,     0,    {false,  do_load_system_props}}},
1055         {"loglevel",                {1,     1,    {false,  do_loglevel}}},
1056         {"mkdir",                   {1,     4,    {true,   do_mkdir}}},
1057         // TODO: Do mount operations in vendor_init.
1058         // mount_all is currently too complex to run in vendor_init as it queues action triggers,
1059         // imports rc scripts, etc.  It should be simplified and run in vendor_init context.
1060         // mount and umount are run in the same context as mount_all for symmetry.
1061         {"mount_all",               {1,     kMax, {false,  do_mount_all}}},
1062         {"mount",                   {3,     kMax, {false,  do_mount}}},
1063         {"umount",                  {1,     1,    {false,  do_umount}}},
1064         {"readahead",               {1,     2,    {true,   do_readahead}}},
1065         {"restart",                 {1,     1,    {false,  do_restart}}},
1066         {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
1067         {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
1068         {"rm",                      {1,     1,    {true,   do_rm}}},
1069         {"rmdir",                   {1,     1,    {true,   do_rmdir}}},
1070         {"setprop",                 {2,     2,    {true,   do_setprop}}},
1071         {"setrlimit",               {3,     3,    {false,  do_setrlimit}}},
1072         {"start",                   {1,     1,    {false,  do_start}}},
1073         {"stop",                    {1,     1,    {false,  do_stop}}},
1074         {"swapon_all",              {1,     1,    {false,  do_swapon_all}}},
1075         {"symlink",                 {2,     2,    {true,   do_symlink}}},
1076         {"sysclktz",                {1,     1,    {false,  do_sysclktz}}},
1077         {"trigger",                 {1,     1,    {false,  do_trigger}}},
1078         {"verity_load_state",       {0,     0,    {false,  do_verity_load_state}}},
1079         {"verity_update_state",     {0,     0,    {false,  do_verity_update_state}}},
1080         {"wait",                    {1,     2,    {true,   do_wait}}},
1081         {"wait_for_prop",           {2,     2,    {false,  do_wait_for_prop}}},
1082         {"write",                   {2,     2,    {true,   do_write}}},
1083     };
1084     // clang-format on
1085     return builtin_functions;
1086 }
1087 // Builtin-function-map end
1088 
1089 }  // namespace init
1090 }  // namespace android
1091