Home | History | Annotate | Download | only in init
      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 
     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>
     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 
    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 
    115 static Result<Success> do_class_stop(const BuiltinArguments& args) {
    116     ForEachServiceInClass(args[1], &Service::Stop);
    117     return Success();
    118 }
    119 
    120 static Result<Success> do_class_reset(const BuiltinArguments& args) {
    121     ForEachServiceInClass(args[1], &Service::Reset);
    122     return Success();
    123 }
    124 
    125 static Result<Success> do_class_restart(const BuiltinArguments& args) {
    126     ForEachServiceInClass(args[1], &Service::Restart);
    127     return Success();
    128 }
    129 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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]
    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> */
    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> */
    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  */
    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  */
    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  */
    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  */
    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 
    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 
    602 static Result<Success> do_setprop(const BuiltinArguments& args) {
    603     property_set(args[1], args[2]);
    604     return Success();
    605 }
    606 
    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 
    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 
    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 
    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 
    640 static Result<Success> do_trigger(const BuiltinArguments& args) {
    641     ActionManager::GetInstance().QueueEventTrigger(args[1]);
    642     return Success();
    643 }
    644 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    940 static Result<Success> do_load_persist_props(const BuiltinArguments& args) {
    941     load_persist_props();
    942     return Success();
    943 }
    944 
    945 static Result<Success> do_load_system_props(const BuiltinArguments& args) {
    946     load_system_props();
    947     return Success();
    948 }
    949 
    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 
    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 
    984 static bool is_file_crypto() {
    985     return android::base::GetProperty("ro.crypto.type", "") == "file";
    986 }
    987 
    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 
   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 
   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
   1030 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