Merge changes from topic "fdsan_abort_msg"

* changes:
  debuggerd_test: add test for fdsan abort message.
  debuggerd_handler: receive abort messages via sigqueue(DEBUGGER_SIGNAL).
This commit is contained in:
Josh Gao 2018-08-28 20:20:21 +00:00 committed by Gerrit Code Review
commit 06512082d3
2 changed files with 45 additions and 9 deletions

View file

@ -29,6 +29,7 @@
#include <regex>
#include <thread>
#include <android/fdsan.h>
#include <android/set_abort_message.h>
#include <android-base/file.h>
@ -801,6 +802,31 @@ TEST_F(CrasherTest, competing_tracer) {
AssertDeath(SIGABRT);
}
TEST_F(CrasherTest, fdsan_warning_abort_message) {
int intercept_result;
unique_fd output_fd;
StartProcess([]() {
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
unique_fd fd(open("/dev/null", O_RDONLY | O_CLOEXEC));
if (fd == -1) {
abort();
}
close(fd.get());
_exit(0);
});
StartIntercept(&output_fd);
FinishCrasher();
AssertDeath(0);
FinishIntercept(&intercept_result);
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
std::string result;
ConsumeFd(std::move(output_fd), &result);
ASSERT_MATCH(result, "Abort message: 'attempted to close");
}
TEST(crash_dump, zombie) {
pid_t forkpid = fork();

View file

@ -457,14 +457,14 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
info = nullptr;
}
struct siginfo si = {};
struct siginfo dummy_info = {};
if (!info) {
memset(&si, 0, sizeof(si));
si.si_signo = signal_number;
si.si_code = SI_USER;
si.si_pid = __getpid();
si.si_uid = getuid();
info = &si;
memset(&dummy_info, 0, sizeof(dummy_info));
dummy_info.si_signo = signal_number;
dummy_info.si_code = SI_USER;
dummy_info.si_pid = __getpid();
dummy_info.si_uid = getuid();
info = &dummy_info;
} else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
// rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels
// that contain commit 66dd34a (3.9+). The manpage claims to only allow
@ -473,8 +473,18 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
}
void* abort_message = nullptr;
if (signal_number != DEBUGGER_SIGNAL && g_callbacks.get_abort_message) {
abort_message = g_callbacks.get_abort_message();
if (signal_number == DEBUGGER_SIGNAL) {
if (info->si_code == SI_QUEUE && info->si_pid == __getpid()) {
// Allow for the abort message to be explicitly specified via the sigqueue value.
// Keep the bottom bit intact for representing whether we want a backtrace or a tombstone.
uintptr_t value = reinterpret_cast<uintptr_t>(info->si_ptr);
abort_message = reinterpret_cast<void*>(value & ~1);
info->si_ptr = reinterpret_cast<void*>(value & 1);
}
} else {
if (g_callbacks.get_abort_message) {
abort_message = g_callbacks.get_abort_message();
}
}
// If sival_int is ~0, it means that the fallback handler has been called