Merge "Revert "New protocol for property_service""
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 831150b..e4f88b0 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -36,7 +36,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
-#include <log/logger.h>
+#include <log/log.h>
 #include <procinfo/process.h>
 #include <selinux/selinux.h>
 
@@ -57,8 +57,8 @@
 }
 
 // Attach to a thread, and verify that it's still a member of the given process
-static bool ptrace_attach_thread(pid_t pid, pid_t tid, std::string* error) {
-  if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
+static bool ptrace_seize_thread(pid_t pid, pid_t tid, std::string* error) {
+  if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) {
     *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
     return false;
   }
@@ -71,6 +71,12 @@
     *error = StringPrintf("thread %d is not in process %d", tid, pid);
     return false;
   }
+
+  // Put the task into ptrace-stop state.
+  if (ptrace(PTRACE_INTERRUPT, tid, 0, 0) != 0) {
+    PLOG(FATAL) << "failed to interrupt thread " << tid;
+  }
+
   return true;
 }
 
@@ -160,11 +166,15 @@
   return true;
 }
 
+static void signal_handler(int) {
+  // We can't log easily, because the heap might be corrupt.
+  // Just die and let the surrounding log context explain things.
+  _exit(1);
+}
+
 static void abort_handler(pid_t target, const bool& tombstoned_connected,
                           unique_fd& tombstoned_socket, unique_fd& output_fd,
                           const char* abort_msg) {
-  LOG(ERROR) << abort_msg;
-
   // If we abort before we get an output fd, contact tombstoned to let any
   // potential listeners know that we failed.
   if (!tombstoned_connected) {
@@ -177,7 +187,6 @@
 
   dprintf(output_fd.get(), "crash_dump failed to dump process %d: %s\n", target, abort_msg);
 
-  // Don't dump ourselves.
   _exit(1);
 }
 
@@ -203,6 +212,11 @@
     abort_handler(target, tombstoned_connected, tombstoned_socket, output_fd, abort_msg);
   });
 
+  // Don't try to dump ourselves.
+  struct sigaction action = {};
+  action.sa_handler = signal_handler;
+  debuggerd_register_handlers(&action);
+
   if (argc != 2) {
     return 1;
   }
@@ -243,10 +257,13 @@
     exit(0);
   }
 
+  // Die if we take too long.
+  alarm(20);
+
   check_process(target_proc_fd, target);
 
   std::string attach_error;
-  if (!ptrace_attach_thread(target, main_tid, &attach_error)) {
+  if (!ptrace_seize_thread(target, main_tid, &attach_error)) {
     LOG(FATAL) << attach_error;
   }
 
@@ -271,9 +288,9 @@
 
   LOG(INFO) << "performing dump of process " << target << " (target tid = " << main_tid << ")";
 
-  // At this point, the thread that made the request has been PTRACE_ATTACHed
-  // and has the signal that triggered things queued. Send PTRACE_CONT, and
-  // then wait for the signal.
+  // At this point, the thread that made the request has been attached and is
+  // in ptrace-stopped state. After resumption, the triggering signal that has
+  // been queued will be delivered.
   if (ptrace(PTRACE_CONT, main_tid, 0, 0) != 0) {
     PLOG(ERROR) << "PTRACE_CONT(" << main_tid << ") failed";
     exit(1);
@@ -302,17 +319,16 @@
   // Now that we have the signal that kicked things off, attach all of the
   // sibling threads, and then proceed.
   bool fatal_signal = signo != DEBUGGER_SIGNAL;
-  int resume_signal = fatal_signal ? signo : 0;
   std::set<pid_t> siblings;
   std::set<pid_t> attached_siblings;
-  if (resume_signal == 0) {
+  if (fatal_signal) {
     if (!android::procinfo::GetProcessTids(target, &siblings)) {
       PLOG(FATAL) << "failed to get process siblings";
     }
     siblings.erase(main_tid);
 
     for (pid_t sibling_tid : siblings) {
-      if (!ptrace_attach_thread(target, sibling_tid, &attach_error)) {
+      if (!ptrace_seize_thread(target, sibling_tid, &attach_error)) {
         LOG(WARNING) << attach_error;
       } else {
         attached_siblings.insert(sibling_tid);
@@ -338,40 +354,39 @@
                       attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr);
   }
 
+  // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in
+  // group-stop state, which is true as long as no stopping signals are sent.
+
   bool wait_for_gdb = android::base::GetBoolProperty("debug.debuggerd.wait_for_gdb", false);
-  if (wait_for_gdb) {
+  if (!fatal_signal || siginfo.si_code == SI_USER) {
     // Don't wait_for_gdb when the process didn't actually crash.
-    if (!fatal_signal) {
-      wait_for_gdb = false;
-    } else {
-      // Use ALOGI to line up with output from engrave_tombstone.
-      ALOGI(
-        "***********************************************************\n"
-        "* Process %d has been suspended while crashing.\n"
-        "* To attach gdbserver and start gdb, run this on the host:\n"
-        "*\n"
-        "*     gdbclient.py -p %d\n"
-        "*\n"
-        "***********************************************************",
-        target, main_tid);
-    }
+    wait_for_gdb = false;
   }
 
-  for (pid_t tid : attached_siblings) {
-    // Don't send the signal to sibling threads.
-    if (ptrace(PTRACE_DETACH, tid, 0, wait_for_gdb ? SIGSTOP : 0) != 0) {
-      PLOG(ERROR) << "ptrace detach from " << tid << " failed";
+  // If the process crashed or we need to send it SIGSTOP for wait_for_gdb,
+  // get it in a state where it can receive signals, and then send the relevant
+  // signal.
+  if (wait_for_gdb || fatal_signal) {
+    if (ptrace(PTRACE_INTERRUPT, main_tid, 0, 0) != 0) {
+      PLOG(ERROR) << "failed to use PTRACE_INTERRUPT on " << main_tid;
     }
-  }
 
-  if (ptrace(PTRACE_DETACH, main_tid, 0, wait_for_gdb ? SIGSTOP : resume_signal)) {
-    PLOG(ERROR) << "ptrace detach from main thread " << main_tid << " failed";
+    if (tgkill(target, main_tid, wait_for_gdb ? SIGSTOP : signo) != 0) {
+      PLOG(ERROR) << "failed to resend signal " << signo << " to " << main_tid;
+    }
   }
 
   if (wait_for_gdb) {
-    if (tgkill(target, main_tid, resume_signal) != 0) {
-      PLOG(ERROR) << "failed to resend signal to process " << target;
-    }
+    // Use ALOGI to line up with output from engrave_tombstone.
+    ALOGI(
+      "***********************************************************\n"
+      "* Process %d has been suspended while crashing.\n"
+      "* To attach gdbserver and start gdb, run this on the host:\n"
+      "*\n"
+      "*     gdbclient.py -p %d\n"
+      "*\n"
+      "***********************************************************",
+      target, main_tid);
   }
 
   if (fatal_signal) {
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f51b5f2..e7503e9 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -17,6 +17,7 @@
 #include <err.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 
 #include <chrono>
@@ -90,6 +91,7 @@
   // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
   void FinishIntercept(int* result);
 
+  void StartProcess(std::function<void()> function);
   void StartCrasher(const std::string& crash_type);
   void FinishCrasher();
   void AssertDeath(int signo);
@@ -166,9 +168,8 @@
   }
 }
 
-void CrasherTest::StartCrasher(const std::string& crash_type) {
-  std::string type = "wait-" + crash_type;
-
+void CrasherTest::StartProcess(std::function<void()> function) {
+  unique_fd read_pipe;
   unique_fd crasher_read_pipe;
   if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
     FAIL() << "failed to create pipe: " << strerror(errno);
@@ -182,9 +183,17 @@
     dup2(crasher_read_pipe.get(), STDIN_FILENO);
     dup2(devnull.get(), STDOUT_FILENO);
     dup2(devnull.get(), STDERR_FILENO);
+    function();
+    _exit(0);
+  }
+}
+
+void CrasherTest::StartCrasher(const std::string& crash_type) {
+  std::string type = "wait-" + crash_type;
+  StartProcess([type]() {
     execl(CRASHER_PATH, CRASHER_PATH, type.c_str(), nullptr);
     err(1, "exec failed");
-  }
+  });
 }
 
 void CrasherTest::FinishCrasher() {
@@ -340,24 +349,15 @@
   AssertDeath(SIGABRT);
 }
 
+// wait_for_gdb shouldn't trigger on manually sent signals.
 TEST_F(CrasherTest, wait_for_gdb_signal) {
   if (!android::base::SetProperty(kWaitForGdbKey, "1")) {
     FAIL() << "failed to enable wait_for_gdb";
   }
 
   StartCrasher("abort");
-  ASSERT_EQ(0, kill(crasher_pid, SIGABRT)) << strerror(errno);
-
-  std::this_thread::sleep_for(500ms);
-
-  int status;
-  ASSERT_EQ(crasher_pid, (TIMEOUT(1, waitpid(crasher_pid, &status, WUNTRACED))));
-  ASSERT_TRUE(WIFSTOPPED(status));
-  ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
-
-  ASSERT_EQ(0, kill(crasher_pid, SIGCONT)) << strerror(errno);
-
-  AssertDeath(SIGABRT);
+  ASSERT_EQ(0, kill(crasher_pid, SIGSEGV)) << strerror(errno);
+  AssertDeath(SIGSEGV);
 }
 
 TEST_F(CrasherTest, backtrace) {
@@ -388,3 +388,20 @@
   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_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
+  StartProcess([]() {
+    prctl(PR_SET_DUMPABLE, 0);
+    volatile char* null = static_cast<char*>(nullptr);
+    *null = '\0';
+  });
+  AssertDeath(SIGSEGV);
+}
+
+TEST_F(CrasherTest, PR_SET_DUMPABLE_0_raise) {
+  StartProcess([]() {
+    prctl(PR_SET_DUMPABLE, 0);
+    raise(SIGUSR1);
+  });
+  AssertDeath(SIGUSR1);
+}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 6033a6b..8ea06c0 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <linux/futex.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
@@ -46,6 +47,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include "private/bionic_futex.h"
 #include "private/libc_logging.h"
 
 // see man(2) prctl, specifically the section about PR_GET_NAME
@@ -61,6 +63,9 @@
 
 static debuggerd_callbacks_t g_callbacks;
 
+// Mutex to ensure only one crashing thread dumps itself.
+static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 // Don't use __libc_fatal because it exits via abort, which might put us back into a signal handler.
 #define fatal(...)                                             \
   do {                                                         \
@@ -151,8 +156,7 @@
 }
 
 struct debugger_thread_info {
-  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-  bool crash_dump_started = false;
+  bool crash_dump_started;
   pid_t crashing_tid;
   pid_t pseudothread_tid;
   int signal_number;
@@ -228,16 +232,41 @@
     }
   }
 
-  pthread_mutex_unlock(&thread_info->mutex);
+  syscall(__NR_exit, 0);
   return 0;
 }
 
+static void resend_signal(siginfo_t* info) {
+  // Signals can either be fatal or nonfatal.
+  // For fatal signals, crash_dump will send us the signal we crashed with
+  // before resuming us, so that processes using waitpid on us will see that we
+  // exited with the correct exit status (e.g. so that sh will report
+  // "Segmentation fault" instead of "Killed"). For this to work, we need
+  // to deregister our signal handler for that signal before continuing.
+  if (info->si_signo != DEBUGGER_SIGNAL) {
+    signal(info->si_signo, SIG_DFL);
+  }
+
+  // We need to return from our signal handler so that crash_dump can see the
+  // signal via ptrace and dump the thread that crashed. However, returning
+  // does not guarantee that the signal will be thrown again, even for SIGSEGV
+  // and friends, since the signal could have been sent manually. We blocked
+  // all signals when registering the handler, so resending the signal (using
+  // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered
+  // when our signal handler returns.
+  int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), info->si_signo, info);
+  if (rc != 0) {
+    fatal("failed to resend signal during crash: %s", strerror(errno));
+  }
+
+  if (info->si_signo == DEBUGGER_SIGNAL) {
+    pthread_mutex_unlock(&crash_mutex);
+  }
+}
+
 // Handler that does crash dumping by forking and doing the processing in the child.
 // Do this by ptracing the relevant thread, and then execing debuggerd to do the actual dump.
 static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
-  // Mutex to prevent multiple crashing threads from trying to talk
-  // to debuggerd at the same time.
-  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
   int ret = pthread_mutex_lock(&crash_mutex);
   if (ret != 0) {
     __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
@@ -250,59 +279,10 @@
     info = nullptr;
   }
 
-  log_signal_summary(signal_number, 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");
-
-    pthread_mutex_unlock(&crash_mutex);
-    return;
-  }
-
-  void* abort_message = nullptr;
-  if (g_callbacks.get_abort_message) {
-    abort_message = g_callbacks.get_abort_message();
-  }
-
-  debugger_thread_info thread_info = {
-    .crashing_tid = gettid(),
-    .signal_number = signal_number,
-    .info = info
-  };
-  pthread_mutex_lock(&thread_info.mutex);
-
-  // Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
-  pid_t child_pid = clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
-                          CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID,
-                          &thread_info, nullptr, nullptr, &thread_info.pseudothread_tid);
-  if (child_pid == -1) {
-    fatal("failed to spawn debuggerd dispatch thread: %s", strerror(errno));
-  }
-
-  // Wait for the child to finish and unlock the mutex.
-  // This relies on bionic behavior that isn't guaranteed by the standard.
-  pthread_mutex_lock(&thread_info.mutex);
-
-  // Signals can either be fatal or nonfatal.
-  // For fatal signals, crash_dump will PTRACE_CONT us with the signal we
-  // crashed with, so that processes using waitpid on us will see that we
-  // exited with the correct exit status (e.g. so that sh will report
-  // "Segmentation fault" instead of "Killed"). For this to work, we need
-  // to deregister our signal handler for that signal before continuing.
-  if (signal_number != DEBUGGER_SIGNAL) {
-    signal(signal_number, SIG_DFL);
-  }
-
-  // We need to return from the signal handler so that debuggerd can dump the
-  // thread that crashed, but returning here does not guarantee that the signal
-  // will be thrown again, even for SIGSEGV and friends, since the signal could
-  // have been sent manually. Resend the signal with rt_tgsigqueueinfo(2) to
-  // preserve the SA_SIGINFO contents.
-  struct siginfo si;
+  struct siginfo si = {};
   if (!info) {
     memset(&si, 0, sizeof(si));
+    si.si_signo = signal_number;
     si.si_code = SI_USER;
     si.si_pid = getpid();
     si.si_uid = getuid();
@@ -314,23 +294,59 @@
     // check to allow all si_code values in calls coming from inside the house.
   }
 
+  log_signal_summary(signal_number, info);
+  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+    // The process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
+    __libc_format_log(ANDROID_LOG_INFO, "libc",
+                      "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
+
+    resend_signal(info);
+    return;
+  }
+
+  void* abort_message = nullptr;
+  if (g_callbacks.get_abort_message) {
+    abort_message = g_callbacks.get_abort_message();
+  }
   // Populate si_value with the abort message address, if found.
   if (abort_message) {
     info->si_value.sival_ptr = abort_message;
   }
 
-  // Only resend the signal if we know that either crash_dump has ptraced us or
-  // the signal was fatal.
-  if (thread_info.crash_dump_started || signal_number != DEBUGGER_SIGNAL) {
-    int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), signal_number, info);
-    if (rc != 0) {
-      fatal("failed to resend signal during crash: %s", strerror(errno));
-    }
+  debugger_thread_info thread_info = {
+    .crash_dump_started = false,
+    .pseudothread_tid = -1,
+    .crashing_tid = gettid(),
+    .signal_number = signal_number,
+    .info = info
+  };
+
+  // Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
+  pid_t child_pid =
+    clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
+          CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID,
+          &thread_info, nullptr, nullptr, &thread_info.pseudothread_tid);
+  if (child_pid == -1) {
+    fatal("failed to spawn debuggerd dispatch thread: %s", strerror(errno));
   }
 
-  if (signal_number == DEBUGGER_SIGNAL) {
-    pthread_mutex_unlock(&crash_mutex);
+  // Wait for the child to start...
+  __futex_wait(&thread_info.pseudothread_tid, -1, nullptr);
+
+  // and then wait for it to finish.
+  __futex_wait(&thread_info.pseudothread_tid, child_pid, nullptr);
+
+  // Signals can either be fatal or nonfatal.
+  // For fatal signals, crash_dump will PTRACE_CONT us with the signal we
+  // crashed with, so that processes using waitpid on us will see that we
+  // exited with the correct exit status (e.g. so that sh will report
+  // "Segmentation fault" instead of "Killed"). For this to work, we need
+  // to deregister our signal handler for that signal before continuing.
+  if (signal_number != DEBUGGER_SIGNAL) {
+    signal(signal_number, SIG_DFL);
   }
+
+  resend_signal(info);
 }
 
 void debuggerd_init(debuggerd_callbacks_t* callbacks) {
@@ -363,15 +379,5 @@
 
   // Use the alternate signal stack if available so we can catch stack overflows.
   action.sa_flags |= SA_ONSTACK;
-
-  sigaction(SIGABRT, &action, nullptr);
-  sigaction(SIGBUS, &action, nullptr);
-  sigaction(SIGFPE, &action, nullptr);
-  sigaction(SIGILL, &action, nullptr);
-  sigaction(SIGSEGV, &action, nullptr);
-#if defined(SIGSTKFLT)
-  sigaction(SIGSTKFLT, &action, nullptr);
-#endif
-  sigaction(SIGTRAP, &action, nullptr);
-  sigaction(DEBUGGER_SIGNAL, &action, nullptr);
+  debuggerd_register_handlers(&action);
 }
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 302f4c2..7196e0a 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -39,4 +39,18 @@
 // to the log.
 #define DEBUGGER_SIGNAL (__SIGRTMIN + 3)
 
+static void __attribute__((__unused__)) debuggerd_register_handlers(struct sigaction* action) {
+  sigaction(SIGABRT, action, nullptr);
+  sigaction(SIGBUS, action, nullptr);
+  sigaction(SIGFPE, action, nullptr);
+  sigaction(SIGILL, action, nullptr);
+  sigaction(SIGSEGV, action, nullptr);
+#if defined(SIGSTKFLT)
+  sigaction(SIGSTKFLT, action, nullptr);
+#endif
+  sigaction(SIGSYS, action, nullptr);
+  sigaction(SIGTRAP, action, nullptr);
+  sigaction(DEBUGGER_SIGNAL, action, nullptr);
+}
+
 __END_DECLS
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 63e3dbd..8705ece 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -85,7 +85,13 @@
     std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
     struct stat st;
     if (stat(path.c_str(), &st) != 0) {
-      PLOG(ERROR) << "failed to stat " << path;
+      if (errno == ENOENT) {
+        oldest_tombstone = i;
+        break;
+      } else {
+        PLOG(ERROR) << "failed to stat " << path;
+        continue;
+      }
     }
 
     if (st.st_mtime < oldest_time) {
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index eaae9c4..b8345ca 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -2,6 +2,9 @@
     user tombstoned
     group system
 
+    # Don't start tombstoned until after the real /data is mounted.
+    class late_start
+
     socket tombstoned_crash seqpacket 0666 system system
     socket tombstoned_intercept seqpacket 0666 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/init/init.cpp b/init/init.cpp
index ddc707f..1ce3c35 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -835,7 +835,12 @@
     parser.AddSectionParser("service",std::make_unique<ServiceParser>());
     parser.AddSectionParser("on", std::make_unique<ActionParser>());
     parser.AddSectionParser("import", std::make_unique<ImportParser>());
-    parser.ParseConfig("/init.rc");
+    std::string bootscript = property_get("ro.boot.init_rc");
+    if (bootscript.empty()) {
+        parser.ParseConfig("/init.rc");
+    } else {
+        parser.ParseConfig(bootscript);
+    }
 
     ActionManager& am = ActionManager::GetInstance();
 
diff --git a/init/seccomp.cpp b/init/seccomp.cpp
index d9f2f79..d632302 100644
--- a/init/seccomp.cpp
+++ b/init/seccomp.cpp
@@ -170,6 +170,12 @@
     // Needed for trusty
     AllowSyscall(f, __NR_syncfs);
 
+    // Needed for strace
+    AllowSyscall(f, __NR_tkill);  // __NR_tkill
+
+    // Needed for kernel to restart syscalls
+    AllowSyscall(f, __NR_restart_syscall);
+
      // arm64-only filter - autogenerated from bionic syscall usage
     for (size_t i = 0; i < arm64_filter_size; ++i)
         f.push_back(arm64_filter[i]);
@@ -201,6 +207,12 @@
     // Syscalls needed to run GFXBenchmark
     AllowSyscall(f, 190); // __NR_vfork
 
+    // Needed for strace
+    AllowSyscall(f, 238);  // __NR_tkill
+
+    // Needed for kernel to restart syscalls
+    AllowSyscall(f, 0);  // __NR_restart_syscall
+
     // arm32-on-arm64 only filter - autogenerated from bionic syscall usage
     for (size_t i = 0; i < arm_filter_size; ++i)
         f.push_back(arm_filter[i]);
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 8a390f6..337861e 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -23,6 +23,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <memory>
 #include <string>
@@ -54,6 +55,11 @@
 TEST(logcat, buckets) {
     FILE *fp;
 
+#undef LOG_TAG
+#define LOG_TAG "inject"
+    RLOGE("logcat.buckets");
+    sleep(1);
+
     ASSERT_TRUE(NULL != (fp = popen(
       "logcat -b radio -b events -b system -b main -d 2>/dev/null",
       "r")));
@@ -165,13 +171,39 @@
         if (!ep) {
             continue;
         }
-        ep -= 7;
+        static const size_t tag_field_width = 7;
+        ep -= tag_field_width;
         *ep = '\0';
         return cp;
     }
     return NULL;
 }
 
+// If there is not enough background noise in the logs, then spam the logs to
+// permit tail checking so that the tests can progress.
+static size_t inject(ssize_t count) {
+    if (count <= 0) return 0;
+
+    static const size_t retry = 3;
+    size_t errors = retry;
+    size_t num = 0;
+    for(;;) {
+        log_time ts(CLOCK_MONOTONIC);
+        if (__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) >= 0) {
+            if (++num >= (size_t)count) {
+                sleep(1); // let data settle end-to-end
+                return num;
+            }
+            errors = retry;
+            usleep(50);
+        } else if (--errors <= 0) {
+            return num;
+        }
+    }
+    // NOTREACH
+    return num;
+}
+
 TEST(logcat, tz) {
 
     if (android_log_clockid() == CLOCK_MONOTONIC) {
@@ -201,7 +233,7 @@
 
         pclose(fp);
 
-    } while ((count < 3) && --tries && (sleep(1), true));
+    } while ((count < 3) && --tries && inject(3 - count));
 
     ASSERT_EQ(3, count);
 }
@@ -236,8 +268,7 @@
         char buffer[BIG_BUFFER];
 
         snprintf(buffer, sizeof(buffer),
-          "logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null",
-          num);
+                 "logcat -v long -b all -t %d 2>/dev/null", num);
 
         FILE *fp;
         ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
@@ -250,7 +281,7 @@
 
         pclose(fp);
 
-    } while ((count < num) && --tries && (sleep(1), true));
+    } while ((count < num) && --tries && inject(num - count));
 
     ASSERT_EQ(num, count);
 }
@@ -273,26 +304,34 @@
 
 TEST(logcat, tail_time) {
     FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
-
+    int count;
     char buffer[BIG_BUFFER];
     char *last_timestamp = NULL;
     char *first_timestamp = NULL;
-    int count = 0;
-
     char *cp;
-    while ((cp = fgetLongTime(buffer, sizeof(buffer), fp))) {
-        ++count;
-        if (!first_timestamp) {
-            first_timestamp = strdup(cp);
-        }
-        free(last_timestamp);
-        last_timestamp = strdup(cp);
-    }
-    pclose(fp);
 
-    EXPECT_EQ(10, count);
+    int tries = 3; // in case run too soon after system start or buffer clear
+
+    // Do not be tempted to use -v usec because that increases the
+    // chances of an occasional test failure by 1000 (see below).
+    do {
+        ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
+
+        count = 0;
+
+        while ((cp = fgetLongTime(buffer, sizeof(buffer), fp))) {
+            ++count;
+            if (!first_timestamp) {
+                first_timestamp = strdup(cp);
+            }
+            free(last_timestamp);
+            last_timestamp = strdup(cp);
+        }
+        pclose(fp);
+
+    } while ((count < 10) && --tries && inject(10 - count));
+
+    EXPECT_EQ(10, count); // We want _some_ history, too small, falses below
     EXPECT_TRUE(last_timestamp != NULL);
     EXPECT_TRUE(first_timestamp != NULL);
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8d974fa..d6ae6f0 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -359,9 +359,6 @@
     start vold
     installkey /data
 
-    # start tombstoned to record early-boot crashes.
-    start tombstoned
-
     # Start bootcharting as soon as possible after the data partition is
     # mounted to collect more data.
     mkdir /data/bootchart 0755 shell shell