Loading init/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ cc_library_static { "first_stage_mount.cpp", "import_parser.cpp", "init.cpp", "init_first_stage.cpp", "keychords.cpp", "modalias_handler.cpp", "parser.cpp", Loading @@ -115,6 +116,7 @@ cc_library_static { "property_service.cpp", "property_type.cpp", "reboot.cpp", "reboot_utils.cpp", "security.cpp", "selinux.cpp", "service.cpp", Loading init/init.cpp +7 −151 Original line number Diff line number Diff line Loading @@ -18,15 +18,12 @@ #include <dirent.h> #include <fcntl.h> #include <paths.h> #include <pthread.h> #include <seccomp_policy.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <sys/mount.h> #include <sys/signalfd.h> #include <sys/sysmacros.h> #include <sys/types.h> #include <unistd.h> Loading @@ -43,8 +40,6 @@ #include <cutils/android_reboot.h> #include <keyutils.h> #include <libavb/libavb.h> #include <private/android_filesystem_config.h> #include <selinux/android.h> #include "action_parser.h" #include "epoll.h" Loading @@ -53,6 +48,7 @@ #include "keychords.h" #include "property_service.h" #include "reboot.h" #include "reboot_utils.h" #include "security.h" #include "selinux.h" #include "sigchld_handler.h" Loading Loading @@ -417,14 +413,6 @@ static Result<Success> queue_property_triggers_action(const BuiltinArguments& ar return Success(); } static void global_seccomp() { import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) { LOG(FATAL) << "Failed to globally enable seccomp!"; } }); } // Set the UDC controller for the ConfigFS USB Gadgets. // Read the UDC controller in use from "/sys/class/udc". // In case of multiple UDC controllers select the first one. Loading @@ -441,40 +429,6 @@ static void set_usb_controller() { } } static void InstallRebootSignalHandlers() { // Instead of panic'ing the kernel as is the default behavior when init crashes, // we prefer to reboot to bootloader on development builds, as this will prevent // boot looping bad configurations and allow both developers and test farms to easily // recover. struct sigaction action; memset(&action, 0, sizeof(action)); sigfillset(&action.sa_mask); action.sa_handler = [](int signal) { // These signal handlers are also caught for processes forked from init, however we do not // want them to trigger reboot, so we directly call _exit() for children processes here. if (getpid() != 1) { _exit(signal); } // Calling DoReboot() or LOG(FATAL) is not a good option as this is a signal handler. // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option // and probably good enough given this is already an error case and only enabled for // development builds. RebootSystem(ANDROID_RB_RESTART2, "bootloader"); }; action.sa_flags = SA_RESTART; sigaction(SIGABRT, &action, nullptr); sigaction(SIGBUS, &action, nullptr); sigaction(SIGFPE, &action, nullptr); sigaction(SIGILL, &action, nullptr); sigaction(SIGSEGV, &action, nullptr); #if defined(SIGSTKFLT) sigaction(SIGSTKFLT, &action, nullptr); #endif sigaction(SIGSYS, &action, nullptr); sigaction(SIGTRAP, &action, nullptr); } static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { if (siginfo.ssi_pid != 0) { // Drop any userspace SIGTERM requests. Loading Loading @@ -611,6 +565,8 @@ static void InitKernelLogging(char* argv[]) { android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter); } int first_stage_main(int argc, char** argv); int main(int argc, char** argv) { if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc, argv); Loading @@ -622,114 +578,14 @@ int main(int argc, char** argv) { return SubcontextMain(argc, argv, &function_map); } if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr); if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); std::vector<std::pair<std::string, int>> errors; #define CHECKCALL(x) \ if (x != 0) errors.emplace_back(#x " failed", errno); // Clear the umask. umask(0); CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); CHECKCALL(mkdir("/dev/pts", 0755)); CHECKCALL(mkdir("/dev/socket", 0755)); CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); #define MAKE_STR(x) __STRING(x) CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); #undef MAKE_STR // Don't expose the raw commandline to unprivileged processes. CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = { AID_READPROC }; CHECKCALL(setgroups(arraysize(groups), groups)); CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); if constexpr (WORLD_WRITABLE_KMSG) { CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); } CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); // This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3))); // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755)); #undef CHECKCALL // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... InitKernelLogging(argv); if (!errors.empty()) { for (const auto& [error_string, error_errno] : errors) { LOG(ERROR) << error_string << " " << strerror(error_errno); } LOG(FATAL) << "Init encountered errors starting first stage, aborting"; } LOG(INFO) << "init first stage started!"; if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } SetInitAvbVersionInRecovery(); // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote). global_seccomp(); // Set up SELinux, loading the SELinux policy. SelinuxSetupKernelLogging(); SelinuxInitialize(); // We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (selinux_android_restorecon("/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /init failed"; if (getenv("INIT_SECOND_STAGE") == nullptr) { return first_stage_main(argc, argv); } setenv("INIT_SECOND_STAGE", "true", 1); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond; setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1); char* path = argv[0]; char* args[] = { path, nullptr }; execv(path, args); // execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } // At this point we're in the second stage of init. InitKernelLogging(argv); LOG(INFO) << "init second stage started!"; Loading init/init_first_stage.cpp 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <paths.h> #include <seccomp_policy.h> #include <stdlib.h> #include <sys/mount.h> #include <sys/stat.h> #include <sys/sysmacros.h> #include <sys/types.h> #include <unistd.h> #include <string> #include <vector> #include <android-base/chrono_utils.h> #include <android-base/logging.h> #include <cutils/android_reboot.h> #include <private/android_filesystem_config.h> #include <selinux/android.h> #include "first_stage_mount.h" #include "reboot_utils.h" #include "selinux.h" #include "util.h" using android::base::boot_clock; namespace android { namespace init { static void GlobalSeccomp() { import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) { LOG(FATAL) << "Failed to globally enable seccomp!"; } }); } int first_stage_main(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } boot_clock::time_point start_time = boot_clock::now(); std::vector<std::pair<std::string, int>> errors; #define CHECKCALL(x) \ if (x != 0) errors.emplace_back(#x " failed", errno); // Clear the umask. umask(0); CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); CHECKCALL(mkdir("/dev/pts", 0755)); CHECKCALL(mkdir("/dev/socket", 0755)); CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); #define MAKE_STR(x) __STRING(x) CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); #undef MAKE_STR // Don't expose the raw commandline to unprivileged processes. CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = {AID_READPROC}; CHECKCALL(setgroups(arraysize(groups), groups)); CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); if constexpr (WORLD_WRITABLE_KMSG) { CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); } CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); // This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3))); // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755)); #undef CHECKCALL // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); }); if (!errors.empty()) { for (const auto& [error_string, error_errno] : errors) { LOG(ERROR) << error_string << " " << strerror(error_errno); } LOG(FATAL) << "Init encountered errors starting first stage, aborting"; } LOG(INFO) << "init first stage started!"; if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } SetInitAvbVersionInRecovery(); // Does this need to be done in first stage init or can it be done later? // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote). GlobalSeccomp(); // Set up SELinux, loading the SELinux policy. SelinuxSetupKernelLogging(); SelinuxInitialize(); // Unneeded? It's an ext4 file system so shouldn't it have the right domain already? // We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (selinux_android_restorecon("/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /init failed"; } setenv("INIT_SECOND_STAGE", "true", 1); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond; setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1); const char* path = argv[0]; const char* args[] = {path, nullptr}; execv(path, const_cast<char**>(args)); // execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; return 1; } } // namespace init } // namespace android init/reboot.cpp +10 −53 Original line number Diff line number Diff line Loading @@ -20,11 +20,9 @@ #include <fcntl.h> #include <linux/fs.h> #include <mntent.h> #include <sys/capability.h> #include <sys/cdefs.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/reboot.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> Loading @@ -51,9 +49,9 @@ #include <selinux/selinux.h> #include "action_manager.h" #include "capabilities.h" #include "init.h" #include "property_service.h" #include "reboot_utils.h" #include "service.h" #include "sigchld_handler.h" Loading Loading @@ -159,54 +157,6 @@ static void LogShutdownTime(UmountStat stat, Timer* t) { << stat; } bool IsRebootCapable() { if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) { PLOG(WARNING) << "CAP_SYS_BOOT is not supported"; return true; } ScopedCaps caps(cap_get_proc()); if (!caps) { PLOG(WARNING) << "cap_get_proc() failed"; return true; } cap_flag_value_t value = CAP_SET; if (cap_get_flag(caps.get(), CAP_SYS_BOOT, CAP_EFFECTIVE, &value) != 0) { PLOG(WARNING) << "cap_get_flag(CAP_SYS_BOOT, EFFECTIVE) failed"; return true; } return value == CAP_SET; } void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) { LOG(INFO) << "Reboot ending, jumping to kernel"; if (!IsRebootCapable()) { // On systems where init does not have the capability of rebooting the // device, just exit cleanly. exit(0); } switch (cmd) { case ANDROID_RB_POWEROFF: reboot(RB_POWER_OFF); break; case ANDROID_RB_RESTART2: syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str()); break; case ANDROID_RB_THERMOFF: reboot(RB_POWER_OFF); break; } // In normal case, reboot should not return. PLOG(ERROR) << "reboot call returned"; abort(); } /* Find all read+write block devices and emulated devices in /proc/mounts * and add them to correpsponding list. */ Loading Loading @@ -329,7 +279,14 @@ static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeo return stat; } void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, //* Reboot / shutdown the system. // cmd ANDROID_RB_* as defined in android_reboot.h // reason Reason string like "reboot", "shutdown,userrequested" // rebootTarget Reboot target string like "bootloader". Otherwise, it should be an // empty string. // runFsck Whether to run fsck after umount is done. // static void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) { Timer t; LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget; Loading init/reboot.h +0 −17 Original line number Diff line number Diff line Loading @@ -22,26 +22,9 @@ namespace android { namespace init { // This is a wrapper around the actual reboot calls. DoReboot() should be preferred in most cases. void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget); /* Reboot / shutdown the system. * cmd ANDROID_RB_* as defined in android_reboot.h * reason Reason string like "reboot", "shutdown,userrequested" * rebootTarget Reboot target string like "bootloader". Otherwise, it should be an * empty string. * runFsck Whether to run fsck after umount is done. */ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) __attribute__((__noreturn__)); // Parses and handles a setprop sys.powerctl message. bool HandlePowerctlMessage(const std::string& command); // Determines whether the system is capable of rebooting. This is conservative, // so if any of the attempts to determine this fail, it will still return true. bool IsRebootCapable(); } // namespace init } // namespace android Loading Loading
init/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ cc_library_static { "first_stage_mount.cpp", "import_parser.cpp", "init.cpp", "init_first_stage.cpp", "keychords.cpp", "modalias_handler.cpp", "parser.cpp", Loading @@ -115,6 +116,7 @@ cc_library_static { "property_service.cpp", "property_type.cpp", "reboot.cpp", "reboot_utils.cpp", "security.cpp", "selinux.cpp", "service.cpp", Loading
init/init.cpp +7 −151 Original line number Diff line number Diff line Loading @@ -18,15 +18,12 @@ #include <dirent.h> #include <fcntl.h> #include <paths.h> #include <pthread.h> #include <seccomp_policy.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <sys/mount.h> #include <sys/signalfd.h> #include <sys/sysmacros.h> #include <sys/types.h> #include <unistd.h> Loading @@ -43,8 +40,6 @@ #include <cutils/android_reboot.h> #include <keyutils.h> #include <libavb/libavb.h> #include <private/android_filesystem_config.h> #include <selinux/android.h> #include "action_parser.h" #include "epoll.h" Loading @@ -53,6 +48,7 @@ #include "keychords.h" #include "property_service.h" #include "reboot.h" #include "reboot_utils.h" #include "security.h" #include "selinux.h" #include "sigchld_handler.h" Loading Loading @@ -417,14 +413,6 @@ static Result<Success> queue_property_triggers_action(const BuiltinArguments& ar return Success(); } static void global_seccomp() { import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) { LOG(FATAL) << "Failed to globally enable seccomp!"; } }); } // Set the UDC controller for the ConfigFS USB Gadgets. // Read the UDC controller in use from "/sys/class/udc". // In case of multiple UDC controllers select the first one. Loading @@ -441,40 +429,6 @@ static void set_usb_controller() { } } static void InstallRebootSignalHandlers() { // Instead of panic'ing the kernel as is the default behavior when init crashes, // we prefer to reboot to bootloader on development builds, as this will prevent // boot looping bad configurations and allow both developers and test farms to easily // recover. struct sigaction action; memset(&action, 0, sizeof(action)); sigfillset(&action.sa_mask); action.sa_handler = [](int signal) { // These signal handlers are also caught for processes forked from init, however we do not // want them to trigger reboot, so we directly call _exit() for children processes here. if (getpid() != 1) { _exit(signal); } // Calling DoReboot() or LOG(FATAL) is not a good option as this is a signal handler. // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option // and probably good enough given this is already an error case and only enabled for // development builds. RebootSystem(ANDROID_RB_RESTART2, "bootloader"); }; action.sa_flags = SA_RESTART; sigaction(SIGABRT, &action, nullptr); sigaction(SIGBUS, &action, nullptr); sigaction(SIGFPE, &action, nullptr); sigaction(SIGILL, &action, nullptr); sigaction(SIGSEGV, &action, nullptr); #if defined(SIGSTKFLT) sigaction(SIGSTKFLT, &action, nullptr); #endif sigaction(SIGSYS, &action, nullptr); sigaction(SIGTRAP, &action, nullptr); } static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { if (siginfo.ssi_pid != 0) { // Drop any userspace SIGTERM requests. Loading Loading @@ -611,6 +565,8 @@ static void InitKernelLogging(char* argv[]) { android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter); } int first_stage_main(int argc, char** argv); int main(int argc, char** argv) { if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc, argv); Loading @@ -622,114 +578,14 @@ int main(int argc, char** argv) { return SubcontextMain(argc, argv, &function_map); } if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr); if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); std::vector<std::pair<std::string, int>> errors; #define CHECKCALL(x) \ if (x != 0) errors.emplace_back(#x " failed", errno); // Clear the umask. umask(0); CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); CHECKCALL(mkdir("/dev/pts", 0755)); CHECKCALL(mkdir("/dev/socket", 0755)); CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); #define MAKE_STR(x) __STRING(x) CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); #undef MAKE_STR // Don't expose the raw commandline to unprivileged processes. CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = { AID_READPROC }; CHECKCALL(setgroups(arraysize(groups), groups)); CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); if constexpr (WORLD_WRITABLE_KMSG) { CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); } CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); // This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3))); // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755)); #undef CHECKCALL // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... InitKernelLogging(argv); if (!errors.empty()) { for (const auto& [error_string, error_errno] : errors) { LOG(ERROR) << error_string << " " << strerror(error_errno); } LOG(FATAL) << "Init encountered errors starting first stage, aborting"; } LOG(INFO) << "init first stage started!"; if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } SetInitAvbVersionInRecovery(); // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote). global_seccomp(); // Set up SELinux, loading the SELinux policy. SelinuxSetupKernelLogging(); SelinuxInitialize(); // We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (selinux_android_restorecon("/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /init failed"; if (getenv("INIT_SECOND_STAGE") == nullptr) { return first_stage_main(argc, argv); } setenv("INIT_SECOND_STAGE", "true", 1); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond; setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1); char* path = argv[0]; char* args[] = { path, nullptr }; execv(path, args); // execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } // At this point we're in the second stage of init. InitKernelLogging(argv); LOG(INFO) << "init second stage started!"; Loading
init/init_first_stage.cpp 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <paths.h> #include <seccomp_policy.h> #include <stdlib.h> #include <sys/mount.h> #include <sys/stat.h> #include <sys/sysmacros.h> #include <sys/types.h> #include <unistd.h> #include <string> #include <vector> #include <android-base/chrono_utils.h> #include <android-base/logging.h> #include <cutils/android_reboot.h> #include <private/android_filesystem_config.h> #include <selinux/android.h> #include "first_stage_mount.h" #include "reboot_utils.h" #include "selinux.h" #include "util.h" using android::base::boot_clock; namespace android { namespace init { static void GlobalSeccomp() { import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) { LOG(FATAL) << "Failed to globally enable seccomp!"; } }); } int first_stage_main(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); } boot_clock::time_point start_time = boot_clock::now(); std::vector<std::pair<std::string, int>> errors; #define CHECKCALL(x) \ if (x != 0) errors.emplace_back(#x " failed", errno); // Clear the umask. umask(0); CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); CHECKCALL(mkdir("/dev/pts", 0755)); CHECKCALL(mkdir("/dev/socket", 0755)); CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); #define MAKE_STR(x) __STRING(x) CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); #undef MAKE_STR // Don't expose the raw commandline to unprivileged processes. CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = {AID_READPROC}; CHECKCALL(setgroups(arraysize(groups), groups)); CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); if constexpr (WORLD_WRITABLE_KMSG) { CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); } CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); // This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3))); // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755)); #undef CHECKCALL // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); }); if (!errors.empty()) { for (const auto& [error_string, error_errno] : errors) { LOG(ERROR) << error_string << " " << strerror(error_errno); } LOG(FATAL) << "Init encountered errors starting first stage, aborting"; } LOG(INFO) << "init first stage started!"; if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } SetInitAvbVersionInRecovery(); // Does this need to be done in first stage init or can it be done later? // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote). GlobalSeccomp(); // Set up SELinux, loading the SELinux policy. SelinuxSetupKernelLogging(); SelinuxInitialize(); // Unneeded? It's an ext4 file system so shouldn't it have the right domain already? // We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (selinux_android_restorecon("/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /init failed"; } setenv("INIT_SECOND_STAGE", "true", 1); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond; setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1); const char* path = argv[0]; const char* args[] = {path, nullptr}; execv(path, const_cast<char**>(args)); // execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; return 1; } } // namespace init } // namespace android
init/reboot.cpp +10 −53 Original line number Diff line number Diff line Loading @@ -20,11 +20,9 @@ #include <fcntl.h> #include <linux/fs.h> #include <mntent.h> #include <sys/capability.h> #include <sys/cdefs.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/reboot.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> Loading @@ -51,9 +49,9 @@ #include <selinux/selinux.h> #include "action_manager.h" #include "capabilities.h" #include "init.h" #include "property_service.h" #include "reboot_utils.h" #include "service.h" #include "sigchld_handler.h" Loading Loading @@ -159,54 +157,6 @@ static void LogShutdownTime(UmountStat stat, Timer* t) { << stat; } bool IsRebootCapable() { if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) { PLOG(WARNING) << "CAP_SYS_BOOT is not supported"; return true; } ScopedCaps caps(cap_get_proc()); if (!caps) { PLOG(WARNING) << "cap_get_proc() failed"; return true; } cap_flag_value_t value = CAP_SET; if (cap_get_flag(caps.get(), CAP_SYS_BOOT, CAP_EFFECTIVE, &value) != 0) { PLOG(WARNING) << "cap_get_flag(CAP_SYS_BOOT, EFFECTIVE) failed"; return true; } return value == CAP_SET; } void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) { LOG(INFO) << "Reboot ending, jumping to kernel"; if (!IsRebootCapable()) { // On systems where init does not have the capability of rebooting the // device, just exit cleanly. exit(0); } switch (cmd) { case ANDROID_RB_POWEROFF: reboot(RB_POWER_OFF); break; case ANDROID_RB_RESTART2: syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str()); break; case ANDROID_RB_THERMOFF: reboot(RB_POWER_OFF); break; } // In normal case, reboot should not return. PLOG(ERROR) << "reboot call returned"; abort(); } /* Find all read+write block devices and emulated devices in /proc/mounts * and add them to correpsponding list. */ Loading Loading @@ -329,7 +279,14 @@ static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeo return stat; } void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, //* Reboot / shutdown the system. // cmd ANDROID_RB_* as defined in android_reboot.h // reason Reason string like "reboot", "shutdown,userrequested" // rebootTarget Reboot target string like "bootloader". Otherwise, it should be an // empty string. // runFsck Whether to run fsck after umount is done. // static void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) { Timer t; LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget; Loading
init/reboot.h +0 −17 Original line number Diff line number Diff line Loading @@ -22,26 +22,9 @@ namespace android { namespace init { // This is a wrapper around the actual reboot calls. DoReboot() should be preferred in most cases. void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget); /* Reboot / shutdown the system. * cmd ANDROID_RB_* as defined in android_reboot.h * reason Reason string like "reboot", "shutdown,userrequested" * rebootTarget Reboot target string like "bootloader". Otherwise, it should be an * empty string. * runFsck Whether to run fsck after umount is done. */ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) __attribute__((__noreturn__)); // Parses and handles a setprop sys.powerctl message. bool HandlePowerctlMessage(const std::string& command); // Determines whether the system is capable of rebooting. This is conservative, // so if any of the attempts to determine this fail, it will still return true. bool IsRebootCapable(); } // namespace init } // namespace android Loading