Reland: Add /system_ext/etc/selinux/ to the debug policy search path for GSI

This change only *adds* /system_ext/etc/selinux to the debug policy
search path, and does not change any preconditions to load the debug
policy. The device still needs to be bootloader-unlocked and has the
debug ramdisk flashed to be able to use the debug policy. The only thing
changed is that now the debug policy can be loaded from /system_ext or
/debug_ramdisk when system partition is compliance testing GSI.

The debug policy in the boot ramdisk may be outdated if the system
partition is flashed with a image built from a different revision.
This happens frequently when running the compliance testing VTS, where
the device is flashed with (A) GSI and (B) device vendor image & debug
boot image, and (A) and (B) are built from different git revisions.

To address this, we install a copy of the debug policy under
/system_ext, so that the version desync between (A) & (B) wouldn't be a
problem anymore because (A) no longer relies on the debug policy file
from (B).

Bug: 188067818
Test: Flash RQ2A.201207.001 bramble-user with debug ramdisk & flash
  gsi_arm64-user from master, device can boot and `adb root` works
Change-Id: Ibe17eb1ecb0e813309c9596d1f152b7455686b26
This commit is contained in:
Yi-Yo Chiang 2021-09-23 14:14:16 +00:00
parent be09a1e643
commit bb77c544e5
3 changed files with 58 additions and 14 deletions

View file

@ -89,7 +89,19 @@ init_host_sources = [
"host_init_verifier.cpp",
]
cc_defaults {
soong_config_module_type {
name: "libinit_cc_defaults",
module_type: "cc_defaults",
config_namespace: "ANDROID",
bool_variables: [
"PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT",
],
properties: [
"cflags",
],
}
libinit_cc_defaults {
name: "init_defaults",
sanitize: {
misc_undefined: ["signed-integer-overflow"],
@ -109,6 +121,7 @@ cc_defaults {
"-DDUMP_ON_UMOUNT_FAILURE=0",
"-DSHUTDOWN_ZERO_TIMEOUT=0",
"-DINIT_FULL_SOURCES",
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=0",
],
product_variables: {
debuggable: {
@ -137,6 +150,14 @@ cc_defaults {
cppflags: ["-DUSER_MODE_LINUX"],
},
},
soong_config_variables: {
PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT: {
cflags: [
"-UINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT",
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=1",
],
},
},
static_libs: [
"libavb",
"libc++fs",

View file

@ -330,14 +330,21 @@ int FirstStageMain(int argc, char** argv) {
// If "/force_debuggable" is present, the second-stage init will use a userdebug
// sepolicy and load adb_debug.prop to allow adb root, if the device is unlocked.
if (access("/force_debuggable", F_OK) == 0) {
constexpr const char adb_debug_prop_src[] = "/adb_debug.prop";
constexpr const char userdebug_plat_sepolicy_cil_src[] = "/userdebug_plat_sepolicy.cil";
std::error_code ec; // to invoke the overloaded copy_file() that won't throw.
if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) ||
!fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) {
LOG(ERROR) << "Failed to setup debug ramdisk";
} else {
// setenv for second-stage init to read above kDebugRamdisk* files.
setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
if (access(adb_debug_prop_src, F_OK) == 0 &&
!fs::copy_file(adb_debug_prop_src, kDebugRamdiskProp, ec)) {
LOG(WARNING) << "Can't copy " << adb_debug_prop_src << " to " << kDebugRamdiskProp
<< ": " << ec.message();
}
if (access(userdebug_plat_sepolicy_cil_src, F_OK) == 0 &&
!fs::copy_file(userdebug_plat_sepolicy_cil_src, kDebugRamdiskSEPolicy, ec)) {
LOG(WARNING) << "Can't copy " << userdebug_plat_sepolicy_cil_src << " to "
<< kDebugRamdiskSEPolicy << ": " << ec.message();
}
// setenv for second-stage init to read above kDebugRamdisk* files.
setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
}
if (ForceNormalBoot(cmdline, bootconfig)) {

View file

@ -295,6 +295,25 @@ bool IsSplitPolicyDevice() {
return access(plat_policy_cil_file, R_OK) != -1;
}
std::optional<const char*> GetUserdebugPlatformPolicyFile() {
// See if we need to load userdebug_plat_sepolicy.cil instead of plat_sepolicy.cil.
const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
if (force_debuggable_env && "true"s == force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
const std::vector<const char*> debug_policy_candidates = {
#if INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT == 1
"/system_ext/etc/selinux/userdebug_plat_sepolicy.cil",
#endif
kDebugRamdiskSEPolicy,
};
for (const char* debug_policy : debug_policy_candidates) {
if (access(debug_policy, F_OK) == 0) {
return debug_policy;
}
}
}
return std::nullopt;
}
struct PolicyFile {
unique_fd fd;
std::string path;
@ -310,13 +329,10 @@ bool OpenSplitPolicy(PolicyFile* policy_file) {
// secilc is invoked to compile the above three policy files into a single monolithic policy
// file. This file is then loaded into the kernel.
// See if we need to load userdebug_plat_sepolicy.cil instead of plat_sepolicy.cil.
const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
bool use_userdebug_policy =
((force_debuggable_env && "true"s == force_debuggable_env) &&
AvbHandle::IsDeviceUnlocked() && access(kDebugRamdiskSEPolicy, F_OK) == 0);
const auto userdebug_plat_sepolicy = GetUserdebugPlatformPolicyFile();
const bool use_userdebug_policy = userdebug_plat_sepolicy.has_value();
if (use_userdebug_policy) {
LOG(WARNING) << "Using userdebug system sepolicy";
LOG(INFO) << "Using userdebug system sepolicy " << *userdebug_plat_sepolicy;
}
// Load precompiled policy from vendor image, if a matching policy is found there. The policy
@ -413,7 +429,7 @@ bool OpenSplitPolicy(PolicyFile* policy_file) {
// clang-format off
std::vector<const char*> compile_args {
"/system/bin/secilc",
use_userdebug_policy ? kDebugRamdiskSEPolicy: plat_policy_cil_file,
use_userdebug_policy ? *userdebug_plat_sepolicy : plat_policy_cil_file,
"-m", "-M", "true", "-G", "-N",
"-c", version_as_string.c_str(),
plat_mapping_file.c_str(),