From 6bd3bc8d015816eb0174ede8d0e8b7cfaa6569cd Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Tue, 31 Mar 2020 01:28:35 +0100 Subject: [PATCH] Properly fail userspace reboot if it's not supported Previously, after `adb reboot userspace` is called on a device that doesn't suppor it, init would've logged an error and quietly exit the shutdown sequence. This was leaving adb handing forever. With this approach, init will fail setprop "sys.powerctl=reboot,userspace" in case userspace reboot is not supported. Test: adb root Test: adb setprop init.userspace_reboot.is_supported 0 Test: adb reboot userspace Test: atest CtsInitTestCases Bug: 146639622 Change-Id: I1264078f53ed3ff54638c7f3b6846b7437f98ee5 Merged-In: I1264078f53ed3ff54638c7f3b6846b7437f98ee5 (cherry picked from commit 92116e4129812eccb32d7a20208e03be7ee2ec75) --- init/property_service.cpp | 6 ++++++ init/property_service_test.cpp | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/init/property_service.cpp b/init/property_service.cpp index a5fea7cd6..a89504e59 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -85,6 +86,7 @@ using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; using android::properties::PropertyInfoAreaFile; using android::properties::PropertyInfoEntry; +using android::sysprop::InitProperties::is_userspace_reboot_supported; namespace android { namespace init { @@ -489,6 +491,10 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, } LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid << process_log_string; + if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) { + *error = "Userspace reboot is not supported by this device"; + return PROP_ERROR_INVALID_VALUE; + } } // If a process other than init is writing a non-empty value, it means that process is diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp index 0f4cd0d1f..c6dcfa257 100644 --- a/init/property_service_test.cpp +++ b/init/property_service_test.cpp @@ -22,8 +22,10 @@ #include #include +#include #include +using android::base::GetProperty; using android::base::SetProperty; namespace android { @@ -74,5 +76,19 @@ TEST(property_service, non_utf8_value) { EXPECT_TRUE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\x80")); } +TEST(property_service, userspace_reboot_not_supported) { + if (getuid() != 0) { + GTEST_SKIP() << "Skipping test, must be run as root."; + return; + } + const std::string original_value = GetProperty("init.userspace_reboot.is_supported", ""); + auto guard = android::base::make_scope_guard([&original_value]() { + SetProperty("init.userspace_reboot.is_supported", original_value); + }); + + ASSERT_TRUE(SetProperty("init.userspace_reboot.is_supported", "false")); + EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace")); +} + } // namespace init } // namespace android