diff options
| author | Christopher Ferris <cferris@google.com> | 2022-02-09 17:57:21 -0800 |
|---|---|---|
| committer | Christopher Ferris <cferris@google.com> | 2022-02-16 15:02:38 -0800 |
| commit | d5662795ec74190bb53105a3ee7f2891bc88838f (patch) | |
| tree | 95944216b66afbf7899f7348ceffcdd6f323e523 /debuggerd/handler/debuggerd_fallback.cpp | |
| parent | 56eb6b9d515de540cd3a64e08ee0a879438dd160 (diff) | |
Dump threads in tombstone fallback path.
When dumping a tombstone using the fallback path, only the main
thread was showing up. Modify the code to dump the threads using
a slightly different path for the tombstone generation code.
In addition, while looking at this code, two MTE variables were
not set in the tombstone fallback code. Added those variables
so MTE devices will work properly in this fallback path.
Modified the tombstone unit tests for seccomp to have
multiple threads and verify those threads show up in the tombstone.
Bug: 208933016
Test: Ran unit tests.
Test: Ran debuggerd <PID> on a privileged process and verified
Test: all threads dumped. Also verified that the tagged_addr_ctrl
Test: variable is present on the raven device.
Change-Id: I16eadb0cc2c37a7dbc5cac16af9b5051008b5127
Diffstat (limited to 'debuggerd/handler/debuggerd_fallback.cpp')
| -rw-r--r-- | debuggerd/handler/debuggerd_fallback.cpp | 61 |
1 files changed, 17 insertions, 44 deletions
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp index baf994fa19..4c1f9eb470 100644 --- a/debuggerd/handler/debuggerd_fallback.cpp +++ b/debuggerd/handler/debuggerd_fallback.cpp @@ -98,32 +98,6 @@ static void debuggerd_fallback_tombstone(int output_fd, int proto_fd, ucontext_t __linker_disable_fallback_allocator(); } -static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) { - pid_t current_tid = gettid(); - char buf[BUFSIZ]; - snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid); - DIR* dir = opendir(buf); - - if (!dir) { - async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno)); - return; - } - - struct dirent* ent; - while ((ent = readdir(dir))) { - char* end; - long tid = strtol(ent->d_name, &end, 10); - if (end == ent->d_name || *end != '\0') { - continue; - } - - if (tid != current_tid) { - callback(tid, output_fd); - } - } - closedir(dir); -} - static bool forward_output(int src_fd, int dst_fd, pid_t expected_tid) { // Make sure the thread actually got the signal. struct pollfd pfd = { @@ -216,21 +190,21 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { } // Only allow one thread to perform a trace at a time. - static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; - int ret = pthread_mutex_trylock(&trace_mutex); - if (ret != 0) { - async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", - strerror(ret)); + static std::mutex trace_mutex; + if (!trace_mutex.try_lock()) { + async_safe_format_log(ANDROID_LOG_INFO, "libc", "trace lock failed"); return; } + std::lock_guard<std::mutex> scoped_lock(trace_mutex, std::adopt_lock); + // Fetch output fd from tombstoned. unique_fd tombstone_socket, output_fd; if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, nullptr, kDebuggerdNativeBacktrace)) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "missing crash_dump_fallback() in selinux policy?"); - goto exit; + return; } dump_backtrace_header(output_fd.get()); @@ -239,15 +213,15 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { debuggerd_fallback_trace(output_fd.get(), ucontext); // Send a signal to all of our siblings, asking them to dump their stack. - iterate_siblings( - [](pid_t tid, int output_fd) { + pid_t current_tid = gettid(); + if (!iterate_tids(current_tid, [&output_fd](pid_t tid) { // Use a pipe, to be able to detect situations where the thread gracefully exits before // receiving our signal. unique_fd pipe_read, pipe_write; if (!Pipe(&pipe_read, &pipe_write)) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", strerror(errno)); - return false; + return; } uint64_t expected = pack_thread_fd(-1, -1); @@ -257,7 +231,7 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "thread %d is already outputting to fd %d?", tid, fd); close(sent_fd); - return false; + return; } siginfo_t siginfo = {}; @@ -269,10 +243,10 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", tid, strerror(errno)); - return false; + return; } - bool success = forward_output(pipe_read.get(), output_fd, tid); + bool success = forward_output(pipe_read.get(), output_fd.get(), tid); if (!success) { async_safe_format_log(ANDROID_LOG_ERROR, "libc", "timeout expired while waiting for thread %d to dump", tid); @@ -288,15 +262,14 @@ static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { } } - return true; - }, - output_fd.get()); + return; + })) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open /proc/%d/task: %s", + current_tid, strerror(errno)); + } dump_backtrace_footer(output_fd.get()); tombstoned_notify_completion(tombstone_socket.get()); - -exit: - pthread_mutex_unlock(&trace_mutex); } static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) { |
