Loading adb/commandline.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -1944,7 +1944,8 @@ static int install_multiple_app(int argc, const char** argv) { for (int i = argc - 1; i >= 0; i--) { const char* file = argv[i]; if (android::base::EndsWithIgnoreCase(file, ".apk")) { if (android::base::EndsWithIgnoreCase(file, ".apk") || android::base::EndsWithIgnoreCase(file, ".dm")) { struct stat sb; if (stat(file, &sb) != -1) total_size += sb.st_size; first_apk = i; Loading Loading @@ -2005,9 +2006,8 @@ static int install_multiple_app(int argc, const char** argv) { } std::string cmd = android::base::StringPrintf( "%s install-write -S %" PRIu64 " %d %d_%s -", install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, i, android::base::Basename(file).c_str()); "%s install-write -S %" PRIu64 " %d %s -", install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, android::base::Basename(file).c_str()); int localFd = adb_open(file, O_RDONLY); if (localFd < 0) { Loading debuggerd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ cc_test { "libcutils", "libdebuggerd_client", "liblog", "libminijail", "libnativehelper" ], Loading debuggerd/Android.mk 0 → 100644 +23 −0 Original line number Diff line number Diff line LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := crash_dump.policy LOCAL_MODULE_CLASS := ETC LOCAL_MULTILIB := both ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64)) LOCAL_MODULE_STEM_32 := crash_dump.arm.policy LOCAL_MODULE_STEM_64 := crash_dump.arm64.policy endif ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64)) LOCAL_MODULE_STEM_32 := crash_dump.x86.policy LOCAL_MODULE_STEM_64 := crash_dump.x86_64.policy endif LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy LOCAL_SRC_FILES_arm := seccomp_policy/crash_dump.arm.policy LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy include $(BUILD_PREBUILT) debuggerd/debuggerd_test.cpp +140 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,9 @@ #include <cutils/sockets.h> #include <gtest/gtest.h> #include <libminijail.h> #include <scoped_minijail.h> #include "debuggerd/handler.h" #include "protocol.h" #include "tombstoned/tombstoned.h" Loading Loading @@ -77,8 +80,7 @@ constexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb"; }() #define ASSERT_BACKTRACE_FRAME(result, frame_name) \ ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX \ R"(/libc.so \()" frame_name R"(\+)") ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ \S+ \()" frame_name R"(\+)"); static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd, InterceptStatus* status, DebuggerdDumpType intercept_type) { Loading Loading @@ -565,6 +567,141 @@ TEST_F(CrasherTest, fake_pid) { ASSERT_BACKTRACE_FRAME(result, "tgkill"); } static const char* const kDebuggerdSeccompPolicy = "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy"; pid_t seccomp_fork() { unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC)); if (policy_fd == -1) { LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy; } ScopedMinijail jail{minijail_new()}; if (!jail) { LOG(FATAL) << "failed to create minijail"; } minijail_no_new_privs(jail.get()); minijail_log_seccomp_filter_failures(jail.get()); minijail_use_seccomp_filter(jail.get()); minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release()); pid_t result = fork(); if (result == -1) { return result; } else if (result != 0) { return result; } // Spawn and detach a thread that spins forever. std::atomic<bool> thread_ready(false); std::thread thread([&jail, &thread_ready]() { minijail_enter(jail.get()); thread_ready = true; for (;;) ; }); thread.detach(); while (!thread_ready) { continue; } minijail_enter(jail.get()); return result; } TEST_F(CrasherTest, seccomp_crash) { int intercept_result; unique_fd output_fd; StartProcess([]() { abort(); }, &seccomp_fork); StartIntercept(&output_fd); FinishCrasher(); AssertDeath(SIGABRT); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "abort"); } __attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) { siginfo_t siginfo; siginfo.si_code = SI_QUEUE; siginfo.si_pid = getpid(); siginfo.si_uid = getuid(); if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) { PLOG(FATAL) << "invalid dump type"; } siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace; if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), DEBUGGER_SIGNAL, &siginfo) != 0) { PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self"; return false; } return true; } TEST_F(CrasherTest, seccomp_tombstone) { int intercept_result; unique_fd output_fd; static const auto dump_type = kDebuggerdTombstone; StartProcess( []() { raise_debugger_signal(dump_type); _exit(0); }, &seccomp_fork); StartIntercept(&output_fd, dump_type); FinishCrasher(); AssertDeath(0); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal"); } TEST_F(CrasherTest, seccomp_backtrace) { int intercept_result; unique_fd output_fd; static const auto dump_type = kDebuggerdNativeBacktrace; StartProcess( []() { raise_debugger_signal(dump_type); _exit(0); }, &seccomp_fork); StartIntercept(&output_fd, dump_type); FinishCrasher(); AssertDeath(0); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal"); } TEST_F(CrasherTest, seccomp_crash_logcat) { StartProcess([]() { abort(); }, &seccomp_fork); FinishCrasher(); // Make sure we don't get SIGSYS when trying to dump a crash to logcat. AssertDeath(SIGABRT); } TEST_F(CrasherTest, competing_tracer) { int intercept_result; unique_fd output_fd; Loading debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h +3 −3 Original line number Diff line number Diff line Loading @@ -40,16 +40,16 @@ int open_tombstone(std::string* path); /* Creates a tombstone file and writes the crash dump to it. */ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address, const std::map<pid_t, std::string>& threads, uint64_t abort_msg_address, std::string* amfd_data); void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo, void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo, ucontext_t* ucontext); void engrave_tombstone(android::base::unique_fd output_fd, BacktraceMap* map, unwindstack::Memory* process_memory, const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread, uintptr_t abort_msg_address, OpenFilesList* open_files, uint64_t abort_msg_address, OpenFilesList* open_files, std::string* amfd_data); #endif // _DEBUGGERD_TOMBSTONE_H Loading
adb/commandline.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -1944,7 +1944,8 @@ static int install_multiple_app(int argc, const char** argv) { for (int i = argc - 1; i >= 0; i--) { const char* file = argv[i]; if (android::base::EndsWithIgnoreCase(file, ".apk")) { if (android::base::EndsWithIgnoreCase(file, ".apk") || android::base::EndsWithIgnoreCase(file, ".dm")) { struct stat sb; if (stat(file, &sb) != -1) total_size += sb.st_size; first_apk = i; Loading Loading @@ -2005,9 +2006,8 @@ static int install_multiple_app(int argc, const char** argv) { } std::string cmd = android::base::StringPrintf( "%s install-write -S %" PRIu64 " %d %d_%s -", install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, i, android::base::Basename(file).c_str()); "%s install-write -S %" PRIu64 " %d %s -", install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, android::base::Basename(file).c_str()); int localFd = adb_open(file, O_RDONLY); if (localFd < 0) { Loading
debuggerd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ cc_test { "libcutils", "libdebuggerd_client", "liblog", "libminijail", "libnativehelper" ], Loading
debuggerd/Android.mk 0 → 100644 +23 −0 Original line number Diff line number Diff line LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := crash_dump.policy LOCAL_MODULE_CLASS := ETC LOCAL_MULTILIB := both ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64)) LOCAL_MODULE_STEM_32 := crash_dump.arm.policy LOCAL_MODULE_STEM_64 := crash_dump.arm64.policy endif ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64)) LOCAL_MODULE_STEM_32 := crash_dump.x86.policy LOCAL_MODULE_STEM_64 := crash_dump.x86_64.policy endif LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy LOCAL_SRC_FILES_arm := seccomp_policy/crash_dump.arm.policy LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy include $(BUILD_PREBUILT)
debuggerd/debuggerd_test.cpp +140 −3 Original line number Diff line number Diff line Loading @@ -41,6 +41,9 @@ #include <cutils/sockets.h> #include <gtest/gtest.h> #include <libminijail.h> #include <scoped_minijail.h> #include "debuggerd/handler.h" #include "protocol.h" #include "tombstoned/tombstoned.h" Loading Loading @@ -77,8 +80,7 @@ constexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb"; }() #define ASSERT_BACKTRACE_FRAME(result, frame_name) \ ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX \ R"(/libc.so \()" frame_name R"(\+)") ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ \S+ \()" frame_name R"(\+)"); static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd, InterceptStatus* status, DebuggerdDumpType intercept_type) { Loading Loading @@ -565,6 +567,141 @@ TEST_F(CrasherTest, fake_pid) { ASSERT_BACKTRACE_FRAME(result, "tgkill"); } static const char* const kDebuggerdSeccompPolicy = "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy"; pid_t seccomp_fork() { unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC)); if (policy_fd == -1) { LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy; } ScopedMinijail jail{minijail_new()}; if (!jail) { LOG(FATAL) << "failed to create minijail"; } minijail_no_new_privs(jail.get()); minijail_log_seccomp_filter_failures(jail.get()); minijail_use_seccomp_filter(jail.get()); minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release()); pid_t result = fork(); if (result == -1) { return result; } else if (result != 0) { return result; } // Spawn and detach a thread that spins forever. std::atomic<bool> thread_ready(false); std::thread thread([&jail, &thread_ready]() { minijail_enter(jail.get()); thread_ready = true; for (;;) ; }); thread.detach(); while (!thread_ready) { continue; } minijail_enter(jail.get()); return result; } TEST_F(CrasherTest, seccomp_crash) { int intercept_result; unique_fd output_fd; StartProcess([]() { abort(); }, &seccomp_fork); StartIntercept(&output_fd); FinishCrasher(); AssertDeath(SIGABRT); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "abort"); } __attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) { siginfo_t siginfo; siginfo.si_code = SI_QUEUE; siginfo.si_pid = getpid(); siginfo.si_uid = getuid(); if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) { PLOG(FATAL) << "invalid dump type"; } siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace; if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), DEBUGGER_SIGNAL, &siginfo) != 0) { PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self"; return false; } return true; } TEST_F(CrasherTest, seccomp_tombstone) { int intercept_result; unique_fd output_fd; static const auto dump_type = kDebuggerdTombstone; StartProcess( []() { raise_debugger_signal(dump_type); _exit(0); }, &seccomp_fork); StartIntercept(&output_fd, dump_type); FinishCrasher(); AssertDeath(0); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal"); } TEST_F(CrasherTest, seccomp_backtrace) { int intercept_result; unique_fd output_fd; static const auto dump_type = kDebuggerdNativeBacktrace; StartProcess( []() { raise_debugger_signal(dump_type); _exit(0); }, &seccomp_fork); StartIntercept(&output_fd, dump_type); FinishCrasher(); AssertDeath(0); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal"); } TEST_F(CrasherTest, seccomp_crash_logcat) { StartProcess([]() { abort(); }, &seccomp_fork); FinishCrasher(); // Make sure we don't get SIGSYS when trying to dump a crash to logcat. AssertDeath(SIGABRT); } TEST_F(CrasherTest, competing_tracer) { int intercept_result; unique_fd output_fd; Loading
debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h +3 −3 Original line number Diff line number Diff line Loading @@ -40,16 +40,16 @@ int open_tombstone(std::string* path); /* Creates a tombstone file and writes the crash dump to it. */ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address, const std::map<pid_t, std::string>& threads, uint64_t abort_msg_address, std::string* amfd_data); void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo, void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo, ucontext_t* ucontext); void engrave_tombstone(android::base::unique_fd output_fd, BacktraceMap* map, unwindstack::Memory* process_memory, const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread, uintptr_t abort_msg_address, OpenFilesList* open_files, uint64_t abort_msg_address, OpenFilesList* open_files, std::string* amfd_data); #endif // _DEBUGGERD_TOMBSTONE_H