summaryrefslogtreecommitdiff
path: root/debuggerd/handler/debuggerd_handler.cpp
diff options
context:
space:
mode:
authorBill Peckham <bpeckham@google.com>2018-08-31 14:51:14 -0700
committerBill Peckham <bpeckham@google.com>2018-08-31 14:51:14 -0700
commit444b55f41abdc074774a181cf3a0312bc5648a5b (patch)
tree427b6effbbdd9fe54776bd8e929e8f60c75d983d /debuggerd/handler/debuggerd_handler.cpp
parentf4c8b47b8efee20583b379cf1d7e53506d891e55 (diff)
Merge QP1A.180823.001
Change-Id: I43a054f155f100b3d7f414e17d3af9b900a05ab5
Diffstat (limited to 'debuggerd/handler/debuggerd_handler.cpp')
-rw-r--r--debuggerd/handler/debuggerd_handler.cpp29
1 files changed, 21 insertions, 8 deletions
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 7fb59daea..98594efdf 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -59,7 +59,16 @@
#include "protocol.h"
using android::base::Pipe;
-using android::base::unique_fd;
+
+// We muck with our fds in a 'thread' that doesn't share the same fd table.
+// Close fds in that thread with a raw close syscall instead of going through libc.
+struct FdsanBypassCloser {
+ static void Close(int fd) {
+ syscall(__NR_close, fd);
+ }
+};
+
+using unique_fd = android::base::unique_fd_impl<FdsanBypassCloser>;
// see man(2) prctl, specifically the section about PR_GET_NAME
#define MAX_TASK_NAME_LEN (16)
@@ -99,6 +108,7 @@ class ErrnoRestorer {
int saved_errno_;
};
+extern "C" void* android_fdsan_get_fd_table();
extern "C" void debuggerd_fallback_handler(siginfo_t*, ucontext_t*, void*);
static debuggerd_callbacks_t g_callbacks;
@@ -277,6 +287,7 @@ struct debugger_thread_info {
siginfo_t* siginfo;
void* ucontext;
uintptr_t abort_msg;
+ uintptr_t fdsan_table;
};
// Logging and contacting debuggerd requires free file descriptors, which we might not have.
@@ -299,7 +310,8 @@ static int debuggerd_dispatch_pseudothread(void* arg) {
debugger_thread_info* thread_info = static_cast<debugger_thread_info*>(arg);
for (int i = 0; i < 1024; ++i) {
- close(i);
+ // Don't use close to avoid bionic's file descriptor ownership checks.
+ syscall(__NR_close, i);
}
int devnull = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
@@ -320,23 +332,23 @@ static int debuggerd_dispatch_pseudothread(void* arg) {
}
// ucontext_t is absurdly large on AArch64, so piece it together manually with writev.
- uint32_t version = 1;
- constexpr size_t expected =
- sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(uintptr_t);
+ uint32_t version = 2;
+ constexpr size_t expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV2);
errno = 0;
if (fcntl(output_write.get(), F_SETPIPE_SZ, expected) < static_cast<int>(expected)) {
- fatal_errno("failed to set pipe bufer size");
+ fatal_errno("failed to set pipe buffer size");
}
- struct iovec iovs[4] = {
+ struct iovec iovs[5] = {
{.iov_base = &version, .iov_len = sizeof(version)},
{.iov_base = thread_info->siginfo, .iov_len = sizeof(siginfo_t)},
{.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
{.iov_base = &thread_info->abort_msg, .iov_len = sizeof(uintptr_t)},
+ {.iov_base = &thread_info->fdsan_table, .iov_len = sizeof(uintptr_t)},
};
- ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 4));
+ ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 5));
if (rc == -1) {
fatal_errno("failed to write crash info");
} else if (rc != expected) {
@@ -494,6 +506,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
.siginfo = info,
.ucontext = context,
.abort_msg = reinterpret_cast<uintptr_t>(abort_message),
+ .fdsan_table = reinterpret_cast<uintptr_t>(android_fdsan_get_fd_table()),
};
// Set PR_SET_DUMPABLE to 1, so that crash_dump can ptrace us.