summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2012-10-02 15:23:20 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-10-02 15:23:20 -0700
commit98957db5536e93724c2e9e6bd19d5063f9d4dc2c (patch)
tree5eb31ce5e31c4a3bd30bd492bdb367d228edb633
parent2e0452cbd1f5b981fbadb4021198d2c27ec1cde3 (diff)
parentf84bc8d6f6368f1c846124a8168761ee8cc589c0 (diff)
downloadbionic-98957db5536e93724c2e9e6bd19d5063f9d4dc2c.zip
bionic-98957db5536e93724c2e9e6bd19d5063f9d4dc2c.tar.gz
bionic-98957db5536e93724c2e9e6bd19d5063f9d4dc2c.tar.bz2
Merge "Test flags before using "info"" into jb-mr1-dev
-rw-r--r--linker/debugger.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/linker/debugger.c b/linker/debugger.c
index dde66f3..e4d4ae9 100644
--- a/linker/debugger.c
+++ b/linker/debugger.c
@@ -29,14 +29,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <ctype.h>
+#include <stdbool.h>
#include <signal.h>
-#include <sys/mman.h>
#include <sys/prctl.h>
#include <errno.h>
-
-#include "linker.h"
-
#include <sys/socket.h>
#include <sys/un.h>
@@ -113,11 +109,15 @@ static int socket_abstract_client(const char *name, int type)
#include <../libc/private/logd.h>
/*
- * Writes a summary of the signal to the log file.
+ * Writes a summary of the signal to the log file. We do this so that, if
+ * for some reason we're not able to contact debuggerd, there is still some
+ * indication of the failure in the log.
*
* We could be here as a result of native heap corruption, or while a
* mutex is being held, so we don't want to use any libc functions that
* could allocate memory or hold a lock.
+ *
+ * "info" will be NULL if the siginfo_t information was not available.
*/
static void logSignalSummary(int signum, const siginfo_t* info)
{
@@ -145,14 +145,46 @@ static void logSignalSummary(int signum, const siginfo_t* info)
// implies that 16 byte names are not.
threadname[MAX_TASK_NAME_LEN] = 0;
}
- format_buffer(buffer, sizeof(buffer),
- "Fatal signal %d (%s) at 0x%08x (code=%d), thread %d (%s)",
- signum, signame, info->si_addr, info->si_code, gettid(), threadname);
+ if (info != NULL) {
+ format_buffer(buffer, sizeof(buffer),
+ "Fatal signal %d (%s) at 0x%08x (code=%d), thread %d (%s)",
+ signum, signame, info->si_addr, info->si_code, gettid(), threadname);
+ } else {
+ format_buffer(buffer, sizeof(buffer),
+ "Fatal signal %d (%s), thread %d (%s)",
+ signum, signame, gettid(), threadname);
+ }
__libc_android_log_write(ANDROID_LOG_FATAL, "libc", buffer);
}
/*
+ * Returns true if the handler for signal "signum" has SA_SIGINFO set.
+ */
+static bool haveSiginfo(int signum)
+{
+ struct sigaction oldact, newact;
+
+ memset(&newact, 0, sizeof(newact));
+ newact.sa_handler = SIG_DFL;
+ newact.sa_flags = SA_RESTART;
+ sigemptyset(&newact.sa_mask);
+
+ if (sigaction(signum, &newact, &oldact) < 0) {
+ __libc_android_log_write(ANDROID_LOG_FATAL, "libc",
+ "Failed testing for SA_SIGINFO");
+ return 0;
+ }
+ bool ret = (oldact.sa_flags & SA_SIGINFO) != 0;
+
+ if (sigaction(signum, &oldact, NULL) < 0) {
+ __libc_android_log_write(ANDROID_LOG_FATAL, "libc",
+ "Restore failed in test for SA_SIGINFO");
+ }
+ return ret;
+}
+
+/*
* Catches fatal signals so we can ask debuggerd to ptrace us before
* we crash.
*/
@@ -162,6 +194,14 @@ void debugger_signal_handler(int n, siginfo_t* info, void* unused __attribute__(
unsigned tid;
int s;
+ /*
+ * It's possible somebody cleared the SA_SIGINFO flag, which would mean
+ * our "info" arg holds an undefined value.
+ */
+ if (!haveSiginfo(n)) {
+ info = NULL;
+ }
+
logSignalSummary(n, info);
tid = gettid();