Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48e83e62 authored by Tom Cherry's avatar Tom Cherry
Browse files

init: move InitKernelLogging() to first stage init

The kernel opens /dev/console and uses that fd for stdin/stdout/stderr
if there is a serial console enabled and no initramfs, otherwise it
does not provide any fds for stdin/stdout/stderr.  InitKernelLogging()
is used to close these existing fds if they exist and replace them
with /dev/null.

Currently, InitKernelLogging() is only called in second stage init,
which means that processes exec'ed from first stage init will inherit
the kernel provided fds if any are provided.

In the case that they are provided, the exec of second stage init
causes an SELinux denial as it does not have access to /dev/console.
In the case that they are not provided, exec of any further process is
potentially dangerous as the first fd's opened by that process will
take the stdin/stdout/stderr fileno's, which can cause issues if
printf(), etc is then used by that process.

Lastly, simply moving InitKernelLogging() to first stage init is not
enough, since first stage init still runs in kernel context and future
child processes will not have permissions to access kernel context
resources.  Therefore, it must be done for a second time in second
stage init.

Bug: 117281017
Test: no audits when booting marlin.
Change-Id: If27edab5c32b27765e24c32fbed506ef625889de
parent 3da42a6c
Loading
Loading
Loading
Loading
+2 −18
Original line number Original line Diff line number Diff line
@@ -570,23 +570,6 @@ static void InitAborter(const char* abort_message) {
    RebootSystem(ANDROID_RB_RESTART2, "bootloader");
    RebootSystem(ANDROID_RB_RESTART2, "bootloader");
}
}


static void InitKernelLogging(char* argv[]) {
    // Make stdin/stdout/stderr all point to /dev/null.
    int fd = open("/sys/fs/selinux/null", O_RDWR);
    if (fd == -1) {
        int saved_errno = errno;
        android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
        errno = saved_errno;
        PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
    }
    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    if (fd > 2) close(fd);

    android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
}

static void GlobalSeccomp() {
static void GlobalSeccomp() {
    import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
    import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
                                    bool in_qemu) {
                                    bool in_qemu) {
@@ -643,7 +626,8 @@ int main(int argc, char** argv) {
        SetupSelinux(argv);
        SetupSelinux(argv);
    }
    }


    InitKernelLogging(argv);
    // We need to set up stdin/stdout/stderr again now that we're running in init's context.
    InitKernelLogging(argv, InitAborter);
    LOG(INFO) << "init second stage started!";
    LOG(INFO) << "init second stage started!";


    // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
    // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
+5 −3
Original line number Original line Diff line number Diff line
@@ -99,9 +99,11 @@ int main(int argc, char** argv) {


    // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
    // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
    // talk to the outside world...
    // talk to the outside world...
    android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
    // We need to set up stdin/stdout/stderr for child processes forked from first
        RebootSystem(ANDROID_RB_RESTART2, "bootloader");
    // stage init as part of the mount process.  This closes /dev/console if the
    });
    // kernel had previously opened it.
    auto reboot_bootloader = [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); };
    InitKernelLogging(argv, reboot_bootloader);


    if (!errors.empty()) {
    if (!errors.empty()) {
        for (const auto& [error_string, error_errno] : errors) {
        for (const auto& [error_string, error_errno] : errors) {
+16 −0
Original line number Original line Diff line number Diff line
@@ -436,5 +436,21 @@ bool IsLegalPropertyName(const std::string& name) {
    return true;
    return true;
}
}


void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function) {
    // Make stdin/stdout/stderr all point to /dev/null.
    int fd = open("/dev/null", O_RDWR);
    if (fd == -1) {
        int saved_errno = errno;
        android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
        errno = saved_errno;
        PLOG(FATAL) << "Couldn't open /dev/null";
    }
    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    if (fd > 2) close(fd);
    android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
}

}  // namespace init
}  // namespace init
}  // namespace android
}  // namespace android
+2 −0
Original line number Original line Diff line number Diff line
@@ -64,6 +64,8 @@ bool is_android_dt_value_expected(const std::string& sub_path, const std::string


bool IsLegalPropertyName(const std::string& name);
bool IsLegalPropertyName(const std::string& name);


void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function);

}  // namespace init
}  // namespace init
}  // namespace android
}  // namespace android