Loading debuggerd/debuggerd_test.cpp +35 −3 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/parseint.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/properties.h> #include <android-base/strings.h> #include <android-base/strings.h> Loading Loading @@ -149,7 +150,7 @@ class CrasherTest : public ::testing::Test { // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code. // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code. void FinishIntercept(int* result); void FinishIntercept(int* result); void StartProcess(std::function<void()> function); void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork); void StartCrasher(const std::string& crash_type); void StartCrasher(const std::string& crash_type); void FinishCrasher(); void FinishCrasher(); void AssertDeath(int signo); void AssertDeath(int signo); Loading Loading @@ -195,14 +196,14 @@ void CrasherTest::FinishIntercept(int* result) { } } } } void CrasherTest::StartProcess(std::function<void()> function) { void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) { unique_fd read_pipe; unique_fd read_pipe; unique_fd crasher_read_pipe; unique_fd crasher_read_pipe; if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { FAIL() << "failed to create pipe: " << strerror(errno); FAIL() << "failed to create pipe: " << strerror(errno); } } crasher_pid = fork(); crasher_pid = forker(); if (crasher_pid == -1) { if (crasher_pid == -1) { FAIL() << "fork failed: " << strerror(errno); FAIL() << "fork failed: " << strerror(errno); } else if (crasher_pid == 0) { } else if (crasher_pid == 0) { Loading Loading @@ -527,6 +528,37 @@ TEST_F(CrasherTest, capabilities) { ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); } } TEST_F(CrasherTest, fake_pid) { int intercept_result; unique_fd output_fd; // Prime the getpid/gettid caches. UNUSED(getpid()); UNUSED(gettid()); std::function<pid_t()> clone_fn = []() { return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr); }; StartProcess( []() { ASSERT_NE(getpid(), syscall(__NR_getpid)); ASSERT_NE(gettid(), syscall(__NR_gettid)); raise(SIGSEGV); }, clone_fn); StartIntercept(&output_fd); FinishCrasher(); AssertDeath(SIGSEGV); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); } TEST(crash_dump, zombie) { TEST(crash_dump, zombie) { pid_t forkpid = fork(); pid_t forkpid = fork(); Loading debuggerd/handler/debuggerd_handler.cpp +15 −5 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,16 @@ #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME // Wrappers that directly invoke the respective syscalls, in case the cached values are invalid. #pragma GCC poison getpid gettid static pid_t __getpid() { return syscall(__NR_getpid); } static pid_t __gettid() { return syscall(__NR_gettid); } static inline void futex_wait(volatile void* ftx, int value) { static inline void futex_wait(volatile void* ftx, int value) { syscall(__NR_futex, ftx, FUTEX_WAIT, value, nullptr, nullptr, 0); syscall(__NR_futex, ftx, FUTEX_WAIT, value, nullptr, nullptr, 0); } } Loading Loading @@ -124,7 +134,7 @@ static void log_signal_summary(int signum, const siginfo_t* info) { } } if (signum == DEBUGGER_SIGNAL) { if (signum == DEBUGGER_SIGNAL) { async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", gettid(), async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", __gettid(), thread_name); thread_name); return; return; } } Loading Loading @@ -177,7 +187,7 @@ static void log_signal_summary(int signum, const siginfo_t* info) { } } async_safe_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", async_safe_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", signum, signal_name, code_desc, addr_desc, gettid(), thread_name); signum, signal_name, code_desc, addr_desc, __gettid(), thread_name); } } /* /* Loading Loading @@ -337,7 +347,7 @@ static void resend_signal(siginfo_t* info, bool crash_dump_started) { // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered // when our signal handler returns. // when our signal handler returns. if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) { if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) { int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), info->si_signo, info); int rc = syscall(SYS_rt_tgsigqueueinfo, __getpid(), __gettid(), info->si_signo, info); if (rc != 0) { if (rc != 0) { fatal_errno("failed to resend signal during crash"); fatal_errno("failed to resend signal during crash"); } } Loading @@ -362,7 +372,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si)); si.si_signo = signal_number; si.si_signo = signal_number; si.si_code = SI_USER; si.si_code = SI_USER; si.si_pid = getpid(); si.si_pid = __getpid(); si.si_uid = getuid(); si.si_uid = getuid(); info = &si; info = &si; } else if (info->si_code >= 0 || info->si_code == SI_TKILL) { } else if (info->si_code >= 0 || info->si_code == SI_TKILL) { Loading Loading @@ -404,7 +414,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c debugger_thread_info thread_info = { debugger_thread_info thread_info = { .crash_dump_started = false, .crash_dump_started = false, .pseudothread_tid = -1, .pseudothread_tid = -1, .crashing_tid = gettid(), .crashing_tid = __gettid(), .signal_number = signal_number, .signal_number = signal_number, .info = info .info = info }; }; Loading Loading
debuggerd/debuggerd_test.cpp +35 −3 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/parseint.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/properties.h> #include <android-base/strings.h> #include <android-base/strings.h> Loading Loading @@ -149,7 +150,7 @@ class CrasherTest : public ::testing::Test { // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code. // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code. void FinishIntercept(int* result); void FinishIntercept(int* result); void StartProcess(std::function<void()> function); void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork); void StartCrasher(const std::string& crash_type); void StartCrasher(const std::string& crash_type); void FinishCrasher(); void FinishCrasher(); void AssertDeath(int signo); void AssertDeath(int signo); Loading Loading @@ -195,14 +196,14 @@ void CrasherTest::FinishIntercept(int* result) { } } } } void CrasherTest::StartProcess(std::function<void()> function) { void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) { unique_fd read_pipe; unique_fd read_pipe; unique_fd crasher_read_pipe; unique_fd crasher_read_pipe; if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { FAIL() << "failed to create pipe: " << strerror(errno); FAIL() << "failed to create pipe: " << strerror(errno); } } crasher_pid = fork(); crasher_pid = forker(); if (crasher_pid == -1) { if (crasher_pid == -1) { FAIL() << "fork failed: " << strerror(errno); FAIL() << "fork failed: " << strerror(errno); } else if (crasher_pid == 0) { } else if (crasher_pid == 0) { Loading Loading @@ -527,6 +528,37 @@ TEST_F(CrasherTest, capabilities) { ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); } } TEST_F(CrasherTest, fake_pid) { int intercept_result; unique_fd output_fd; // Prime the getpid/gettid caches. UNUSED(getpid()); UNUSED(gettid()); std::function<pid_t()> clone_fn = []() { return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr); }; StartProcess( []() { ASSERT_NE(getpid(), syscall(__NR_getpid)); ASSERT_NE(gettid(), syscall(__NR_gettid)); raise(SIGSEGV); }, clone_fn); StartIntercept(&output_fd); FinishCrasher(); AssertDeath(SIGSEGV); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); } TEST(crash_dump, zombie) { TEST(crash_dump, zombie) { pid_t forkpid = fork(); pid_t forkpid = fork(); Loading
debuggerd/handler/debuggerd_handler.cpp +15 −5 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,16 @@ #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME // Wrappers that directly invoke the respective syscalls, in case the cached values are invalid. #pragma GCC poison getpid gettid static pid_t __getpid() { return syscall(__NR_getpid); } static pid_t __gettid() { return syscall(__NR_gettid); } static inline void futex_wait(volatile void* ftx, int value) { static inline void futex_wait(volatile void* ftx, int value) { syscall(__NR_futex, ftx, FUTEX_WAIT, value, nullptr, nullptr, 0); syscall(__NR_futex, ftx, FUTEX_WAIT, value, nullptr, nullptr, 0); } } Loading Loading @@ -124,7 +134,7 @@ static void log_signal_summary(int signum, const siginfo_t* info) { } } if (signum == DEBUGGER_SIGNAL) { if (signum == DEBUGGER_SIGNAL) { async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", gettid(), async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", __gettid(), thread_name); thread_name); return; return; } } Loading Loading @@ -177,7 +187,7 @@ static void log_signal_summary(int signum, const siginfo_t* info) { } } async_safe_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", async_safe_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", signum, signal_name, code_desc, addr_desc, gettid(), thread_name); signum, signal_name, code_desc, addr_desc, __gettid(), thread_name); } } /* /* Loading Loading @@ -337,7 +347,7 @@ static void resend_signal(siginfo_t* info, bool crash_dump_started) { // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered // when our signal handler returns. // when our signal handler returns. if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) { if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) { int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), info->si_signo, info); int rc = syscall(SYS_rt_tgsigqueueinfo, __getpid(), __gettid(), info->si_signo, info); if (rc != 0) { if (rc != 0) { fatal_errno("failed to resend signal during crash"); fatal_errno("failed to resend signal during crash"); } } Loading @@ -362,7 +372,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si)); si.si_signo = signal_number; si.si_signo = signal_number; si.si_code = SI_USER; si.si_code = SI_USER; si.si_pid = getpid(); si.si_pid = __getpid(); si.si_uid = getuid(); si.si_uid = getuid(); info = &si; info = &si; } else if (info->si_code >= 0 || info->si_code == SI_TKILL) { } else if (info->si_code >= 0 || info->si_code == SI_TKILL) { Loading Loading @@ -404,7 +414,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c debugger_thread_info thread_info = { debugger_thread_info thread_info = { .crash_dump_started = false, .crash_dump_started = false, .pseudothread_tid = -1, .pseudothread_tid = -1, .crashing_tid = gettid(), .crashing_tid = __gettid(), .signal_number = signal_number, .signal_number = signal_number, .info = info .info = info }; }; Loading