Merge "init: replace panic() with LOG(FATAL)" am: 57a89f3ba0

am: ce2325895f

Change-Id: Ia46b3e10ce0280e60c8c8dc289d3c2f01ac472e2
This commit is contained in:
Tom Cherry 2017-08-18 16:03:57 +00:00 committed by android-build-merger
commit 0ae159a920
9 changed files with 42 additions and 38 deletions

View file

@ -34,6 +34,7 @@
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/properties.h> #include <android-base/properties.h>
#include <android-base/strings.h> #include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <keyutils.h> #include <keyutils.h>
#include <libavb/libavb.h> #include <libavb/libavb.h>
#include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h>
@ -252,8 +253,7 @@ static Result<Success> wait_for_coldboot_done_action(const std::vector<std::stri
// because any build that slow isn't likely to boot at all, and we'd // because any build that slow isn't likely to boot at all, and we'd
// rather any test lab devices fail back to the bootloader. // rather any test lab devices fail back to the bootloader.
if (wait_for_file(COLDBOOT_DONE, 60s) < 0) { if (wait_for_file(COLDBOOT_DONE, 60s) < 0) {
LOG(ERROR) << "Timed out waiting for " COLDBOOT_DONE; LOG(FATAL) << "Timed out waiting for " COLDBOOT_DONE;
panic();
} }
property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count())); property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count()));
@ -367,8 +367,7 @@ static Result<Success> queue_property_triggers_action(const std::vector<std::str
static void global_seccomp() { static void global_seccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) { import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) {
if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) { if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
LOG(ERROR) << "Failed to globally enable seccomp!"; LOG(FATAL) << "Failed to globally enable seccomp!";
panic();
} }
}); });
} }
@ -398,8 +397,11 @@ static void install_reboot_signal_handlers() {
memset(&action, 0, sizeof(action)); memset(&action, 0, sizeof(action));
sigfillset(&action.sa_mask); sigfillset(&action.sa_mask);
action.sa_handler = [](int) { action.sa_handler = [](int) {
// panic() reboots to bootloader // Calling DoReboot() or LOG(FATAL) is not a good option as this is a signal handler.
panic(); // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option
// and probably good enough given this is already an error case and only enabled for
// development builds.
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
}; };
action.sa_flags = SA_RESTART; action.sa_flags = SA_RESTART;
sigaction(SIGABRT, &action, nullptr); sigaction(SIGABRT, &action, nullptr);
@ -468,8 +470,7 @@ int main(int argc, char** argv) {
LOG(INFO) << "init first stage started!"; LOG(INFO) << "init first stage started!";
if (!DoFirstStageMount()) { if (!DoFirstStageMount()) {
LOG(ERROR) << "Failed to mount required partitions early ..."; LOG(FATAL) << "Failed to mount required partitions early ...";
panic();
} }
SetInitAvbVersionInRecovery(); SetInitAvbVersionInRecovery();
@ -484,8 +485,7 @@ int main(int argc, char** argv) {
// We're in the kernel domain, so re-exec init to transition to the init domain now // We're in the kernel domain, so re-exec init to transition to the init domain now
// that the SELinux policy has been loaded. // that the SELinux policy has been loaded.
if (selinux_android_restorecon("/init", 0) == -1) { if (selinux_android_restorecon("/init", 0) == -1) {
PLOG(ERROR) << "restorecon failed of /init failed"; PLOG(FATAL) << "restorecon failed of /init failed";
panic();
} }
setenv("INIT_SECOND_STAGE", "true", 1); setenv("INIT_SECOND_STAGE", "true", 1);
@ -500,8 +500,7 @@ int main(int argc, char** argv) {
// execv() only returns if an error happened, in which case we // execv() only returns if an error happened, in which case we
// panic and never fall through this conditional. // panic and never fall through this conditional.
PLOG(ERROR) << "execv(\"" << path << "\") failed"; PLOG(FATAL) << "execv(\"" << path << "\") failed";
panic();
} }
// At this point we're in the second stage of init. // At this point we're in the second stage of init.

View file

@ -21,17 +21,35 @@
#include <string.h> #include <string.h>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <cutils/android_reboot.h>
#include <selinux/selinux.h> #include <selinux/selinux.h>
#include "reboot.h"
namespace android { namespace android {
namespace init { namespace init {
static void RebootAborter(const char* abort_message) {
// DoReboot() does a lot to try to shutdown the system cleanly. If something happens to call
// LOG(FATAL) in the shutdown path, we want to catch this and immediately use the syscall to
// reboot instead of recursing here.
static bool has_aborted = false;
if (!has_aborted) {
has_aborted = true;
// Do not queue "shutdown" trigger since we want to shutdown immediately and it's not likely
// that we can even run the ActionQueue at this point.
DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
} else {
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
}
}
void InitKernelLogging(char* argv[]) { void InitKernelLogging(char* argv[]) {
// Make stdin/stdout/stderr all point to /dev/null. // Make stdin/stdout/stderr all point to /dev/null.
int fd = open("/sys/fs/selinux/null", O_RDWR); int fd = open("/sys/fs/selinux/null", O_RDWR);
if (fd == -1) { if (fd == -1) {
int saved_errno = errno; int saved_errno = errno;
android::base::InitLogging(argv, &android::base::KernelLogger); android::base::InitLogging(argv, &android::base::KernelLogger, RebootAborter);
errno = saved_errno; errno = saved_errno;
PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null"; PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
} }
@ -40,7 +58,7 @@ void InitKernelLogging(char* argv[]) {
dup2(fd, 2); dup2(fd, 2);
if (fd > 2) close(fd); if (fd > 2) close(fd);
android::base::InitLogging(argv, &android::base::KernelLogger); android::base::InitLogging(argv, &android::base::KernelLogger, RebootAborter);
} }
int selinux_klog_callback(int type, const char *fmt, ...) { int selinux_klog_callback(int type, const char *fmt, ...) {

View file

@ -191,8 +191,7 @@ static bool IsRebootCapable() {
return value == CAP_SET; return value == CAP_SET;
} }
static void __attribute__((noreturn)) void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
LOG(INFO) << "Reboot ending, jumping to kernel"; LOG(INFO) << "Reboot ending, jumping to kernel";
if (!IsRebootCapable()) { if (!IsRebootCapable()) {
@ -216,7 +215,7 @@ RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
break; break;
} }
// In normal case, reboot should not return. // In normal case, reboot should not return.
PLOG(FATAL) << "reboot call returned"; PLOG(ERROR) << "reboot call returned";
abort(); abort();
} }

View file

@ -22,6 +22,9 @@
namespace android { namespace android {
namespace init { namespace init {
// This is a wrapper around the actual reboot calls. DoReboot() should be preferred in most cases.
void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget);
/* Reboot / shutdown the system. /* Reboot / shutdown the system.
* cmd ANDROID_RB_* as defined in android_reboot.h * cmd ANDROID_RB_* as defined in android_reboot.h
* reason Reason string like "reboot", "userrequested" * reason Reason string like "reboot", "userrequested"

View file

@ -25,8 +25,6 @@
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/unique_fd.h> #include <android-base/unique_fd.h>
#include "util.h"
using android::base::unique_fd; using android::base::unique_fd;
namespace android { namespace android {
@ -178,8 +176,7 @@ Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args) {
LOG(ERROR) << "Unknown architecture"; LOG(ERROR) << "Unknown architecture";
#endif #endif
LOG(ERROR) << "Unable to set adequate mmap entropy value!"; LOG(FATAL) << "Unable to set adequate mmap entropy value!";
panic();
return Error(); return Error();
} }
@ -194,8 +191,7 @@ Result<Success> SetKptrRestrictAction(const std::vector<std::string>& args) {
std::string path = KPTR_RESTRICT_PATH; std::string path = KPTR_RESTRICT_PATH;
if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) { if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
LOG(ERROR) << "Unable to set adequate kptr_restrict value!"; LOG(FATAL) << "Unable to set adequate kptr_restrict value!";
panic();
return Error(); return Error();
} }
return Success(); return Success();

View file

@ -345,21 +345,19 @@ void SelinuxInitialize() {
LOG(INFO) << "Loading SELinux policy"; LOG(INFO) << "Loading SELinux policy";
if (!LoadPolicy()) { if (!LoadPolicy()) {
panic(); LOG(FATAL) << "Unable to load SELinux policy";
} }
bool kernel_enforcing = (security_getenforce() == 1); bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = IsEnforcing(); bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) { if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) { if (security_setenforce(is_enforcing)) {
PLOG(ERROR) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false"); PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
panic();
} }
} }
if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) { if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
LOG(ERROR) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error(); LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
panic();
} }
// init's first stage can't set properties, so pass the time to the second stage. // init's first stage can't set properties, so pass the time to the second stage.

View file

@ -306,8 +306,7 @@ void Service::Reap() {
if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) { if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) { if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) { if (++crash_count_ > 4) {
LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes"; LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
panic();
} }
} else { } else {
time_crashed_ = now; time_crashed_ = now;

View file

@ -345,12 +345,6 @@ bool expand_props(const std::string& src, std::string* dst) {
return true; return true;
} }
void panic() {
LOG(ERROR) << "panic: rebooting to bootloader";
// Do not queue "shutdown" trigger since we want to shutdown immediately
DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
}
static std::string init_android_dt_dir() { static std::string init_android_dt_dir() {
// Use the standard procfs-based path by default // Use the standard procfs-based path by default
std::string android_dt_dir = kDefaultAndroidDtDir; std::string android_dt_dir = kDefaultAndroidDtDir;

View file

@ -55,8 +55,6 @@ std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
bool is_dir(const char* pathname); bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst); bool expand_props(const std::string& src, std::string* dst);
void panic() __attribute__((__noreturn__));
// Returns the platform's Android DT directory as specified in the kernel cmdline. // Returns the platform's Android DT directory as specified in the kernel cmdline.
// If the platform does not configure a custom DT path, returns the standard one (based in procfs). // If the platform does not configure a custom DT path, returns the standard one (based in procfs).
const std::string& get_android_dt_dir(); const std::string& get_android_dt_dir();