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
This commit is contained in:
Nikita Ioffe 2023-06-26 14:55:31 +01:00
parent 8790a71bc4
commit a66adf45aa
5 changed files with 79 additions and 44 deletions

View file

@ -214,8 +214,8 @@ cc_library_headers {
visibility: [":__subpackages__"],
}
cc_library_static {
name: "libinit",
cc_defaults {
name: "libinit_defaults",
recovery_available: true,
defaults: [
"init_defaults",
@ -252,10 +252,17 @@ cc_library_static {
],
},
},
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 @@ cc_defaults {
recovery_available: true,
stem: "init",
defaults: ["init_defaults"],
static_libs: ["libinit"],
srcs: ["main.cpp"],
symlinks: ["ueventd"],
target: {
@ -309,12 +315,14 @@ cc_defaults {
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 {
cc_binary {
name: "init_first_stage.microdroid",
defaults: ["init_first_stage_defaults"],
cflags: ["-DMICRODROID"],
cflags: ["-DMICRODROID=1"],
installable: false,
}

View file

@ -18,7 +18,7 @@ package {
}
cc_defaults {
name: "libinit_defaults",
name: "libinit_fuzzer_defaults",
static_libs: [
"libc++fs",
"liblmkd_utils",
@ -53,7 +53,7 @@ cc_fuzz {
],
shared_libs: ["libhidlmetadata",],
defaults: [
"libinit_defaults",
"libinit_fuzzer_defaults",
],
}
@ -62,7 +62,7 @@ cc_fuzz {
srcs: [
"init_property_fuzzer.cpp",
],
defaults: ["libinit_defaults"],
defaults: ["libinit_fuzzer_defaults"],
}
cc_fuzz {
@ -71,6 +71,6 @@ cc_fuzz {
"init_ueventHandler_fuzzer.cpp",
],
defaults: [
"libinit_defaults",
"libinit_fuzzer_defaults",
],
}

View file

@ -300,8 +300,6 @@ bool GetVendorMappingVersion(std::string* plat_vers) {
}
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 OpenSplitPolicy(PolicyFile* policy_file) {
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 @@ void SelinuxSetupKernelLogging() {
}
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 @@ static void LoadSelinuxPolicy(std::string& policy) {
}
}
// 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 @@ static void LoadSelinuxPolicy(std::string& policy) {
// (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 @@ int SetupSelinux(char** argv) {
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 @@ int SetupSelinux(char** argv) {
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();

View file

@ -732,11 +732,6 @@ void SetDefaultMountNamespaceReady() {
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;

View file

@ -105,7 +105,14 @@ bool IsRecoveryMode();
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);