init: clean up the 1st/2nd stage init split
The first split of 1st/2nd stage init went a bit overboard, since it
split these even in the case of the recovery image and system-as-root,
which don't actually need the split. This change simplifies this a
bit:
system-as-root and recovery have a single combined /system/bin/init
and a symlink from /init to it.
non-system-as-root has a separate first stage init at /init on the
first stage ramdisk and a combined /system/bin/init on system.img.
Two particular benefits from this:
1) Removal of the rsync of TARGET_RAMDISK_OUT to the recovery image
2) Decrease of overall space on the recovery image since it won't have
a statically linked first stage init
This also unified the various entry points of init to depend entirely
on the arguments passed to it, instead of the hybrid of arguments and
environment variable used previously.
Bug: 80395578
Test: boot both system-as-root and non-system-as-root
Change-Id: Ic2f29b6f56b7defc80eaa0e7cd0c9107e978816f
diff --git a/init/selinux.cpp b/init/selinux.cpp
index fd7e86f..3a09096 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -18,8 +18,8 @@
// for SELinux operation for init.
// When the system boots, there is no SEPolicy present and init is running in the kernel domain.
-// Init loads the SEPolicy from the file system, restores the context of /init based on this
-// SEPolicy, and finally exec()'s itself to run in the proper domain.
+// Init loads the SEPolicy from the file system, restores the context of /system/bin/init based on
+// this SEPolicy, and finally exec()'s itself to run in the proper domain.
// The SEPolicy on Android comes in two variants: monolithic and split.
@@ -58,8 +58,10 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/unique_fd.h>
+#include <cutils/android_reboot.h>
#include <selinux/android.h>
+#include "reboot_utils.h"
#include "util.h"
using android::base::ParseInt;
@@ -379,8 +381,6 @@
return IsSplitPolicyDevice() ? LoadSplitPolicy() : LoadMonolithicPolicy();
}
-} // namespace
-
void SelinuxInitialize() {
Timer t;
@@ -405,6 +405,8 @@
setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
}
+} // namespace
+
// The files and directories that were created before initial sepolicy load or
// files on ramdisk need to have their security context restored to the proper
// value. This must happen before /dev is populated by ueventd.
@@ -496,6 +498,39 @@
return major_version;
}
+// This function initializes SELinux then execs init to run in the init SELinux context.
+int SetupSelinux(char** argv) {
+ android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
+ RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ });
+
+ if (REBOOT_BOOTLOADER_ON_PANIC) {
+ InstallRebootSignalHandlers();
+ }
+
+ // Set up SELinux, loading the SELinux policy.
+ SelinuxSetupKernelLogging();
+ SelinuxInitialize();
+
+ // We're in the kernel domain and want to transition to the init domain. File systems that
+ // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
+ // but other file systems do. In particular, this is needed for ramdisks such as the
+ // recovery image for A/B devices.
+ if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
+ PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
+ }
+
+ const char* path = "/system/bin/init";
+ const char* args[] = {path, "second_stage", nullptr};
+ execv(path, const_cast<char**>(args));
+
+ // execv() only returns if an error happened, in which case we
+ // panic and never return from this function.
+ PLOG(FATAL) << "execv(\"" << path << "\") failed";
+
+ return 1;
+}
+
// selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
// its value. selinux_android_restorecon() also needs an sehandle for file context look up. It
// will create and store its own copy, but selinux_android_set_sehandle() can be used to provide