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/Android.bp b/init/Android.bp
index f62d7b7..06060db 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -214,8 +214,8 @@
     visibility: [":__subpackages__"],
 }
 
-cc_library_static {
-    name: "libinit",
+cc_defaults {
+    name: "libinit_defaults",
     recovery_available: true,
     defaults: [
         "init_defaults",
@@ -252,10 +252,17 @@
             ],
         },
     },
-    visibility: [
-        "//system/apex/apexd",
-        "//frameworks/native/cmds/installd",
-    ],
+}
+
+cc_library_static {
+    name: "libinit",
+    defaults: ["libinit_defaults"],
+}
+
+cc_library_static {
+    name: "libinit.microdroid",
+    defaults: ["libinit_defaults"],
+    cflags: ["-DMICRODROID=1"],
 }
 
 phony {
@@ -270,7 +277,6 @@
     recovery_available: true,
     stem: "init",
     defaults: ["init_defaults"],
-    static_libs: ["libinit"],
     srcs: ["main.cpp"],
     symlinks: ["ueventd"],
     target: {
@@ -309,12 +315,14 @@
 cc_binary {
     name: "init_second_stage",
     defaults: ["init_second_stage_defaults"],
+    static_libs: ["libinit"],
 }
 
 cc_binary {
     name: "init_second_stage.microdroid",
     defaults: ["init_second_stage_defaults"],
-    cflags: ["-DMICRODROID"],
+    static_libs: ["libinit.microdroid"],
+    cflags: ["-DMICRODROID=1"],
     installable: false,
     visibility: ["//packages/modules/Virtualization/microdroid"],
 }
@@ -460,7 +468,7 @@
 cc_binary {
     name: "init_first_stage.microdroid",
     defaults: ["init_first_stage_defaults"],
-    cflags: ["-DMICRODROID"],
+    cflags: ["-DMICRODROID=1"],
     installable: false,
 }
 
diff --git a/init/fuzzer/Android.bp b/init/fuzzer/Android.bp
index c21a196..856ca8c 100644
--- a/init/fuzzer/Android.bp
+++ b/init/fuzzer/Android.bp
@@ -18,7 +18,7 @@
 }
 
 cc_defaults {
-    name: "libinit_defaults",
+    name: "libinit_fuzzer_defaults",
     static_libs: [
         "libc++fs",
         "liblmkd_utils",
@@ -53,7 +53,7 @@
     ],
     shared_libs: ["libhidlmetadata",],
     defaults: [
-        "libinit_defaults",
+        "libinit_fuzzer_defaults",
     ],
 }
 
@@ -62,7 +62,7 @@
     srcs: [
         "init_property_fuzzer.cpp",
     ],
-    defaults: ["libinit_defaults"],
+    defaults: ["libinit_fuzzer_defaults"],
 }
 
 cc_fuzz {
@@ -71,6 +71,6 @@
         "init_ueventHandler_fuzzer.cpp",
     ],
     defaults: [
-        "libinit_defaults",
+        "libinit_fuzzer_defaults",
     ],
 }
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();
 
diff --git a/init/util.cpp b/init/util.cpp
index bc8ea6e..d0478e8 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -732,11 +732,6 @@
     is_default_mount_namespace_ready = true;
 }
 
-bool IsMicrodroid() {
-    static bool is_microdroid = android::base::GetProperty("ro.hardware", "") == "microdroid";
-    return is_microdroid;
-}
-
 bool Has32BitAbi() {
     static bool has = !android::base::GetProperty("ro.product.cpu.abilist32", "").empty();
     return has;
diff --git a/init/util.h b/init/util.h
index e58e70e..3f0a4e0 100644
--- a/init/util.h
+++ b/init/util.h
@@ -105,7 +105,14 @@
 bool IsDefaultMountNamespaceReady();
 void SetDefaultMountNamespaceReady();
 
-bool IsMicrodroid();
+inline constexpr bool IsMicrodroid() {
+#ifdef MICRODROID
+    return MICRODROID;
+#else
+    return false;
+#endif
+}
+
 bool Has32BitAbi();
 
 std::string GetApexNameFromFileName(const std::string& path);