Merge "Make __android_log_assert behave more like libc asserts."
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 58eaed7..ed6d3b7 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -18,10 +18,12 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <stdlib.h>
-#include <syscall.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
 #include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <syscall.h>
 #include <unistd.h>
 
 #include <limits>
@@ -51,24 +53,25 @@
 using android::base::unique_fd;
 using android::base::StringPrintf;
 
-static bool pid_contains_tid(pid_t pid, pid_t tid) {
-  std::string task_path = StringPrintf("/proc/%d/task/%d", pid, tid);
-  return access(task_path.c_str(), F_OK) == 0;
+static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
+  struct stat st;
+  std::string task_path = StringPrintf("task/%d", tid);
+  return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0;
 }
 
 // Attach to a thread, and verify that it's still a member of the given process
-static bool ptrace_seize_thread(pid_t pid, pid_t tid, std::string* error) {
+static bool ptrace_seize_thread(int pid_proc_fd, 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;
   }
 
   // Make sure that the task we attached to is actually part of the pid we're dumping.
-  if (!pid_contains_tid(pid, tid)) {
+  if (!pid_contains_tid(pid_proc_fd, tid)) {
     if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
       PLOG(FATAL) << "failed to detach from thread " << tid;
     }
-    *error = StringPrintf("thread %d is not in process %d", tid, pid);
+    *error = StringPrintf("thread %d is not in process", tid);
     return false;
   }
 
@@ -190,6 +193,24 @@
   _exit(1);
 }
 
+static void drop_capabilities() {
+  __user_cap_header_struct capheader;
+  memset(&capheader, 0, sizeof(capheader));
+  capheader.version = _LINUX_CAPABILITY_VERSION_3;
+  capheader.pid = 0;
+
+  __user_cap_data_struct capdata[2];
+  memset(&capdata, 0, sizeof(capdata));
+
+  if (capset(&capheader, &capdata[0]) == -1) {
+    PLOG(FATAL) << "failed to drop capabilities";
+  }
+
+  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
+    PLOG(FATAL) << "failed to set PR_SET_NO_NEW_PRIVS";
+  }
+}
+
 static void check_process(int proc_fd, pid_t expected_pid) {
   android::procinfo::ProcessInfo proc_info;
   if (!android::procinfo::GetProcessInfoFromProcPidFd(proc_fd, &proc_info)) {
@@ -263,7 +284,7 @@
   check_process(target_proc_fd, target);
 
   std::string attach_error;
-  if (!ptrace_seize_thread(target, main_tid, &attach_error)) {
+  if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) {
     LOG(FATAL) << attach_error;
   }
 
@@ -304,6 +325,7 @@
   }
 
   int signo = siginfo.si_signo;
+  bool fatal_signal = signo != DEBUGGER_SIGNAL;
   bool backtrace = false;
   uintptr_t abort_address = 0;
 
@@ -319,17 +341,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;
-  std::set<pid_t> siblings;
   std::set<pid_t> attached_siblings;
-  if (fatal_signal || backtrace) {
+  {
+    std::set<pid_t> siblings;
     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_seize_thread(target, sibling_tid, &attach_error)) {
+      if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
         LOG(WARNING) << attach_error;
       } else {
         attached_siblings.insert(sibling_tid);
@@ -337,6 +358,9 @@
     }
   }
 
+  // Drop our capabilities now that we've attached to the threads we care about.
+  drop_capabilities();
+
   check_process(target_proc_fd, target);
 
   // TODO: Use seccomp to lock ourselves down.
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 9469bbd..38a7be3 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -39,6 +39,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/capability.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
@@ -207,7 +208,7 @@
   }
 
   // Don't use fork(2) to avoid calling pthread_atfork handlers.
-  int forkpid = clone(nullptr, nullptr, SIGCHLD, nullptr);
+  int forkpid = clone(nullptr, nullptr, 0, nullptr);
   if (forkpid == -1) {
     __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to fork in debuggerd signal handler: %s",
                       strerror(errno));
@@ -216,6 +217,11 @@
     close(pipefds[0]);
     close(pipefds[1]);
 
+    // Set all of the ambient capability bits we can, so that crash_dump can ptrace us.
+    for (unsigned long i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) != -1; ++i) {
+      prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0);
+    }
+
     char buf[10];
     snprintf(buf, sizeof(buf), "%d", thread_info->crashing_tid);
     execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, buf, nullptr);
@@ -242,10 +248,12 @@
     close(pipefds[0]);
 
     // Don't leave a zombie child.
-    siginfo_t child_siginfo;
-    if (TEMP_FAILURE_RETRY(waitid(P_PID, forkpid, &child_siginfo, WEXITED)) != 0) {
+    int status;
+    if (TEMP_FAILURE_RETRY(waitpid(forkpid, &status, __WCLONE)) == -1 && errno != ECHILD) {
       __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to wait for crash_dump helper: %s",
                         strerror(errno));
+    } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) {
+      __libc_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper crashed or stopped");
       thread_info->crash_dump_started = false;
     }
   }
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 965a81f..2388edc 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -265,10 +265,14 @@
     if (!svc) {
         return -1;
     }
-    if (!svc->Start()) {
+    if (!start_waiting_for_exec()) {
         return -1;
     }
-    waiting_for_exec = true;
+    if (!svc->Start()) {
+        stop_waiting_for_exec();
+        ServiceManager::GetInstance().RemoveService(*svc);
+        return -1;
+    }
     return 0;
 }
 
@@ -1018,7 +1022,7 @@
                    << "\") failed: value too long";
         return -1;
     }
-    if (!wait_property(name, value)) {
+    if (!start_waiting_for_property(name, value)) {
         LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
                    << "\") failed: init already in waiting";
         return -1;
diff --git a/init/init.cpp b/init/init.cpp
index c8c18d2..43f601f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -82,7 +82,7 @@
 
 const char *ENV[32];
 
-bool waiting_for_exec = false;
+static std::unique_ptr<Timer> waiting_for_exec(nullptr);
 
 static int epoll_fd = -1;
 
@@ -131,7 +131,24 @@
     return -1;
 }
 
-bool wait_property(const char *name, const char *value)
+bool start_waiting_for_exec()
+{
+    if (waiting_for_exec) {
+        return false;
+    }
+    waiting_for_exec.reset(new Timer());
+    return true;
+}
+
+void stop_waiting_for_exec()
+{
+    if (waiting_for_exec) {
+        LOG(INFO) << "Wait for exec took " << *waiting_for_exec;
+        waiting_for_exec.reset();
+    }
+}
+
+bool start_waiting_for_property(const char *name, const char *value)
 {
     if (waiting_for_prop) {
         return false;
@@ -142,7 +159,8 @@
         wait_prop_value = value;
         waiting_for_prop.reset(new Timer());
     } else {
-        LOG(INFO) << "wait_property(\"" << name << "\", \"" << value << "\"): already set";
+        LOG(INFO) << "start_waiting_for_property(\""
+                  << name << "\", \"" << value << "\"): already set";
     }
     return true;
 }
diff --git a/init/init.h b/init/init.h
index 4e4da32..3768c02 100644
--- a/init/init.h
+++ b/init/init.h
@@ -23,7 +23,6 @@
 class Service;
 
 extern const char *ENV[32];
-extern bool waiting_for_exec;
 extern std::string default_console;
 extern struct selabel_handle *sehandle;
 extern struct selabel_handle *sehandle_prop;
@@ -36,6 +35,10 @@
 
 int add_environment(const char* key, const char* val);
 
-bool wait_property(const char *name, const char *value);
+bool start_waiting_for_exec();
+
+void stop_waiting_for_exec();
+
+bool start_waiting_for_property(const char *name, const char *value);
 
 #endif  /* _INIT_INIT_H */
diff --git a/init/service.cpp b/init/service.cpp
index 0f7f62f..e186f27 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -997,7 +997,7 @@
     }
 
     if (svc->Reap()) {
-        waiting_for_exec = false;
+        stop_waiting_for_exec();
         RemoveService(*svc);
     }
 
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 013999a..b701bba 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -177,11 +177,8 @@
                                            CAP_MASK_LONG(CAP_SETPCAP),
                                               "system/bin/webview_zygote64" },
 
-    { 00755, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SYS_PTRACE),
-                                              "system/bin/crash_dump32" },
-    { 00755, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SYS_PTRACE),
-                                              "system/bin/crash_dump64" },
-
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/debuggerd" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index d7b5cb5..2f23c2c 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -246,7 +246,9 @@
     // For now we rely on CTS test to catch things like this but
     // it should probably be addressed in the future.
     for (const auto& soname : sonames) {
-      dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE);
+      LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
+                          "Error preloading public library %s: %s",
+                          soname.c_str(), dlerror());
     }
 
     public_libraries_ = base::Join(sonames, ':');