Add odm sepolicy support to selinux.cpp
init: support loading odm sepolicy
Currently init merges two sepolicy cil files:
- /system/etc/selinux/plat_sepolicy.cil
- /vendor/etc/selinux/nonplat_sepolicy.cil
This change replaces nonplat_sepolicy.cil with the following two files:
- /vendor/etc/selinux/declaration/nonplat_declaration.cil
- /vendor/etc/selinux/vender_sepolicy.cil
And support merging another default (but optional):
- /odm/etc/selinux/odm_sepolicy.cil.
Bug: 64240127
Test: boot sailfish normally without odm.cil
Test: boot another device having odm.cil
Change-Id: I0b7f8c656c73ddb0fd46f2af3c625d7c81566f2f
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ef59164..3f7ad13 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -198,9 +198,18 @@
bool FindPrecompiledSplitPolicy(std::string* file) {
file->clear();
-
- static constexpr const char precompiled_sepolicy[] = "/vendor/etc/selinux/precompiled_sepolicy";
- if (access(precompiled_sepolicy, R_OK) == -1) {
+ // If there is an odm partition, precompiled_sepolicy will be in
+ // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
+ static constexpr const char vendor_precompiled_sepolicy[] =
+ "/vendor/etc/selinux/precompiled_sepolicy";
+ static constexpr const char odm_precompiled_sepolicy[] =
+ "/odm/etc/selinux/precompiled_sepolicy";
+ if (access(odm_precompiled_sepolicy, R_OK) == 0) {
+ *file = odm_precompiled_sepolicy;
+ } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
+ *file = vendor_precompiled_sepolicy;
+ } else {
+ PLOG(INFO) << "No precompiled sepolicy";
return false;
}
std::string actual_plat_id;
@@ -209,19 +218,18 @@
"/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256";
return false;
}
+
std::string precompiled_plat_id;
- if (!ReadFirstLine("/vendor/etc/selinux/precompiled_sepolicy.plat_and_mapping.sha256",
- &precompiled_plat_id)) {
- PLOG(INFO) << "Failed to read "
- "/vendor/etc/selinux/"
- "precompiled_sepolicy.plat_and_mapping.sha256";
+ std::string precompiled_sha256 = *file + ".plat_and_mapping.sha256";
+ if (!ReadFirstLine(precompiled_sha256.c_str(), &precompiled_plat_id)) {
+ PLOG(INFO) << "Failed to read " << precompiled_sha256;
+ file->clear();
return false;
}
if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
+ file->clear();
return false;
}
-
- *file = precompiled_sepolicy;
return true;
}
@@ -293,24 +301,55 @@
return false;
}
std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+
+ // vendor_sepolicy.cil and nonplat_declaration.cil are the new design to replace
+ // nonplat_sepolicy.cil.
+ std::string nonplat_declaration_cil_file("/vendor/etc/selinux/nonplat_declaration.cil");
+ std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");
+
+ if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {
+ // For backward compatibility.
+ // TODO: remove this after no device is using nonplat_sepolicy.cil.
+ vendor_policy_cil_file = "/vendor/etc/selinux/nonplat_sepolicy.cil";
+ nonplat_declaration_cil_file.clear();
+ } else if (access(nonplat_declaration_cil_file.c_str(), F_OK) == -1) {
+ LOG(ERROR) << "Missing " << nonplat_declaration_cil_file;
+ return false;
+ }
+
+ // odm_sepolicy.cil is default but optional.
+ std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");
+ if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
+ odm_policy_cil_file.clear();
+ }
const std::string version_as_string = std::to_string(max_policy_version);
// clang-format off
- const char* compile_args[] = {
+ std::vector<const char*> compile_args {
"/system/bin/secilc",
plat_policy_cil_file,
"-M", "true", "-G", "-N",
// Target the highest policy language version supported by the kernel
"-c", version_as_string.c_str(),
mapping_file.c_str(),
- "/vendor/etc/selinux/nonplat_sepolicy.cil",
"-o", compiled_sepolicy,
// We don't care about file_contexts output by the compiler
"-f", "/sys/fs/selinux/null", // /dev/null is not yet available
- nullptr};
+ };
// clang-format on
- if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args)) {
+ if (!nonplat_declaration_cil_file.empty()) {
+ compile_args.push_back(nonplat_declaration_cil_file.c_str());
+ }
+ if (!vendor_policy_cil_file.empty()) {
+ compile_args.push_back(vendor_policy_cil_file.c_str());
+ }
+ if (!odm_policy_cil_file.empty()) {
+ compile_args.push_back(odm_policy_cil_file.c_str());
+ }
+ compile_args.push_back(nullptr);
+
+ if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
unlink(compiled_sepolicy);
return false;
}