init: make fatal reboot target configurable
Currently, if init encounters a fatal issues it reboots to fastboot
but this may be not desirable in all cases, especially the case of
critical services crashing. Therefore this change adds the ability
for vendors to customize the reboot target via the
androidboot.init_fatal_reboot_target= kernel command line.
This applies to all LOG(FATAL) messages as well as fatal signals in
userdebug/eng builds, except for signals before logging is enabled in
first stage init.
Bug: 121006328
Test: device reboots to configurable target with LOG(FATAL)
Test: device reboots to configurable target after a segfault in the
various stages of init
Test: device reboots to fastboot without a configured target
Change-Id: I16ea9e32e2fee08dece3d33b697d7a08191d607b
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index 4524f69..d1a712f 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -32,6 +32,27 @@
namespace android {
namespace init {
+static std::string init_fatal_reboot_target = "bootloader";
+
+void SetFatalRebootTarget() {
+ std::string cmdline;
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
+ cmdline = android::base::Trim(cmdline);
+
+ const char kRebootTargetString[] = "androidboot.init_fatal_reboot_target=";
+ auto start_pos = cmdline.find(kRebootTargetString);
+ if (start_pos == std::string::npos) {
+ return; // We already default to bootloader if no setting is provided.
+ }
+ start_pos += sizeof(kRebootTargetString) - 1;
+
+ auto end_pos = cmdline.find(' ', start_pos);
+ // if end_pos isn't found, then we've run off the end, but this is okay as this is the last
+ // entry, and -1 is a valid size for string::substr();
+ auto size = end_pos == std::string::npos ? -1 : end_pos - start_pos;
+ init_fatal_reboot_target = cmdline.substr(start_pos, size);
+}
+
bool IsRebootCapable() {
if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) {
PLOG(WARNING) << "CAP_SYS_BOOT is not supported";
@@ -85,13 +106,13 @@
if (pid == -1) {
// Couldn't fork, don't even try to backtrace, just reboot.
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
} else if (pid == 0) {
// Fork a child for safety, since we always want to shut down if something goes wrong, but
// its worth trying to get the backtrace, even in the signal handler, since typically it
// does work despite not being async-signal-safe.
sleep(5);
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
}
// In the parent, let's try to get a backtrace then shutdown.
@@ -103,7 +124,7 @@
for (size_t i = 0; i < backtrace->NumFrames(); i++) {
LOG(ERROR) << backtrace->FormatFrameData(i);
}
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
}
void InstallRebootSignalHandlers() {