init selinux.cpp: use a better way to detect if we run in Microdroid
We are now conditionally compiling init binaries & libinit for
Microdroid (adding -DMICRODROID=1 cflag), so instead of checking for the
presence of the /system/etc/selinux/microdroid_precompiled_sepolicy we
can check if the code is compiled for Microdroid.
In a follow-up changes we can split the sepolicy loading logic into 2
separate headers (one for Android and one for Microdroid) and include
the necessary one depending on the target we compile for.
Bug: 287206497
Test: atest MicrodroidTestApp
Change-Id: Id9c837d03a96ff9564688d33955ec85094eee487
diff --git a/init/selinux.cpp b/init/selinux.cpp
index a936532..e0ef491 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -300,8 +300,6 @@
}
constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
-constexpr const char kMicrodroidPrecompiledSepolicy[] =
- "/system/etc/selinux/microdroid_precompiled_sepolicy";
bool IsSplitPolicyDevice() {
return access(plat_policy_cil_file, R_OK) != -1;
@@ -499,19 +497,14 @@
bool OpenMonolithicPolicy(PolicyFile* policy_file) {
static constexpr char kSepolicyFile[] = "/sepolicy";
- // In Microdroid the precompiled sepolicy is located on /system, since there is no vendor code.
- // TODO(b/287206497): refactor once we start conditionally compiling init for Microdroid.
- std::string monolithic_policy_file = access(kMicrodroidPrecompiledSepolicy, R_OK) == 0
- ? kMicrodroidPrecompiledSepolicy
- : kSepolicyFile;
- LOG(INFO) << "Opening SELinux policy from monolithic file " << monolithic_policy_file;
- policy_file->fd.reset(open(monolithic_policy_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ LOG(INFO) << "Opening SELinux policy from monolithic file " << kSepolicyFile;
+ policy_file->fd.reset(open(kSepolicyFile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (policy_file->fd < 0) {
PLOG(ERROR) << "Failed to open monolithic SELinux policy";
return false;
}
- policy_file->path = monolithic_policy_file;
+ policy_file->path = kSepolicyFile;
return true;
}
@@ -858,6 +851,10 @@
}
int SelinuxGetVendorAndroidVersion() {
+ if (IsMicrodroid()) {
+ // As of now Microdroid doesn't have any vendor code.
+ return __ANDROID_API_FUTURE__;
+ }
static int vendor_android_version = [] {
if (!IsSplitPolicyDevice()) {
// If this device does not split sepolicy files, it's not a Treble device and therefore,
@@ -961,6 +958,26 @@
}
}
+// Encapsulates steps to load SELinux policy in Microdroid.
+// So far the process is very straightforward - just load the precompiled policy from /system.
+void LoadSelinuxPolicyMicrodroid() {
+ constexpr const char kMicrodroidPrecompiledSepolicy[] =
+ "/system/etc/selinux/microdroid_precompiled_sepolicy";
+
+ LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
+ unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ if (policy_fd < 0) {
+ PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
+ }
+
+ std::string policy;
+ if (!android::base::ReadFdToString(policy_fd, &policy)) {
+ PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
+ }
+
+ LoadSelinuxPolicy(policy);
+}
+
// The SELinux setup process is carefully orchestrated around snapuserd. Policy
// must be loaded off dynamic partitions, and during an OTA, those partitions
// cannot be read without snapuserd. But, with kernel-privileged snapuserd
@@ -976,20 +993,9 @@
// (5) Re-launch snapuserd and attach it to the dm-user devices from step (2).
//
// After this sequence, it is safe to enable enforcing mode and continue booting.
-int SetupSelinux(char** argv) {
- SetStdioToDevNull(argv);
- InitKernelLogging(argv);
-
- if (REBOOT_BOOTLOADER_ON_PANIC) {
- InstallRebootSignalHandlers();
- }
-
- boot_clock::time_point start_time = boot_clock::now();
-
+void LoadSelinuxPolicyAndroid() {
MountMissingSystemPartitions();
- SelinuxSetupKernelLogging();
-
LOG(INFO) << "Opening SELinux policy";
PrepareApexSepolicy();
@@ -1001,9 +1007,8 @@
auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
if (snapuserd_helper) {
- // Kill the old snapused to avoid audit messages. After this we cannot
- // read from /system (or other dynamic partitions) until we call
- // FinishTransition().
+ // Kill the old snapused to avoid audit messages. After this we cannot read from /system
+ // (or other dynamic partitions) until we call FinishTransition().
snapuserd_helper->StartTransition();
}
@@ -1021,6 +1026,26 @@
if (selinux_android_restorecon("/dev/selinux/", SELINUX_ANDROID_RESTORECON_RECURSE) == -1) {
PLOG(FATAL) << "restorecon failed of /dev/selinux failed";
}
+}
+
+int SetupSelinux(char** argv) {
+ SetStdioToDevNull(argv);
+ InitKernelLogging(argv);
+
+ if (REBOOT_BOOTLOADER_ON_PANIC) {
+ InstallRebootSignalHandlers();
+ }
+
+ boot_clock::time_point start_time = boot_clock::now();
+
+ SelinuxSetupKernelLogging();
+
+ // TODO(b/287206497): refactor into different headers to only include what we need.
+ if (IsMicrodroid()) {
+ LoadSelinuxPolicyMicrodroid();
+ } else {
+ LoadSelinuxPolicyAndroid();
+ }
SelinuxSetEnforcement();