diff --git a/adb/Android.bp b/adb/Android.bp index 1e085a7b3..01e00dd1c 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -24,7 +24,8 @@ cc_defaults { "-Wno-missing-field-initializers", "-Wthread-safety", "-Wvla", - "-DADB_HOST=1", // overridden by adbd_defaults + "-DADB_HOST=1", // overridden by adbd_defaults + "-DALLOW_ADBD_ROOT=0", // overridden by adbd_defaults ], cpp_std: "experimental", @@ -79,7 +80,8 @@ cc_defaults { product_variables: { debuggable: { cflags: [ - "-DALLOW_ADBD_ROOT", + "-UALLOW_ADBD_ROOT", + "-DALLOW_ADBD_ROOT=1", "-DALLOW_ADBD_DISABLE_VERITY", "-DALLOW_ADBD_NO_AUTH", ], diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp index fce3a4fb5..e5a49171b 100644 --- a/adb/daemon/main.cpp +++ b/adb/daemon/main.cpp @@ -58,17 +58,23 @@ #if defined(__ANDROID__) static const char* root_seclabel = nullptr; +static inline bool is_device_unlocked() { + return "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", ""); +} + static bool should_drop_capabilities_bounding_set() { -#if defined(ALLOW_ADBD_ROOT) - if (__android_log_is_debuggable()) { - return false; + if (ALLOW_ADBD_ROOT || is_device_unlocked()) { + if (__android_log_is_debuggable()) { + return false; + } } -#endif return true; } static bool should_drop_privileges() { -#if defined(ALLOW_ADBD_ROOT) + // "adb root" not allowed, always drop privileges. + if (!ALLOW_ADBD_ROOT && !is_device_unlocked()) return true; + // The properties that affect `adb root` and `adb unroot` are ro.secure and // ro.debuggable. In this context the names don't make the expected behavior // particularly obvious. @@ -98,9 +104,6 @@ static bool should_drop_privileges() { } return drop; -#else - return true; // "adb root" not allowed, always drop privileges. -#endif // ALLOW_ADBD_ROOT } static void drop_privileges(int server_port) { @@ -205,6 +208,10 @@ int adbd_main(int server_port) { #if defined(ALLOW_ADBD_NO_AUTH) // If ro.adb.secure is unset, default to no authentication required. auth_required = android::base::GetBoolProperty("ro.adb.secure", false); +#elif defined(__ANDROID__) + if (is_device_unlocked()) { // allows no authentication when the device is unlocked. + auth_required = android::base::GetBoolProperty("ro.adb.secure", false); + } #endif adbd_auth_init(); diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp index 7cf4c3fbd..c56667653 100644 --- a/init/first_stage_init.cpp +++ b/init/first_stage_init.cpp @@ -199,6 +199,12 @@ int FirstStageMain(int argc, char** argv) { SwitchRoot("/first_stage_ramdisk"); } + // If this file 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) { + setenv("INIT_FORCE_DEBUGGABLE", "true", 1); + } + if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } diff --git a/init/init.cpp b/init/init.cpp index bbef1a9a1..7182fda25 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ using android::base::ReadFileToString; using android::base::StringPrintf; using android::base::Timer; using android::base::Trim; +using android::fs_mgr::AvbHandle; namespace android { namespace init { @@ -92,6 +94,7 @@ static std::string wait_prop_value; static bool shutting_down; static std::string shutdown_command; static bool do_shutdown = false; +static bool load_debug_prop = false; std::vector late_import_paths; @@ -655,10 +658,17 @@ int SecondStageMain(int argc, char** argv) { const char* avb_version = getenv("INIT_AVB_VERSION"); if (avb_version) property_set("ro.boot.avb_version", avb_version); + // See if need to load debug props to allow adb root, when the device is unlocked. + const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE"); + if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) { + load_debug_prop = "true"s == force_debuggable_env; + } + // Clean up our environment. unsetenv("INIT_STARTED_AT"); unsetenv("INIT_SELINUX_TOOK"); unsetenv("INIT_AVB_VERSION"); + unsetenv("INIT_FORCE_DEBUGGABLE"); // Now set up SELinux for second stage. SelinuxSetupKernelLogging(); @@ -672,7 +682,7 @@ int SecondStageMain(int argc, char** argv) { InstallSignalFdHandler(&epoll); - property_load_boot_defaults(); + property_load_boot_defaults(load_debug_prop); fs_mgr_vendor_overlay_mount_all(); export_oem_lock_status(); StartPropertyService(&epoll); diff --git a/init/property_service.cpp b/init/property_service.cpp index 4bc857ac9..fc5538c51 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -866,7 +866,7 @@ static void property_derive_build_fingerprint() { } } -void property_load_boot_defaults() { +void property_load_boot_defaults(bool load_debug_prop) { // TODO(b/117892318): merge prop.default and build.prop files into one // We read the properties and their values into a map, in order to always allow properties // loaded in the later property files to override the properties in loaded in the earlier @@ -888,6 +888,12 @@ void property_load_boot_defaults() { load_properties_from_file("/product_services/build.prop", nullptr, &properties); load_properties_from_file("/factory/factory.prop", "ro.*", &properties); + if (load_debug_prop) { + constexpr static const char kAdbDebugProp[] = "/system/etc/adb_debug.prop"; + LOG(INFO) << "Loading " << kAdbDebugProp; + load_properties_from_file(kAdbDebugProp, nullptr, &properties); + } + for (const auto& [name, value] : properties) { std::string error; if (PropertySet(name, value, &error) != PROP_SUCCESS) { diff --git a/init/property_service.h b/init/property_service.h index 9022f5a8a..85e7bc0ae 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -36,7 +36,7 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, extern bool PropertyChildReap(pid_t pid); void property_init(void); -void property_load_boot_defaults(void); +void property_load_boot_defaults(bool); void load_persist_props(void); void load_system_props(void); void StartPropertyService(Epoll* epoll); diff --git a/init/selinux.cpp b/init/selinux.cpp index 3fadfedbe..797c4e08d 100644 --- a/init/selinux.cpp +++ b/init/selinux.cpp @@ -61,14 +61,18 @@ #include #include #include +#include #include #include "reboot_utils.h" #include "util.h" +using namespace std::string_literals; + using android::base::ParseInt; using android::base::Timer; using android::base::unique_fd; +using android::fs_mgr::AvbHandle; namespace android { namespace init { @@ -267,6 +271,8 @@ bool GetVendorMappingVersion(std::string* plat_vers) { } constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil"; +constexpr const char userdebug_plat_policy_cil_file[] = + "/system/etc/selinux/userdebug_plat_sepolicy.cil"; bool IsSplitPolicyDevice() { return access(plat_policy_cil_file, R_OK) != -1; @@ -282,10 +288,21 @@ bool LoadSplitPolicy() { // 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(userdebug_plat_policy_cil_file, F_OK) == 0); + if (use_userdebug_policy) { + LOG(WARNING) << "Using userdebug system sepolicy"; + } + // Load precompiled policy from vendor image, if a matching policy is found there. The policy // must match the platform policy on the system image. std::string precompiled_sepolicy_file; - if (FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) { + // use_userdebug_policy requires compiling sepolicy with userdebug_plat_sepolicy.cil. + // Thus it cannot use the precompiled policy from vendor image. + if (!use_userdebug_policy && FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) { unique_fd fd(open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY)); if (fd != -1) { if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) { @@ -358,7 +375,7 @@ bool LoadSplitPolicy() { // clang-format off std::vector compile_args { "/system/bin/secilc", - plat_policy_cil_file, + use_userdebug_policy ? userdebug_plat_policy_cil_file : plat_policy_cil_file, "-m", "-M", "true", "-G", "-N", // Target the highest policy language version supported by the kernel "-c", version_as_string.c_str(),