Merge "Close /dev/fuse FD before calling onClosed" into qt-dev
diff --git a/init/Android.bp b/init/Android.bp
index 69498ac..6be7290 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -68,6 +68,7 @@
"libpropertyinfoparser",
],
shared_libs: [
+ "libbacktrace",
"libbase",
"libbinder",
"libbootloader_message",
diff --git a/init/Android.mk b/init/Android.mk
index b02c926..c4f7d34 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -105,6 +105,10 @@
libcap \
libgsi \
libcom.android.sysprop.apex \
+ liblzma \
+ libdexfile_support \
+ libunwindstack \
+ libbacktrace \
LOCAL_SANITIZE := signed-integer-overflow
# First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 8b95e38..2b89940 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -33,7 +33,6 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <cutils/android_reboot.h>
#include <private/android_filesystem_config.h>
#include "debug_ramdisk.h"
@@ -168,13 +167,10 @@
"mode=0755,uid=0,gid=0"));
#undef CHECKCALL
+ SetStdioToDevNull(argv);
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
// talk to the outside world...
- // We need to set up stdin/stdout/stderr for child processes forked from first
- // stage init as part of the mount process. This closes /dev/console if the
- // kernel had previously opened it.
- auto reboot_bootloader = [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); };
- InitKernelLogging(argv, reboot_bootloader);
+ InitKernelLogging(argv);
if (!errors.empty()) {
for (const auto& [error_string, error_errno] : errors) {
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 63ceead..f6e9676 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -44,6 +44,12 @@
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
const std::string& source_context, const ucred& cr, std::string* error);
+// reboot_utils.h
+inline void SetFatalRebootTarget() {}
+inline void __attribute__((noreturn)) InitFatalReboot() {
+ abort();
+}
+
// selinux.h
int SelinuxGetVendorAndroidVersion();
void SelabelInitialize();
diff --git a/init/init.cpp b/init/init.cpp
index c79e459..6b03bc9 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -38,7 +38,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <cutils/android_reboot.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr_vendor_overlay.h>
#include <keyutils.h>
@@ -601,17 +600,6 @@
}
}
-static void InitAborter(const char* abort_message) {
- // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
- // simply abort instead of trying to reboot the system.
- if (getpid() != 1) {
- android::base::DefaultAborter(abort_message);
- return;
- }
-
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
-}
-
static void GlobalSeccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
bool in_qemu) {
@@ -632,8 +620,8 @@
InstallRebootSignalHandlers();
}
- // We need to set up stdin/stdout/stderr again now that we're running in init's context.
- InitKernelLogging(argv, InitAborter);
+ SetStdioToDevNull(argv);
+ InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
// Set init and its forked children's oom_adj.
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index 9610304..d1a712f 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -19,14 +19,40 @@
#include <sys/syscall.h>
#include <unistd.h>
-#include <android-base/logging.h>
-#include <cutils/android_reboot.h>
+#include <string>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/strings.h"
+#include "backtrace/Backtrace.h"
+#include "cutils/android_reboot.h"
#include "capabilities.h"
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";
@@ -75,6 +101,32 @@
abort();
}
+void __attribute__((noreturn)) InitFatalReboot() {
+ auto pid = fork();
+
+ if (pid == -1) {
+ // Couldn't fork, don't even try to backtrace, just reboot.
+ 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, init_fatal_reboot_target);
+ }
+
+ // In the parent, let's try to get a backtrace then shutdown.
+ std::unique_ptr<Backtrace> backtrace(
+ Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
+ if (!backtrace->Unwind(0)) {
+ LOG(ERROR) << __FUNCTION__ << ": Failed to unwind callstack.";
+ }
+ for (size_t i = 0; i < backtrace->NumFrames(); i++) {
+ LOG(ERROR) << backtrace->FormatFrameData(i);
+ }
+ RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
+}
+
void InstallRebootSignalHandlers() {
// Instead of panic'ing the kernel as is the default behavior when init crashes,
// we prefer to reboot to bootloader on development builds, as this will prevent
@@ -94,7 +146,7 @@
// 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");
+ InitFatalReboot();
};
action.sa_flags = SA_RESTART;
sigaction(SIGABRT, &action, nullptr);
diff --git a/init/reboot_utils.h b/init/reboot_utils.h
index 073a16a..3fd969e 100644
--- a/init/reboot_utils.h
+++ b/init/reboot_utils.h
@@ -21,11 +21,13 @@
namespace android {
namespace init {
+void SetFatalRebootTarget();
// Determines whether the system is capable of rebooting. This is conservative,
// so if any of the attempts to determine this fail, it will still return true.
bool IsRebootCapable();
// This is a wrapper around the actual reboot calls.
void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target);
+void __attribute__((noreturn)) InitFatalReboot();
void InstallRebootSignalHandlers();
} // namespace init
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 132fc13..86238b4 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -60,7 +60,6 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/unique_fd.h>
-#include <cutils/android_reboot.h>
#include <fs_avb/fs_avb.h>
#include <selinux/android.h>
@@ -518,9 +517,7 @@
// This function initializes SELinux then execs init to run in the init SELinux context.
int SetupSelinux(char** argv) {
- android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
- });
+ InitKernelLogging(argv);
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
diff --git a/init/util.cpp b/init/util.cpp
index 29d7a76..63d2d44 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -40,6 +40,7 @@
#include <selinux/android.h>
#if defined(__ANDROID__)
+#include "reboot_utils.h"
#include "selinux.h"
#else
#include "host_init_stubs.h"
@@ -425,20 +426,50 @@
return true;
}
-void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function) {
+static void InitAborter(const char* abort_message) {
+ // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
+ // simply abort instead of trying to reboot the system.
+ if (getpid() != 1) {
+ android::base::DefaultAborter(abort_message);
+ return;
+ }
+
+ InitFatalReboot();
+}
+
+// The kernel opens /dev/console and uses that fd for stdin/stdout/stderr if there is a serial
+// console enabled and no initramfs, otherwise it does not provide any fds for stdin/stdout/stderr.
+// SetStdioToDevNull() is used to close these existing fds if they exist and replace them with
+// /dev/null regardless.
+//
+// In the case that these fds are provided by the kernel, the exec of second stage init causes an
+// SELinux denial as it does not have access to /dev/console. In the case that they are not
+// provided, exec of any further process is potentially dangerous as the first fd's opened by that
+// process will take the stdin/stdout/stderr fileno's, which can cause issues if printf(), etc is
+// then used by that process.
+//
+// Lastly, simply calling SetStdioToDevNull() in first stage init is not enough, since first
+// stage init still runs in kernel context, future child processes will not have permissions to
+// access any fds that it opens, including the one opened below for /dev/null. Therefore,
+// SetStdioToDevNull() must be called again in second stage init.
+void SetStdioToDevNull(char** argv) {
// Make stdin/stdout/stderr all point to /dev/null.
int fd = open("/dev/null", O_RDWR);
if (fd == -1) {
int saved_errno = errno;
- android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+ android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
errno = saved_errno;
PLOG(FATAL) << "Couldn't open /dev/null";
}
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2) close(fd);
- android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > STDERR_FILENO) close(fd);
+}
+
+void InitKernelLogging(char** argv) {
+ SetFatalRebootTarget();
+ android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
}
bool IsRecoveryMode() {
diff --git a/init/util.h b/init/util.h
index 2232a0f..767620b 100644
--- a/init/util.h
+++ b/init/util.h
@@ -63,7 +63,8 @@
bool IsLegalPropertyName(const std::string& name);
-void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function);
+void SetStdioToDevNull(char** argv);
+void InitKernelLogging(char** argv);
bool IsRecoveryMode();
} // namespace init
} // namespace android
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index f1ca446..f71d0c3 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -86,6 +86,7 @@
const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
+ last_state_ = state_;
last_device_events_.events = 0;
last_proxy_events_.events = 0;