From 683ebc805982a6dbffd94d8a631c75e66c239a67 Mon Sep 17 00:00:00 2001 From: Luis Hector Chavez Date: Tue, 27 Jun 2017 13:49:27 -0700 Subject: [PATCH] init: Terminate gracefully when CAP_SYS_BOOT is absent This change makes it possible for Android running in a container to terminate cleanly instead of calling abort() when requested to shut down. Bug: 62388055 Test: setprop sys.powerctl reboot makes init terminate nicely Change-Id: I31c7b475d89d7cbd665e135d9b8951dfd4bca80d --- init/reboot.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/init/reboot.cpp b/init/reboot.cpp index df7912f96..be1e7607f 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -162,9 +164,30 @@ static void LogShutdownTime(UmountStat stat, Timer* t) { LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration_ms()) << ":" << stat; } +static bool IsRebootCapable() { + cap_t caps = cap_init(); + auto scopeguard = android::base::make_scope_guard([&caps] { cap_free(caps); }); + + // Assume we have the capability. + cap_flag_value_t value = CAP_SET; + if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT) || + cap_get_flag(caps, CAP_SYS_BOOT, CAP_EFFECTIVE, &value) != 0) { + PLOG(ERROR) << "cap_get_flag(CAP_BOOT, EFFECTIVE) failed"; + } + + return value == CAP_SET; +} + static void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) { LOG(INFO) << "Reboot ending, jumping to kernel"; + + if (!IsRebootCapable()) { + // On systems where init does not have the capability of rebooting the + // device, just exit cleanly. + exit(0); + } + switch (cmd) { case ANDROID_RB_POWEROFF: reboot(RB_POWER_OFF);