summaryrefslogtreecommitdiffstats
path: root/init/init.cpp
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-04-24 18:38:17 +0000
committerElliott Hughes <enh@google.com>2015-04-24 12:26:05 -0700
commitf65730e620dde083133b8c1ab61c0d07b4dd8c2f (patch)
treea92c5688fc45a24edfc25c9a709086d9d752da05 /init/init.cpp
parent34dd04dbb53bc6dc1ec4f9c6639b10acb7c53c72 (diff)
downloadsystem_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.cpp59
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.