From 788fc8229c933f44957d27d1447164c0b2538f8d Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Tue, 12 Jun 2018 10:27:28 -0700 Subject: [PATCH] init: Actually check the return value for calls during first stage init Init never checked the return values of the calls made during first stage init (since of course they're not going to fail, right?). But of course commands can fail and they might not necessarily be obvious when they do, so let's make it obvious. Since the kernel log isn't up until later, this creates a list of the failures that can then be sent to the kernel log once it's ready (pending of course failures in setting it up...) Test: boot bullhead, don't see errors Change-Id: I8c12c61fa12e4368346e8b0e1c0bb0844b5d0377 --- init/init.cpp | 52 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/init/init.cpp b/init/init.cpp index 82648d991..b494bcc09 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -604,47 +604,61 @@ int main(int argc, char** argv) { if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); + std::vector> errors; +#define CHECKCALL(x) \ + if (x != 0) errors.emplace_back(#x " failed", errno); + // Clear the umask. umask(0); - clearenv(); - setenv("PATH", _PATH_DEFPATH, 1); + 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. - mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); - mkdir("/dev/pts", 0755); - mkdir("/dev/socket", 0755); - mount("devpts", "/dev/pts", "devpts", 0, NULL); - #define MAKE_STR(x) __STRING(x) - mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); + 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. - chmod("/proc/cmdline", 0440); + CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = { AID_READPROC }; - setgroups(arraysize(groups), groups); - mount("sysfs", "/sys", "sysfs", 0, NULL); - mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL); + CHECKCALL(setgroups(arraysize(groups), groups)); + CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); + CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL)); - mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)); + CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11))); if constexpr (WORLD_WRITABLE_KMSG) { - mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)); + CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11))); } - mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)); - mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)); + CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8))); + CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9))); // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ - mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, - "mode=0755,uid=0,gid=1000"); + 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. - mkdir("/mnt/vendor", 0755); + CHECKCALL(mkdir("/mnt/vendor", 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()) {