Merge "Better seccomp/kuser_helper diagnostics from debuggerd."
diff --git a/adb/client/usb_dispatch.cpp b/adb/client/usb_dispatch.cpp
index 597e66e..f02dccf 100644
--- a/adb/client/usb_dispatch.cpp
+++ b/adb/client/usb_dispatch.cpp
@@ -24,10 +24,10 @@
 
 void usb_init() {
     if (should_use_libusb()) {
-        LOG(INFO) << "using libusb backend";
+        LOG(DEBUG) << "using libusb backend";
         libusb::usb_init();
     } else {
-        LOG(INFO) << "using native backend";
+        LOG(DEBUG) << "using native backend";
         native::usb_init();
     }
 }
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index cd491d6..9469bbd 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -67,11 +67,22 @@
 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 {                                                         \
-    __libc_format_log(ANDROID_LOG_FATAL, "libc", __VA_ARGS__); \
-    _exit(1);                                                  \
-  } while (0)
+static void __noreturn __printflike(1, 2) fatal(const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  __libc_format_log_va_list(ANDROID_LOG_FATAL, "libc", fmt, args);
+  _exit(1);
+}
+
+static void __noreturn __printflike(1, 2) fatal_errno(const char* fmt, ...) {
+  int err = errno;
+  va_list args;
+  va_start(args, fmt);
+
+  char buf[4096];
+  vsnprintf(buf, sizeof(buf), fmt, args);
+  fatal("%s: %s", buf, strerror(err));
+}
 
 /*
  * Writes a summary of the signal to the log file.  We do this so that, if
@@ -192,7 +203,7 @@
 
   int pipefds[2];
   if (pipe(pipefds) != 0) {
-    fatal("failed to create pipe");
+    fatal_errno("failed to create pipe");
   }
 
   // Don't use fork(2) to avoid calling pthread_atfork handlers.
@@ -209,7 +220,7 @@
     snprintf(buf, sizeof(buf), "%d", thread_info->crashing_tid);
     execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, buf, nullptr);
 
-    fatal("exec failed: %s", strerror(errno));
+    fatal_errno("exec failed");
   } else {
     close(pipefds[1]);
     char buf[4];
@@ -264,7 +275,7 @@
   if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) {
     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));
+      fatal_errno("failed to resend signal during crash");
     }
   }
 
@@ -336,7 +347,7 @@
           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));
+    fatal_errno("failed to spawn debuggerd dispatch thread");
   }
 
   // Wait for the child to start...
@@ -366,12 +377,12 @@
   void* thread_stack_allocation =
     mmap(nullptr, PAGE_SIZE * 3, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
   if (thread_stack_allocation == MAP_FAILED) {
-    fatal("failed to allocate debuggerd thread stack");
+    fatal_errno("failed to allocate debuggerd thread stack");
   }
 
   char* stack = static_cast<char*>(thread_stack_allocation) + PAGE_SIZE;
   if (mprotect(stack, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
-    fatal("failed to mprotect debuggerd thread stack");
+    fatal_errno("failed to mprotect debuggerd thread stack");
   }
 
   // Stack grows negatively, set it to the last byte in the page...
diff --git a/init/README.md b/init/README.md
index cef0dbc..c76a33b 100644
--- a/init/README.md
+++ b/init/README.md
@@ -298,7 +298,8 @@
 > Fork and execute command with the given arguments. The command starts
   after "--" so that an optional security context, user, and supplementary
   groups can be provided. No other commands will be run until this one
-  finishes. _seclabel_ can be a - to denote default.
+  finishes. _seclabel_ can be a - to denote default. Properties are expanded
+  within _argument_.
 
 `export <name> <value>`
 > Set the environment variable _name_ equal to _value_ in the
@@ -412,6 +413,11 @@
   or the timeout has been reached. If timeout is not specified it
   currently defaults to five seconds.
 
+`wait_for_prop <name> <value>`
+> Wait for system property _name_ to be _value_. Properties are expanded
+  within _value_. If property _name_ is already set to _value_, continue
+  immediately.
+
 `write <path> <content>`
 > Open the file at _path_ and write a string to it with write(2).
   If the file does not exist, it will be created. If it does exist,
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 1186e9d..965a81f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1003,6 +1003,29 @@
     return -1;
 }
 
+static int do_wait_for_prop(const std::vector<std::string>& args) {
+    const char* name = args[1].c_str();
+    const char* value = args[2].c_str();
+    size_t value_len = strlen(value);
+
+    if (!is_legal_property_name(name)) {
+        LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
+                   << "\") failed: bad name";
+        return -1;
+    }
+    if (value_len >= PROP_VALUE_MAX) {
+        LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
+                   << "\") failed: value too long";
+        return -1;
+    }
+    if (!wait_property(name, value)) {
+        LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
+                   << "\") failed: init already in waiting";
+        return -1;
+    }
+    return 0;
+}
+
 /*
  * Callback to make a directory from the ext4 code
  */
@@ -1074,6 +1097,7 @@
         {"verity_load_state",       {0,     0,    do_verity_load_state}},
         {"verity_update_state",     {0,     0,    do_verity_update_state}},
         {"wait",                    {1,     2,    do_wait}},
+        {"wait_for_prop",           {2,     2,    do_wait_for_prop}},
         {"write",                   {2,     2,    do_write}},
     };
     return builtin_functions;
diff --git a/init/init.cpp b/init/init.cpp
index 850a904..9322eb2 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -87,6 +87,10 @@
 
 static int epoll_fd = -1;
 
+static std::unique_ptr<Timer> waiting_for_prop(nullptr);
+static std::string wait_prop_name;
+static std::string wait_prop_value;
+
 void register_epoll_handler(int fd, void (*fn)()) {
     epoll_event ev;
     ev.events = EPOLLIN;
@@ -128,10 +132,34 @@
     return -1;
 }
 
+bool wait_property(const char *name, const char *value)
+{
+    if (waiting_for_prop) {
+        return false;
+    }
+    if (property_get(name) != value) {
+        // Current property value is not equal to expected value
+        wait_prop_name = name;
+        wait_prop_value = value;
+        waiting_for_prop.reset(new Timer());
+    } else {
+        LOG(INFO) << "wait_property(\"" << name << "\", \"" << value << "\"): already set";
+    }
+    return true;
+}
+
 void property_changed(const char *name, const char *value)
 {
     if (property_triggers_enabled)
         ActionManager::GetInstance().QueuePropertyTrigger(name, value);
+    if (waiting_for_prop) {
+        if (wait_prop_name == name && wait_prop_value == value) {
+            wait_prop_name.clear();
+            wait_prop_value.clear();
+            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
+            waiting_for_prop.reset();
+        }
+    }
 }
 
 static void restart_processes()
@@ -876,7 +904,7 @@
     am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
 
     while (true) {
-        if (!waiting_for_exec) {
+        if (!(waiting_for_exec || waiting_for_prop)) {
             am.ExecuteOneCommand();
             restart_processes();
         }
diff --git a/init/init.h b/init/init.h
index cfb3139..4e4da32 100644
--- a/init/init.h
+++ b/init/init.h
@@ -36,4 +36,6 @@
 
 int add_environment(const char* key, const char* val);
 
+bool wait_property(const char *name, const char *value);
+
 #endif  /* _INIT_INIT_H */
diff --git a/init/seccomp.cpp b/init/seccomp.cpp
index b0688f3..608c4e7 100644
--- a/init/seccomp.cpp
+++ b/init/seccomp.cpp
@@ -234,6 +234,11 @@
     // b/34817266
     AllowSyscall(f, 252); // __NR_epoll_wait
 
+    // Needed by sanitizers (b/34606909)
+    // 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
+    // already allowed.
+    AllowSyscall(f, 85);  // __NR_readlink
+
     // 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]);