diff options
author | Elliott Hughes <enh@google.com> | 2015-04-24 18:38:17 +0000 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2015-04-24 12:26:05 -0700 |
commit | f65730e620dde083133b8c1ab61c0d07b4dd8c2f (patch) | |
tree | a92c5688fc45a24edfc25c9a709086d9d752da05 /init/init.cpp | |
parent | 34dd04dbb53bc6dc1ec4f9c6639b10acb7c53c72 (diff) | |
download | system_core-f65730e620dde083133b8c1ab61c0d07b4dd8c2f.zip system_core-f65730e620dde083133b8c1ab61c0d07b4dd8c2f.tar.gz system_core-f65730e620dde083133b8c1ab61c0d07b4dd8c2f.tar.bz2 |
Revert "Revert "Make init re-exec itself for its SELinux domain transition.""
This reverts commit 4217374611ada50f33aee544f015f6f9dfbf7ced.
It turns out that the kernel passes any unrecognized arguments on to init,
and (at least) N6 and N9 have such arguments. My lazy check of argc was
thus insufficient to recognize what stage of init we were in, so we'd
skip to stage 2 and not set up SELinux. And apparently you can get a
very long way with SELinux off... We'll fix that in a later change.
Bug: 19702273
Change-Id: I43b3fb722fed35dd217cb529cbcac9a29aff4e4b
Diffstat (limited to 'init/init.cpp')
-rw-r--r-- | init/init.cpp | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/init/init.cpp b/init/init.cpp index b1d65db..661ee2f 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -940,7 +940,13 @@ static int audit_callback(void *data, security_class_t /*cls*/, char *buf, size_ return 0; } -static void selinux_initialize() { +static void security_failure() { + ERROR("Security failure; rebooting into recovery mode...\n"); + android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); + while (true) { pause(); } // never reached +} + +static void selinux_initialize(bool in_kernel_domain) { Timer t; selinux_callback cb; @@ -953,19 +959,27 @@ static void selinux_initialize() { return; } - INFO("Loading SELinux policy...\n"); - if (selinux_android_load_policy() < 0) { - ERROR("SELinux: Failed to load policy; rebooting into recovery mode\n"); - android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); - while (1) { pause(); } // never reached - } + if (in_kernel_domain) { + if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) { + ERROR("couldn't write to /sys/fs/selinux/checkreqprot: %s\n", + strerror(errno)); + security_failure(); + } - selinux_init_all_handles(); - bool is_enforcing = selinux_is_enforcing(); - INFO("SELinux: security_setenforce(%d)\n", is_enforcing); - security_setenforce(is_enforcing); + INFO("Loading SELinux policy...\n"); + if (selinux_android_load_policy() < 0) { + ERROR("failed to load policy: %s\n", strerror(errno)); + security_failure(); + } + + bool is_enforcing = selinux_is_enforcing(); + security_setenforce(is_enforcing); - NOTICE("(Initializing SELinux took %.2fs.)\n", t.duration()); + NOTICE("(Initializing SELinux %s took %.2fs.)\n", + is_enforcing ? "enforcing" : "non-enforcing", t.duration()); + } else { + selinux_init_all_handles(); + } } int main(int argc, char** argv) { @@ -1006,7 +1020,8 @@ int main(int argc, char** argv) { klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); - NOTICE("init started!\n"); + bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0); + NOTICE("init%s started!\n", is_first_stage ? "" : " second stage"); property_init(); @@ -1019,7 +1034,23 @@ int main(int argc, char** argv) { // used by init as well as the current required properties. export_kernel_boot_props(); - selinux_initialize(); + // Set up SELinux, including loading the SELinux policy if we're in the kernel domain. + selinux_initialize(is_first_stage); + + // If we're in the kernel domain, re-exec init to transition to the init domain now + // that the SELinux policy has been loaded. + if (is_first_stage) { + if (restorecon("/init") == -1) { + ERROR("restorecon failed: %s\n", strerror(errno)); + security_failure(); + } + char* path = argv[0]; + char* args[] = { path, const_cast<char*>("--second-stage"), nullptr }; + if (execv(path, args) == -1) { + ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno)); + security_failure(); + } + } // These directories were necessarily created before initial policy load // and therefore need their security context restored to the proper value. |