예제 #1
0
static void send_debuggerd_packet(siginfo_t* info) {
  int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
  if (s == -1) {
    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
                      strerror(errno));
    return;
  }

  // debuggerd knows our pid from the credentials on the
  // local socket but we need to tell it the tid of the crashing thread.
  // debuggerd will be paranoid and verify that we sent a tid
  // that's actually in our process.
  debugger_msg_t msg;
  msg.action = DEBUGGER_ACTION_CRASH;
  msg.tid = gettid();
  msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message);
  msg.original_si_code = (info != NULL) ? info->si_code : 0;
  int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
  if (ret == sizeof(msg)) {
    char debuggerd_ack;
    ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
    int saved_errno = errno;
    notify_gdb_of_libraries();
    errno = saved_errno;
  } else {
    // read or write failed -- broken connection?
    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
                      strerror(errno));
  }

  close(s);
}
예제 #2
0
static void send_debuggerd_packet(siginfo_t* info) {
  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
    // process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
    // Honor that intention by not connecting to debuggerd and asking it
    // to dump our internal state.
    __libc_format_log(ANDROID_LOG_INFO, "libc",
                      "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
    return;
  }

  int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
  if (s == -1) {
    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
                      strerror(errno));
    return;
  }

  // debuggerd knows our pid from the credentials on the
  // local socket but we need to tell it the tid of the crashing thread.
  // debuggerd will be paranoid and verify that we sent a tid
  // that's actually in our process.
  debugger_msg_t msg;
  msg.action = DEBUGGER_ACTION_CRASH;
  msg.tid = gettid();
  msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message);
  msg.original_si_code = (info != NULL) ? info->si_code : 0;
  int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
  if (ret == sizeof(msg)) {
    char debuggerd_ack;
    ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
    int saved_errno = errno;
    notify_gdb_of_libraries();
    errno = saved_errno;
  } else {
    // read or write failed -- broken connection?
    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
                      strerror(errno));
  }

  close(s);
}
예제 #3
0
/*
 * Catches fatal signals so we can ask debuggerd to ptrace us before
 * we crash.
 */
void debugger_signal_handler(int n, siginfo_t* info, void*) {
    char msgbuf[128];

    /*
     * 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);

    pid_t tid = gettid();
    int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);

    if (s >= 0) {
        /* debugger knows our pid from the credentials on the
         * local socket but we need to tell it our tid.  It
         * is paranoid and will verify that we are giving a tid
         * that's actually in our process
         */
        int  ret;
        debugger_msg_t msg;
        msg.action = DEBUGGER_ACTION_CRASH;
        msg.tid = tid;
        ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
        if (ret == sizeof(msg)) {
            /* if the write failed, there is no point to read on
             * the file descriptor. */
            ret = TEMP_FAILURE_RETRY(read(s, &tid, 1));
            int saved_errno = errno;
            notify_gdb_of_libraries();
            errno = saved_errno;
        }

        if (ret < 0) {
            /* read or write failed -- broken connection? */
            format_buffer(msgbuf, sizeof(msgbuf),
                "Failed while talking to debuggerd: %s", strerror(errno));
            __libc_android_log_write(ANDROID_LOG_FATAL, "libc", msgbuf);
        }

        close(s);
    } else {
        /* socket failed; maybe process ran out of fds */
        format_buffer(msgbuf, sizeof(msgbuf),
            "Unable to open connection to debuggerd: %s", strerror(errno));
        __libc_android_log_write(ANDROID_LOG_FATAL, "libc", msgbuf);
    }

    /* remove our net so we fault for real when we return */
    signal(n, SIG_DFL);

    /*
     * These signals are not re-thrown when we resume.  This means that
     * crashing due to (say) SIGPIPE doesn't work the way you'd expect it
     * to.  We work around this by throwing them manually.  We don't want
     * to do this for *all* signals because it'll screw up the address for
     * faults like SIGSEGV.
     */
    switch (n) {
        case SIGABRT:
        case SIGFPE:
        case SIGPIPE:
#ifdef SIGSTKFLT
        case SIGSTKFLT:
#endif
            (void) tgkill(getpid(), gettid(), n);
            break;
        default:    // SIGILL, SIGBUS, SIGSEGV
            break;
    }
}
예제 #4
0
/*
 * Catches fatal signals so we can ask debuggerd to ptrace us before
 * we crash.
 */
void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
    /*
     * It's possible somebody cleared the SA_SIGINFO flag, which would mean
     * our "info" arg holds an undefined value.
     */
    if (!have_siginfo(n)) {
        info = NULL;
    }

    log_signal_summary(n, info);

    pid_t tid = gettid();
    int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);

    if (s >= 0) {
        // debuggerd knows our pid from the credentials on the
        // local socket but we need to tell it the tid of the crashing thread.
        // debuggerd will be paranoid and verify that we sent a tid
        // that's actually in our process.
        debugger_msg_t msg;
        msg.action = DEBUGGER_ACTION_CRASH;
        msg.tid = tid;
        msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
        int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
        if (ret == sizeof(msg)) {
#ifdef HAVE_AEE_FEATURE
            int tmppid = getpid();
            __libc_format_log(ANDROID_LOG_FATAL, "libc", "Send stop signal to pid:%d in %s", tmppid, __func__);
            kill(tmppid, SIGSTOP);
#endif
            // if the write failed, there is no point trying to read a response.
            ret = TEMP_FAILURE_RETRY(read(s, &tid, 1));
            int saved_errno = errno;
            notify_gdb_of_libraries();
            errno = saved_errno;
        }

        if (ret < 0) {
            /* read or write failed -- broken connection? */
            __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
                              strerror(errno));
        }

        close(s);
    } else {
        /* socket failed; maybe process ran out of fds */
        __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
                          strerror(errno));
    }

    /* remove our net so we fault for real when we return */
    signal(n, SIG_DFL);

    /*
     * These signals are not re-thrown when we resume.  This means that
     * crashing due to (say) SIGPIPE doesn't work the way you'd expect it
     * to.  We work around this by throwing them manually.  We don't want
     * to do this for *all* signals because it'll screw up the address for
     * faults like SIGSEGV.
     */
    switch (n) {
        case SIGABRT:
        case SIGFPE:
        case SIGPIPE:
#ifdef SIGSTKFLT
        case SIGSTKFLT:
#endif
            (void) tgkill(getpid(), gettid(), n);
            break;
        default:    // SIGILL, SIGBUS, SIGSEGV
            break;
    }
}