diff options
author | Elliott Hughes <enh@google.com> | 2018-04-25 17:00:14 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2018-04-26 08:19:17 -0700 |
commit | 70d8f289454c9b691ec5421b0ed0354b6baaace8 (patch) | |
tree | 065570ea913e9c631e13807522fa0361e5c26e5e | |
parent | f88905d231367eeeb72379d9eb2debbadb47b788 (diff) | |
download | system_core-70d8f289454c9b691ec5421b0ed0354b6baaace8.tar.gz system_core-70d8f289454c9b691ec5421b0ed0354b6baaace8.tar.bz2 system_core-70d8f289454c9b691ec5421b0ed0354b6baaace8.zip |
Show signal sender for SI_FROMUSER signals.
Suicide doesn't change:
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
But homicide now looks like this (this is `sleep 666` killed by
`kill -SEGV` as root:
signal 11 (SIGSEGV), code 0 (SI_USER from pid 4446, uid 0), fault addr --------
Bug: http://b/78594105
Test: manual
Change-Id: I8c2feafba8cc5a3db85e8250004d428a464c5d9e
-rw-r--r-- | debuggerd/handler/debuggerd_handler.cpp | 20 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/include/libdebuggerd/utility.h | 8 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/tombstone.cpp | 22 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/utility.cpp | 40 |
4 files changed, 54 insertions, 36 deletions
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp index 05e6efa60..c07a34a70 100644 --- a/debuggerd/handler/debuggerd_handler.cpp +++ b/debuggerd/handler/debuggerd_handler.cpp @@ -169,24 +169,26 @@ static void log_signal_summary(const siginfo_t* info) { return; } - const char* signal_name = get_signame(info->si_signo); - bool has_address = signal_has_si_addr(info->si_signo, info->si_code); - - // Many signals don't have an address. + // Many signals don't have an address or sender. char addr_desc[32] = ""; // ", fault addr 0x1234" - if (has_address) { + if (signal_has_si_addr(info)) { async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr); } + pid_t self_pid = __getpid(); + char sender_desc[32] = {}; // " from pid 1234, uid 666" + if (signal_has_sender(info, self_pid)) { + get_signal_sender(sender_desc, sizeof(sender_desc), info); + } char main_thread_name[MAX_TASK_NAME_LEN + 1]; if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) { strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name)); } - async_safe_format_log( - ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s), code %d (%s)%s in tid %d (%s), pid %d (%s)", - info->si_signo, signal_name, info->si_code, get_sigcode(info->si_signo, info->si_code), - addr_desc, __gettid(), thread_name, __getpid(), main_thread_name); + async_safe_format_log(ANDROID_LOG_FATAL, "libc", + "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)", + info->si_signo, get_signame(info), info->si_code, get_sigcode(info), + sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name); } /* diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h index 7b04e7192..7c5304e84 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h @@ -74,8 +74,10 @@ void read_with_default(const char* path, char* buf, size_t len, const char* defa void drop_capabilities(); -bool signal_has_si_addr(int si_signo, int si_code); -const char* get_signame(int sig); -const char* get_sigcode(int signo, int code); +bool signal_has_sender(const siginfo_t*, pid_t caller_pid); +bool signal_has_si_addr(const siginfo_t*); +void get_signal_sender(char* buf, size_t n, const siginfo_t*); +const char* get_signame(const siginfo_t*); +const char* get_sigcode(const siginfo_t*); #endif // _DEBUGGERD_UTILITY_H diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp index af8072e76..e11be1ea7 100644 --- a/debuggerd/libdebuggerd/tombstone.cpp +++ b/debuggerd/libdebuggerd/tombstone.cpp @@ -102,18 +102,24 @@ static void dump_probable_cause(log_t* log, const siginfo_t* si) { if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str()); } -static void dump_signal_info(log_t* log, const siginfo_t* si) { +static void dump_signal_info(log_t* log, const ThreadInfo& thread_info) { char addr_desc[32]; // ", fault addr 0x1234" - if (signal_has_si_addr(si->si_signo, si->si_code)) { - snprintf(addr_desc, sizeof(addr_desc), "%p", si->si_addr); + if (signal_has_si_addr(thread_info.siginfo)) { + snprintf(addr_desc, sizeof(addr_desc), "%p", thread_info.siginfo->si_addr); } else { snprintf(addr_desc, sizeof(addr_desc), "--------"); } - _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si->si_signo, - get_signame(si->si_signo), si->si_code, get_sigcode(si->si_signo, si->si_code), addr_desc); + char sender_desc[32] = {}; // " from pid 1234, uid 666" + if (signal_has_sender(thread_info.siginfo, thread_info.pid)) { + get_signal_sender(sender_desc, sizeof(sender_desc), thread_info.siginfo); + } + + _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s%s), fault addr %s\n", + thread_info.siginfo->si_signo, get_signame(thread_info.siginfo), + thread_info.siginfo->si_code, get_sigcode(thread_info.siginfo), sender_desc, addr_desc); - dump_probable_cause(log, si); + dump_probable_cause(log, thread_info.siginfo); } static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) { @@ -412,7 +418,7 @@ static bool dump_thread(log_t* log, BacktraceMap* map, Memory* process_memory, dump_thread_info(log, thread_info); if (thread_info.siginfo) { - dump_signal_info(log, thread_info.siginfo); + dump_signal_info(log, thread_info); } if (primary_thread) { @@ -442,7 +448,7 @@ static bool dump_thread(log_t* log, BacktraceMap* map, Memory* process_memory, if (map) { uint64_t addr = 0; siginfo_t* si = thread_info.siginfo; - if (signal_has_si_addr(si->si_signo, si->si_code)) { + if (signal_has_si_addr(si)) { addr = reinterpret_cast<uint64_t>(si->si_addr); } dump_all_maps(log, map, process_memory, addr); diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp index 1ad180073..1f6f3c803 100644 --- a/debuggerd/libdebuggerd/utility.cpp +++ b/debuggerd/libdebuggerd/utility.cpp @@ -254,13 +254,13 @@ void drop_capabilities() { } } -bool signal_has_si_addr(int si_signo, int si_code) { +bool signal_has_si_addr(const siginfo_t* si) { // Manually sent signals won't have si_addr. - if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) { + if (si->si_code == SI_USER || si->si_code == SI_QUEUE || si->si_code == SI_TKILL) { return false; } - switch (si_signo) { + switch (si->si_signo) { case SIGBUS: case SIGFPE: case SIGILL: @@ -272,8 +272,16 @@ bool signal_has_si_addr(int si_signo, int si_code) { } } -const char* get_signame(int sig) { - switch (sig) { +bool signal_has_sender(const siginfo_t* si, pid_t caller_pid) { + return SI_FROMUSER(si) && (si->si_pid != 0) && (si->si_pid != caller_pid); +} + +void get_signal_sender(char* buf, size_t n, const siginfo_t* si) { + snprintf(buf, n, " from pid %d, uid %d", si->si_pid, si->si_uid); +} + +const char* get_signame(const siginfo_t* si) { + switch (si->si_signo) { case SIGABRT: return "SIGABRT"; case SIGBUS: return "SIGBUS"; case SIGFPE: return "SIGFPE"; @@ -290,11 +298,11 @@ const char* get_signame(int sig) { } } -const char* get_sigcode(int signo, int code) { +const char* get_sigcode(const siginfo_t* si) { // Try the signal-specific codes... - switch (signo) { + switch (si->si_signo) { case SIGILL: - switch (code) { + switch (si->si_code) { case ILL_ILLOPC: return "ILL_ILLOPC"; case ILL_ILLOPN: return "ILL_ILLOPN"; case ILL_ILLADR: return "ILL_ILLADR"; @@ -307,7 +315,7 @@ const char* get_sigcode(int signo, int code) { static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code"); break; case SIGBUS: - switch (code) { + switch (si->si_code) { case BUS_ADRALN: return "BUS_ADRALN"; case BUS_ADRERR: return "BUS_ADRERR"; case BUS_OBJERR: return "BUS_OBJERR"; @@ -317,7 +325,7 @@ const char* get_sigcode(int signo, int code) { static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code"); break; case SIGFPE: - switch (code) { + switch (si->si_code) { case FPE_INTDIV: return "FPE_INTDIV"; case FPE_INTOVF: return "FPE_INTOVF"; case FPE_FLTDIV: return "FPE_FLTDIV"; @@ -330,7 +338,7 @@ const char* get_sigcode(int signo, int code) { static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code"); break; case SIGSEGV: - switch (code) { + switch (si->si_code) { case SEGV_MAPERR: return "SEGV_MAPERR"; case SEGV_ACCERR: return "SEGV_ACCERR"; #if defined(SEGV_BNDERR) @@ -350,21 +358,21 @@ const char* get_sigcode(int signo, int code) { break; #if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too. case SIGSYS: - switch (code) { + switch (si->si_code) { case SYS_SECCOMP: return "SYS_SECCOMP"; } static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code"); break; #endif case SIGTRAP: - switch (code) { + switch (si->si_code) { case TRAP_BRKPT: return "TRAP_BRKPT"; case TRAP_TRACE: return "TRAP_TRACE"; case TRAP_BRANCH: return "TRAP_BRANCH"; case TRAP_HWBKPT: return "TRAP_HWBKPT"; } - if ((code & 0xff) == SIGTRAP) { - switch ((code >> 8) & 0xff) { + if ((si->si_code & 0xff) == SIGTRAP) { + switch ((si->si_code >> 8) & 0xff) { case PTRACE_EVENT_FORK: return "PTRACE_EVENT_FORK"; case PTRACE_EVENT_VFORK: @@ -387,7 +395,7 @@ const char* get_sigcode(int signo, int code) { break; } // Then the other codes... - switch (code) { + switch (si->si_code) { case SI_USER: return "SI_USER"; case SI_KERNEL: return "SI_KERNEL"; case SI_QUEUE: return "SI_QUEUE"; |