Merge "Fix vold vulnerability in FrameworkListener"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 725aa91..45d26f8 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -354,21 +354,13 @@
     case A_AUTH:
         if (p->msg.arg0 == ADB_AUTH_TOKEN) {
             t->connection_state = kCsUnauthorized;
-            t->key = adb_auth_nextkey(t->key);
-            if (t->key) {
-                send_auth_response(p->data, p->msg.data_length, t);
-            } else {
-                /* No more private keys to try, send the public key */
-                send_auth_publickey(t);
-            }
+            send_auth_response(p->data, p->msg.data_length, t);
         } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
-            if (adb_auth_verify(t->token, sizeof(t->token),
-                                p->data, p->msg.data_length)) {
+            if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
                 adb_auth_verified(t);
                 t->failed_auth_attempts = 0;
             } else {
-                if (t->failed_auth_attempts++ > 10)
-                    adb_sleep_ms(1000);
+                if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000);
                 send_auth_request(t);
             }
         } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 215bbe6..446c3df 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -16,8 +16,9 @@
 
 #define TRACE_TAG ADB
 
-#include "sysdeps.h"
+#include "adb.h"
 #include "adb_auth.h"
+#include "transport.h"
 
 #include <errno.h>
 #include <stdio.h>
@@ -25,53 +26,28 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "adb.h"
-#include "transport.h"
-
 bool auth_required = true;
 
 void send_auth_request(atransport *t)
 {
-    D("Calling send_auth_request");
-    apacket *p;
-    int ret;
+    LOG(INFO) << "Calling send_auth_request...";
 
-    ret = adb_auth_generate_token(t->token, sizeof(t->token));
-    if (ret != sizeof(t->token)) {
-        D("Error generating token ret=%d", ret);
+    if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
+        PLOG(ERROR) << "Error generating token";
         return;
     }
 
-    p = get_apacket();
-    memcpy(p->data, t->token, ret);
+    apacket* p = get_apacket();
+    memcpy(p->data, t->token, sizeof(t->token));
     p->msg.command = A_AUTH;
     p->msg.arg0 = ADB_AUTH_TOKEN;
-    p->msg.data_length = ret;
+    p->msg.data_length = sizeof(t->token);
     send_packet(p, t);
 }
 
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
-{
-    D("Calling send_auth_response");
-    apacket *p = get_apacket();
-    int ret;
+static void send_auth_publickey(atransport* t) {
+    LOG(INFO) << "Calling send_auth_publickey";
 
-    ret = adb_auth_sign(t->key, token, token_size, p->data);
-    if (!ret) {
-        D("Error signing the token");
-        put_apacket(p);
-        return;
-    }
-
-    p->msg.command = A_AUTH;
-    p->msg.arg0 = ADB_AUTH_SIGNATURE;
-    p->msg.data_length = ret;
-    send_packet(p, t);
-}
-
-void send_auth_publickey(atransport *t)
-{
-    D("Calling send_auth_publickey");
     std::string key = adb_auth_get_userkey();
     if (key.empty()) {
         D("Failed to get user public key");
@@ -92,6 +68,35 @@
     send_packet(p, t);
 }
 
+void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
+    RSA* key = t->NextKey();
+    if (key == nullptr) {
+        // No more private keys to try, send the public key.
+        send_auth_publickey(t);
+        return;
+    }
+
+    LOG(INFO) << "Calling send_auth_response";
+    apacket* p = get_apacket();
+
+    int ret = adb_auth_sign(key, token, token_size, p->data);
+
+    // Stop sharing this key.
+    RSA_free(key);
+    key = nullptr;
+
+    if (!ret) {
+        D("Error signing the token");
+        put_apacket(p);
+        return;
+    }
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_SIGNATURE;
+    p->msg.data_length = ret;
+    send_packet(p, t);
+}
+
 void adb_auth_verified(atransport *t)
 {
     handle_online(t);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 6363bb4..723ded5 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -19,6 +19,10 @@
 
 #include "adb.h"
 
+#include <deque>
+
+#include <openssl/rsa.h>
+
 extern bool auth_required;
 
 int adb_auth_keygen(const char* filename);
@@ -26,7 +30,6 @@
 
 void send_auth_request(atransport *t);
 void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
-void send_auth_publickey(atransport *t);
 
 /* AUTH packets first argument */
 /* Request */
@@ -37,36 +40,25 @@
 
 #if ADB_HOST
 
-void adb_auth_init(void);
-int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
-                  unsigned char* sig);
-void *adb_auth_nextkey(void *current);
+void adb_auth_init();
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
 std::string adb_auth_get_userkey();
+std::deque<RSA*> adb_auth_get_private_keys();
 
-static inline int adb_auth_generate_token(void *token, size_t token_size) {
-    return 0;
-}
-static inline int adb_auth_verify(void *token, size_t token_size,
-                                  void *sig, int siglen) {
-    return 0;
-}
-static inline void adb_auth_confirm_key(unsigned char *data, size_t len,
-                                        atransport *t) {}
+static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
+static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
+static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); }
 
 #else // !ADB_HOST
 
-static inline int adb_auth_sign(void* key, const unsigned char* token,
-                                size_t token_size, unsigned char* sig) {
-    return 0;
-}
-static inline void *adb_auth_nextkey(void *current) { return NULL; }
-static inline std::string adb_auth_get_userkey() { return ""; }
+static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
+static inline std::string adb_auth_get_userkey() { abort(); }
+static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); }
 
 void adbd_auth_init(void);
 void adbd_cloexec_auth_socket();
-int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(uint8_t* token, size_t token_size,
-                    uint8_t* sig, int siglen);
+bool adb_auth_generate_token(void* token, size_t token_size);
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
 void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
 
 #endif // ADB_HOST
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 415ab8e..9d8dfc0 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -16,37 +16,25 @@
 
 #define TRACE_TAG AUTH
 
-#include "sysdeps.h"
+#include "adb.h"
 #include "adb_auth.h"
+#include "fdevent.h"
+#include "sysdeps.h"
+#include "transport.h"
 
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <crypto_utils/android_pubkey.h>
 #include <openssl/obj_mac.h>
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
-#include <crypto_utils/android_pubkey.h>
-
-#include "cutils/list.h"
-#include "cutils/sockets.h"
-
-#include "adb.h"
-#include "fdevent.h"
-#include "transport.h"
-
-struct adb_public_key {
-    struct listnode node;
-    RSA* key;
-};
-
-static const char *key_paths[] = {
-    "/adb_keys",
-    "/data/misc/adb/adb_keys",
-    NULL
-};
-
 static fdevent listener_fde;
 static fdevent framework_fde;
 static int framework_fd = -1;
@@ -56,135 +44,71 @@
 static atransport* usb_transport;
 static bool needs_retry = false;
 
-static void read_keys(const char *file, struct listnode *list)
-{
-    FILE *f;
-    char buf[MAX_PAYLOAD_V1];
-    char *sep;
-    int ret;
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
+    static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
-    f = fopen(file, "re");
-    if (!f) {
-        D("Can't open '%s'", file);
-        return;
-    }
+    for (const auto& path : key_paths) {
+        if (access(path, R_OK) == 0) {
+            LOG(INFO) << "Loading keys from " << path;
 
-    while (fgets(buf, sizeof(buf), f)) {
-        auto key = reinterpret_cast<adb_public_key*>(
-            calloc(1, sizeof(adb_public_key)));
-        if (key == nullptr) {
-            D("Can't malloc key");
-            break;
-        }
+            std::string content;
+            if (!android::base::ReadFileToString(path, &content)) {
+                PLOG(ERROR) << "Couldn't read " << path;
+                continue;
+            }
 
-        sep = strpbrk(buf, " \t");
-        if (sep)
-            *sep = '\0';
+            for (const auto& line : android::base::Split(content, "\n")) {
+                // TODO: do we really have to support both ' ' and '\t'?
+                char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
+                if (sep) *sep = '\0';
 
-        // b64_pton requires one additional byte in the target buffer for
-        // decoding to succeed. See http://b/28035006 for details.
-        uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
-        ret = __b64_pton(buf, keybuf, sizeof(keybuf));
-        if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
-            D("%s: Invalid base64 data ret=%d", file, ret);
-            free(key);
-            continue;
-        }
+                // b64_pton requires one additional byte in the target buffer for
+                // decoding to succeed. See http://b/28035006 for details.
+                uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+                if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+                    LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
+                    continue;
+                }
 
-        if (!android_pubkey_decode(keybuf, ret, &key->key)) {
-            D("%s: Failed to parse key", file);
-            free(key);
-            continue;
-        }
+                RSA* key = nullptr;
+                if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
+                    LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
+                    continue;
+                }
 
-        list_add_tail(list, &key->node);
-    }
-
-    fclose(f);
-}
-
-static void free_keys(struct listnode *list)
-{
-    struct listnode *item;
-
-    while (!list_empty(list)) {
-        item = list_head(list);
-        list_remove(item);
-        adb_public_key* key = node_to_item(item, struct adb_public_key, node);
-        RSA_free(key->key);
-        free(key);
-    }
-}
-
-static void load_keys(struct listnode *list)
-{
-    const char* path;
-    const char** paths = key_paths;
-    struct stat buf;
-
-    list_init(list);
-
-    while ((path = *paths++)) {
-        if (!stat(path, &buf)) {
-            D("Loading keys from '%s'", path);
-            read_keys(path, list);
+                bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+                RSA_free(key);
+                if (verified) return true;
+            }
         }
     }
+    return false;
 }
 
-int adb_auth_generate_token(void *token, size_t token_size)
-{
-    FILE *f;
-    int ret;
-
-    f = fopen("/dev/urandom", "re");
-    if (!f)
-        return 0;
-
-    ret = fread(token, token_size, 1, f);
-
-    fclose(f);
-    return ret * token_size;
-}
-
-int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
-{
-    struct listnode *item;
-    struct listnode key_list;
-    int ret = 0;
-
-    load_keys(&key_list);
-
-    list_for_each(item, &key_list) {
-        adb_public_key* key = node_to_item(item, struct adb_public_key, node);
-        ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
-        if (ret)
-            break;
-    }
-
-    free_keys(&key_list);
-
-    return ret;
+bool adb_auth_generate_token(void* token, size_t token_size) {
+    FILE* fp = fopen("/dev/urandom", "re");
+    if (!fp) return false;
+    bool okay = (fread(token, token_size, 1, fp) == 1);
+    fclose(fp);
+    return okay;
 }
 
 static void usb_disconnected(void* unused, atransport* t) {
-    D("USB disconnect");
+    LOG(INFO) << "USB disconnect";
     usb_transport = NULL;
     needs_retry = false;
 }
 
 static void framework_disconnected() {
-    D("Framework disconnect");
+    LOG(INFO) << "Framework disconnect";
     fdevent_remove(&framework_fde);
     framework_fd = -1;
 }
 
 static void adb_auth_event(int fd, unsigned events, void*) {
-    char response[2];
-    int ret;
-
     if (events & FDE_READ) {
-        ret = unix_read(fd, response, sizeof(response));
+        char response[2];
+        int ret = unix_read(fd, response, sizeof(response));
         if (ret <= 0) {
             framework_disconnected();
         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
@@ -195,51 +119,43 @@
     }
 }
 
-void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
-{
-    char msg[MAX_PAYLOAD_V1];
-    int ret;
-
+void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
     if (!usb_transport) {
         usb_transport = t;
         t->AddDisconnect(&usb_disconnect);
     }
 
     if (framework_fd < 0) {
-        D("Client not connected");
+        LOG(ERROR) << "Client not connected";
         needs_retry = true;
         return;
     }
 
     if (key[len - 1] != '\0') {
-        D("Key must be a null-terminated string");
+        LOG(ERROR) << "Key must be a null-terminated string";
         return;
     }
 
-    ret = snprintf(msg, sizeof(msg), "PK%s", key);
-    if (ret >= (signed)sizeof(msg)) {
-        D("Key too long. ret=%d", ret);
+    char msg[MAX_PAYLOAD_V1];
+    int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
+    if (msg_len >= static_cast<int>(sizeof(msg))) {
+        LOG(ERROR) << "Key too long (" << msg_len << ")";
         return;
     }
-    D("Sending '%s'", msg);
+    LOG(DEBUG) << "Sending '" << msg << "'";
 
-    ret = unix_write(framework_fd, msg, ret);
-    if (ret < 0) {
-        D("Failed to write PK, errno=%d", errno);
+    if (unix_write(framework_fd, msg, msg_len) == -1) {
+        PLOG(ERROR) << "Failed to write PK";
         return;
     }
 }
 
 static void adb_auth_listener(int fd, unsigned events, void* data) {
     sockaddr_storage addr;
-    socklen_t alen;
-    int s;
-
-    alen = sizeof(addr);
-
-    s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
+    socklen_t alen = sizeof(addr);
+    int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
     if (s < 0) {
-        D("Failed to accept: errno=%d", errno);
+        PLOG(ERROR) << "Failed to accept";
         return;
     }
 
@@ -261,7 +177,7 @@
 void adbd_cloexec_auth_socket() {
     int fd = android_get_control_socket("adbd");
     if (fd == -1) {
-        D("Failed to get adbd socket");
+        PLOG(ERROR) << "Failed to get adbd socket";
         return;
     }
     fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -270,12 +186,12 @@
 void adbd_auth_init(void) {
     int fd = android_get_control_socket("adbd");
     if (fd == -1) {
-        D("Failed to get adbd socket");
+        PLOG(ERROR) << "Failed to get adbd socket";
         return;
     }
 
     if (listen(fd, 4) == -1) {
-        D("Failed to listen on '%d'", fd);
+        PLOG(ERROR) << "Failed to listen on '" << fd << "'";
         return;
     }
 
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index dff874f..ce269cc 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,23 +16,22 @@
 
 #define TRACE_TAG AUTH
 
-#include "sysdeps.h"
 #include "adb_auth.h"
+#include "adb.h"
 #include "adb_utils.h"
+#include "sysdeps.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "adb.h"
+#include <mutex>
 
 #include <android-base/errors.h>
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <crypto_utils/android_pubkey.h>
-#include <cutils/list.h>
-
 #include <openssl/base64.h>
 #include <openssl/evp.h>
 #include <openssl/objects.h>
@@ -40,18 +39,14 @@
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
-#define ANDROID_PATH   ".android"
-#define ADB_KEY_FILE   "adbkey"
+#include "sysdeps/mutex.h"
 
-struct adb_private_key {
-    struct listnode node;
-    RSA *rsa;
-};
-
-static struct listnode key_list;
-
+static std::mutex& g_key_list_mutex = *new std::mutex;
+static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
 
 static std::string get_user_info() {
+    LOG(INFO) << "get_user_info...";
+
     std::string hostname;
     if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
 #if !defined(_WIN32)
@@ -71,6 +66,8 @@
 }
 
 static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
+    LOG(INFO) << "write_public_keyfile...";
+
     uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
     if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
         LOG(ERROR) << "Failed to convert to public key";
@@ -99,19 +96,18 @@
     return true;
 }
 
-static int generate_key(const char *file)
-{
-    EVP_PKEY* pkey = EVP_PKEY_new();
-    BIGNUM* exponent = BN_new();
-    RSA* rsa = RSA_new();
+static int generate_key(const std::string& file) {
+    LOG(INFO) << "generate_key(" << file << ")...";
+
     mode_t old_mask;
     FILE *f = NULL;
     int ret = 0;
 
-    D("generate_key '%s'", file);
-
+    EVP_PKEY* pkey = EVP_PKEY_new();
+    BIGNUM* exponent = BN_new();
+    RSA* rsa = RSA_new();
     if (!pkey || !exponent || !rsa) {
-        D("Failed to allocate key");
+        LOG(ERROR) << "Failed to allocate key";
         goto out;
     }
 
@@ -121,9 +117,9 @@
 
     old_mask = umask(077);
 
-    f = fopen(file, "w");
+    f = fopen(file.c_str(), "w");
     if (!f) {
-        D("Failed to open '%s'", file);
+        PLOG(ERROR) << "Failed to open " << file;
         umask(old_mask);
         goto out;
     }
@@ -143,110 +139,110 @@
     ret = 1;
 
 out:
-    if (f)
-        fclose(f);
+    if (f) fclose(f);
     EVP_PKEY_free(pkey);
     RSA_free(rsa);
     BN_free(exponent);
     return ret;
 }
 
-static int read_key(const char *file, struct listnode *list)
-{
-    D("read_key '%s'", file);
+static bool read_key(const std::string& file) {
+    LOG(INFO) << "read_key '" << file << "'...";
 
-    FILE* fp = fopen(file, "r");
+    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
     if (!fp) {
-        D("Failed to open '%s': %s", file, strerror(errno));
-        return 0;
+        PLOG(ERROR) << "Failed to open '" << file << "'";
+        return false;
     }
 
-    adb_private_key* key = new adb_private_key;
-    key->rsa = RSA_new();
-
-    if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
-        D("Failed to read key");
-        fclose(fp);
-        RSA_free(key->rsa);
-        delete key;
-        return 0;
+    RSA* key = RSA_new();
+    if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
+        LOG(ERROR) << "Failed to read key";
+        RSA_free(key);
+        return false;
     }
 
-    fclose(fp);
-    list_add_tail(list, &key->node);
-    return 1;
+    g_key_list.push_back(key);
+    return true;
 }
 
-static int get_user_keyfilepath(char *filename, size_t len)
-{
+static std::string get_user_key_path() {
     const std::string home = adb_get_homedir_path(true);
-    D("home '%s'", home.c_str());
+    LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
 
-    const std::string android_dir =
-            android::base::StringPrintf("%s%c%s", home.c_str(),
-                                        OS_PATH_SEPARATOR, ANDROID_PATH);
+    const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
+                                                                OS_PATH_SEPARATOR);
 
     struct stat buf;
-    if (stat(android_dir.c_str(), &buf)) {
-        if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
-            D("Cannot mkdir '%s'", android_dir.c_str());
-            return -1;
+    if (stat(android_dir.c_str(), &buf) == -1) {
+        if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+            PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
+            return "";
         }
     }
 
-    return snprintf(filename, len, "%s%c%s",
-                    android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
+    return android_dir + OS_PATH_SEPARATOR + "adbkey";
 }
 
-static int get_user_key(struct listnode *list)
-{
-    struct stat buf;
-    char path[PATH_MAX];
-    int ret;
-
-    ret = get_user_keyfilepath(path, sizeof(path));
-    if (ret < 0 || ret >= (signed)sizeof(path)) {
-        D("Error getting user key filename");
-        return 0;
+static bool get_user_key() {
+    std::string path = get_user_key_path();
+    if (path.empty()) {
+        PLOG(ERROR) << "Error getting user key filename";
+        return false;
     }
 
-    D("user key '%s'", path);
-
-    if (stat(path, &buf) == -1) {
+    struct stat buf;
+    if (stat(path.c_str(), &buf) == -1) {
+        LOG(INFO) << "User key '" << path << "' does not exist...";
         if (!generate_key(path)) {
-            D("Failed to generate new key");
-            return 0;
+            LOG(ERROR) << "Failed to generate new key";
+            return false;
         }
     }
 
-    return read_key(path, list);
+    return read_key(path);
 }
 
-static void get_vendor_keys(struct listnode* key_list) {
+static void get_vendor_keys() {
     const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
     if (adb_keys_path == nullptr) {
         return;
     }
 
     for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
-        if (!read_key(path.c_str(), key_list)) {
-            D("Failed to read '%s'", path.c_str());
+        if (!read_key(path.c_str())) {
+            PLOG(ERROR) << "Failed to read '" << path << "'";
         }
     }
 }
 
-int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
-                  unsigned char* sig)
-{
-    unsigned int len;
-    struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
+std::deque<RSA*> adb_auth_get_private_keys() {
+    std::deque<RSA*> result;
 
+    // Copy all the currently known keys, increasing their reference count so they're
+    // usable until both we and the caller have freed our pointers.
+    std::lock_guard<std::mutex> lock(g_key_list_mutex);
+    for (const auto& key : g_key_list) {
+        RSA_up_ref(key); // Since we're handing out another pointer to this key...
+        result.push_back(key);
+    }
+
+    // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
+    // but try using the public key" (the empty deque could otherwise mean this _or_
+    // that this function hasn't been called yet to request the keys).
+    result.push_back(nullptr);
+
+    return result;
+}
+
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
     if (token_size != TOKEN_SIZE) {
         D("Unexpected token size %zd", token_size);
         return 0;
     }
 
-    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
+    unsigned int len;
+    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
         return 0;
     }
 
@@ -254,40 +250,17 @@
     return (int)len;
 }
 
-void *adb_auth_nextkey(void *current)
-{
-    struct listnode *item;
-
-    if (list_empty(&key_list))
-        return NULL;
-
-    if (!current)
-        return list_head(&key_list);
-
-    list_for_each(item, &key_list) {
-        if (item == current) {
-            /* current is the last item, we tried all the keys */
-            if (item->next == &key_list)
-                return NULL;
-            return item->next;
-        }
-    }
-
-    return NULL;
-}
-
 std::string adb_auth_get_userkey() {
-    char path[PATH_MAX];
-    int ret = get_user_keyfilepath(path, sizeof(path) - 4);
-    if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
-        D("Error getting user key filename");
+    std::string path = get_user_key_path();
+    if (path.empty()) {
+        PLOG(ERROR) << "Error getting user key filename";
         return "";
     }
-    strcat(path, ".pub");
+    path += ".pub";
 
     std::string content;
     if (!android::base::ReadFileToString(path, &content)) {
-        D("Can't load '%s'", path);
+        PLOG(ERROR) << "Can't load '" << path << "'";
         return "";
     }
     return content;
@@ -297,19 +270,14 @@
     return (generate_key(filename) == 0);
 }
 
-void adb_auth_init(void)
-{
-    int ret;
+void adb_auth_init() {
+    LOG(INFO) << "adb_auth_init...";
 
-    D("adb_auth_init");
-
-    list_init(&key_list);
-
-    ret = get_user_key(&key_list);
-    if (!ret) {
-        D("Failed to get user key");
+    if (!get_user_key()) {
+        LOG(ERROR) << "Failed to get user key";
         return;
     }
 
-    get_vendor_keys(&key_list);
+    std::lock_guard<std::mutex> lock(g_key_list_mutex);
+    get_vendor_keys();
 }
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index 9ed44a7..c348dd5 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -47,7 +47,7 @@
           show_progress_(show_progress),
           status_(0),
           line_() {
-        SetLineMessage();
+        SetLineMessage("generating");
     }
 
     void OnStdout(const char* buffer, int length) {
@@ -97,6 +97,7 @@
                                                           OS_PATH_SEPARATOR, dest_file_.c_str());
             }
             std::vector<const char*> srcs{src_file_.c_str()};
+            SetLineMessage("pulling");
             status_ =
                 br_->DoSyncPull(srcs, destination.c_str(), true, line_message_.c_str()) ? 0 : 1;
             if (status_ != 0) {
@@ -111,9 +112,8 @@
     }
 
   private:
-    void SetLineMessage() {
-        line_message_ =
-            android::base::StringPrintf("generating %s", adb_basename(dest_file_).c_str());
+    void SetLineMessage(const std::string& action) {
+        line_message_ = action + " " + adb_basename(dest_file_);
     }
 
     void SetSrcFile(const std::string path) {
@@ -121,7 +121,7 @@
         if (!dest_dir_.empty()) {
             // Only uses device-provided name when user passed a directory.
             dest_file_ = adb_basename(path);
-            SetLineMessage();
+            SetLineMessage("generating");
         }
     }
 
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
index 3cd2b6d..1129285 100644
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -189,7 +189,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport"};
@@ -209,7 +209,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport"};
@@ -223,7 +223,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -239,7 +239,7 @@
                         WithArg<4>(WriteOnStdout("/bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -275,7 +275,7 @@
             WithArg<4>(ReturnCallbackDone())));
     // clang-format on
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -294,7 +294,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", td.path};
@@ -308,7 +308,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file"};
@@ -327,7 +327,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", td.path};
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 894ebd1..0c85fe5 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -111,7 +111,6 @@
 
     usb_init();
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
-    adb_auth_init();
 
     std::string error;
     std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
@@ -119,11 +118,14 @@
         fatal("could not install *smartsocket* listener: %s", error.c_str());
     }
 
-    // Inform our parent that we are up and running.
     if (is_daemon) {
         close_stdin();
         setup_daemon_logging();
+    }
 
+    adb_auth_init();
+
+    if (is_daemon) {
 #if !defined(_WIN32)
         // Start a new session for the daemon. Do this here instead of after the fork so
         // that a ctrl-c between the "starting server" and "done starting server" messages
@@ -133,6 +135,8 @@
         }
 #endif
 
+        // Inform our parent that we are up and running.
+
         // Any error output written to stderr now goes to adb.log. We could
         // keep around a copy of the stderr fd and use that to write any errors
         // encountered by the following code, but that is probably overkill.
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 04df16f..333b861 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -828,4 +828,9 @@
 // configured to drop after 10 missed keepalives. Returns true on success.
 bool set_tcp_keepalive(int fd, int interval_sec);
 
+#if defined(_WIN32)
+// Win32 defines ERROR, which we don't need, but which conflicts with google3 logging.
+#undef ERROR
+#endif
+
 #endif /* _ADB_SYSDEPS_H */
diff --git a/adb/transport.cpp b/adb/transport.cpp
index ad63a6a..0d376b1 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -35,6 +35,7 @@
 #include <android-base/strings.h>
 
 #include "adb.h"
+#include "adb_auth.h"
 #include "adb_utils.h"
 #include "diagnose_usb.h"
 
@@ -1072,3 +1073,11 @@
         return 0;
     }
 }
+
+RSA* atransport::NextKey() {
+    if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+
+    RSA* result = keys_[0];
+    keys_.pop_front();
+    return result;
+}
diff --git a/adb/transport.h b/adb/transport.h
index 46d472b..d41c8bd 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -19,12 +19,15 @@
 
 #include <sys/types.h>
 
+#include <deque>
 #include <list>
 #include <string>
 #include <unordered_set>
 
 #include "adb.h"
 
+#include <openssl/rsa.h>
+
 typedef std::unordered_set<std::string> FeatureSet;
 
 const FeatureSet& supported_features();
@@ -104,7 +107,8 @@
         return type == kTransportLocal && local_port_for_emulator_ == -1;
     }
 
-    void* key = nullptr;
+    RSA* NextKey();
+
     unsigned char token[TOKEN_SIZE] = {};
     size_t failed_auth_attempts = 0;
 
@@ -156,6 +160,8 @@
     // A list of adisconnect callbacks called when the transport is kicked.
     std::list<adisconnect*> disconnects_;
 
+    std::deque<RSA*> keys_;
+
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 44e92fe..bbc724a 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -185,7 +185,7 @@
   return result;
 }
 
-static void send_debuggerd_packet(siginfo_t* info) {
+static void send_debuggerd_packet() {
   // 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;
@@ -222,7 +222,6 @@
     msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_callbacks.get_abort_message());
   }
 
-  msg.original_si_code = (info != nullptr) ? info->si_code : 0;
   ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
   if (ret == sizeof(msg)) {
     char debuggerd_ack;
@@ -254,7 +253,7 @@
 
   log_signal_summary(signal_number, info);
 
-  send_debuggerd_packet(info);
+  send_debuggerd_packet();
 
   // 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
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index c352aeb..12fa4e6 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -51,6 +51,8 @@
 
 #include <private/android_filesystem_config.h>
 
+#include <debuggerd/client.h>
+
 #include "backtrace.h"
 #include "getevent.h"
 #include "signal_sender.h"
@@ -70,7 +72,6 @@
   pid_t pid, tid;
   uid_t uid, gid;
   uintptr_t abort_msg_address;
-  int32_t original_si_code;
 };
 
 static void wait_for_user_action(const debugger_request_t& request) {
@@ -232,7 +233,6 @@
   out_request->uid = cr.uid;
   out_request->gid = cr.gid;
   out_request->abort_msg_address = msg.abort_msg_address;
-  out_request->original_si_code = msg.original_si_code;
 
   if (msg.action == DEBUGGER_ACTION_CRASH) {
     // Ensure that the tid reported by the crashing process is valid.
@@ -487,9 +487,10 @@
     return false;
   }
 
-  int total_sleep_time_usec = 0;
   while (true) {
-    int signal = wait_for_signal(request.tid, &total_sleep_time_usec);
+    // wait_for_signal waits for forever, but the watchdog process will kill us
+    // if it takes too long.
+    int signal = wait_for_signal(request.tid);
     switch (signal) {
       case -1:
         ALOGE("debuggerd: timed out waiting for signal");
@@ -498,8 +499,8 @@
       case SIGSTOP:
         if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
           ALOGV("debuggerd: stopped -- dumping to tombstone");
-          engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                            request.original_si_code, request.abort_msg_address, amfd_data);
+          engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+                            request.abort_msg_address, amfd_data);
         } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
           ALOGV("debuggerd: stopped -- dumping to fd");
           dump_backtrace(fd, backtrace_map, request.pid, request.tid, siblings, nullptr);
@@ -525,8 +526,8 @@
       case SIGTRAP:
         ALOGV("stopped -- fatal signal\n");
         *crash_signal = signal;
-        engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                          request.original_si_code, request.abort_msg_address, amfd_data);
+        engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+                          request.abort_msg_address, amfd_data);
         break;
 
       default:
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
index 41b7b3a..8225c73 100644
--- a/debuggerd/include/debuggerd/client.h
+++ b/debuggerd/include/debuggerd/client.h
@@ -44,7 +44,6 @@
   int32_t action;
   pid_t tid;
   uint64_t abort_msg_address;
-  int32_t original_si_code;
 } debugger_msg_t;
 
 // These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index 58d640e..5ee07cd 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -595,7 +595,7 @@
   si.si_signo = 0;
   ptrace_set_fake_getsiginfo(si);
 
-  dump_signal_info(&log_, 123, SIGSEGV, 10);
+  dump_signal_info(&log_, 123);
 
   std::string tombstone_contents;
   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index dfdf29c..9359678 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -176,7 +176,7 @@
   _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
 }
 
-static void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) {
+static void dump_signal_info(log_t* log, pid_t tid) {
   siginfo_t si;
   memset(&si, 0, sizeof(si));
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) {
@@ -184,18 +184,15 @@
     return;
   }
 
-  // bionic has to re-raise some signals, which overwrites the si_code with SI_TKILL.
-  si.si_code = si_code;
-
   char addr_desc[32]; // ", fault addr 0x1234"
-  if (signal_has_si_addr(signal)) {
+  if (signal_has_si_addr(si.si_signo)) {
     snprintf(addr_desc, sizeof(addr_desc), "%p", si.si_addr);
   } else {
     snprintf(addr_desc, sizeof(addr_desc), "--------");
   }
 
-  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n",
-       signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc);
+  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si.si_signo,
+       get_signame(si.si_signo), si.si_code, get_sigcode(si.si_signo, si.si_code), addr_desc);
 }
 
 static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
@@ -445,17 +442,14 @@
   }
 }
 
-static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map, int signal,
-                        int si_code, uintptr_t abort_msg_address, bool primary_thread) {
+static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map,
+                        uintptr_t abort_msg_address, bool primary_thread) {
   log->current_tid = tid;
   if (!primary_thread) {
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
   }
   dump_thread_info(log, pid, tid);
-
-  if (signal) {
-    dump_signal_info(log, tid, signal, si_code);
-  }
+  dump_signal_info(log, tid);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
   if (primary_thread) {
@@ -606,8 +600,7 @@
 
 // Dumps all information about the specified pid to the tombstone.
 static void dump_crash(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int si_code,
-                       uintptr_t abort_msg_address) {
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address) {
   // don't copy log messages to tombstone unless this is a dev device
   char value[PROPERTY_VALUE_MAX];
   property_get("ro.debuggable", value, "0");
@@ -616,14 +609,14 @@
   _LOG(log, logtype::HEADER,
        "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
   dump_header_info(log);
-  dump_thread(log, pid, tid, map, signal, si_code, abort_msg_address, true);
+  dump_thread(log, pid, tid, map, abort_msg_address, true);
   if (want_logs) {
     dump_logs(log, pid, 5);
   }
 
   if (!siblings.empty()) {
     for (pid_t sibling : siblings) {
-      dump_thread(log, pid, sibling, map, 0, 0, 0, false);
+      dump_thread(log, pid, sibling, map, 0, false);
     }
   }
 
@@ -686,8 +679,8 @@
 }
 
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address, std::string* amfd_data) {
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+                       std::string* amfd_data) {
   log_t log;
   log.current_tid = tid;
   log.crashed_tid = tid;
@@ -699,5 +692,5 @@
 
   log.tfd = tombstone_fd;
   log.amfd_data = amfd_data;
-  dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address);
+  dump_crash(&log, map, pid, tid, siblings, abort_msg_address);
 }
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index 487d950..e1c39c5 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -33,7 +33,7 @@
 
 /* Creates a tombstone file and writes the crash dump to it. */
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address, std::string* amfd_data);
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+                       std::string* amfd_data);
 
 #endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index bd06095..7fabf69 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -31,9 +31,6 @@
 #include <backtrace/Backtrace.h>
 #include <log/log.h>
 
-constexpr int SLEEP_TIME_USEC = 50000;          // 0.05 seconds
-constexpr int MAX_TOTAL_SLEEP_USEC = 10000000;  // 10 seconds
-
 // Whitelist output desired in the logcat output.
 bool is_allowed_in_logcat(enum logtype ltype) {
   if ((ltype == HEADER)
@@ -74,10 +71,10 @@
   }
 }
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+int wait_for_signal(pid_t tid) {
   while (true) {
     int status;
-    pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
+    pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL));
     if (n == -1) {
       ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
       return -1;
@@ -91,14 +88,6 @@
         return -1;
       }
     }
-
-    if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) {
-      ALOGE("timed out waiting for stop signal: tid=%d", tid);
-      return -1;
-    }
-
-    usleep(SLEEP_TIME_USEC);
-    *total_sleep_time_usec += SLEEP_TIME_USEC;
   }
 }
 
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index cd01188..d820f0f 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -77,7 +77,7 @@
 void _LOG(log_t* log, logtype ltype, const char *fmt, ...)
         __attribute__ ((format(printf, 3, 4)));
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
+int wait_for_signal(pid_t tid);
 
 void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...);
 
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 314ed42..ce8df88 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -599,6 +599,7 @@
     ZipEntry zip_entry;
     if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
         fprintf(stderr, "archive does not contain '%s'\n", entry_name);
+        fclose(fp);
         return -1;
     }
 
@@ -606,10 +607,12 @@
     int error = ExtractEntryToFile(zip, &zip_entry, fd);
     if (error != 0) {
         fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
+        fclose(fp);
         return -1;
     }
 
     lseek(fd, 0, SEEK_SET);
+    // TODO: We're leaking 'fp' here.
     return fd;
 }
 
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index ab52512..46d147a 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -898,3 +898,22 @@
 
     return 0;
 }
+
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
+{
+    if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+        int rc = fs_mgr_setup_verity(fstab_rec);
+        if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+            INFO("Verity disabled");
+            return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+        } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
+            return FS_MGR_EARLY_SETUP_VERITY_SUCCESS;
+        } else {
+            return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+        }
+    } else if (device_is_secure()) {
+        ERROR("Verity must be enabled for early mounted partitions on secured devices.\n");
+        return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+    }
+    return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 45adb34..f73cb7e 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -241,9 +241,8 @@
     return f;
 }
 
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
 {
-    FILE *fstab_file;
     int cnt, entries;
     ssize_t len;
     size_t alloc_len = 0;
@@ -255,12 +254,6 @@
 #define FS_OPTIONS_LEN 1024
     char tmp_fs_options[FS_OPTIONS_LEN];
 
-    fstab_file = fopen(fstab_path, "r");
-    if (!fstab_file) {
-        ERROR("Cannot open file %s\n", fstab_path);
-        return 0;
-    }
-
     entries = 0;
     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
@@ -286,7 +279,6 @@
     /* Allocate and init the fstab structure */
     fstab = calloc(1, sizeof(struct fstab));
     fstab->num_entries = entries;
-    fstab->fstab_filename = strdup(fstab_path);
     fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
 
     fseek(fstab_file, 0, SEEK_SET);
@@ -370,18 +362,34 @@
         ERROR("Error updating for slotselect\n");
         goto err;
     }
-    fclose(fstab_file);
     free(line);
     return fstab;
 
 err:
-    fclose(fstab_file);
     free(line);
     if (fstab)
         fs_mgr_free_fstab(fstab);
     return NULL;
 }
 
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+{
+    FILE *fstab_file;
+    struct fstab *fstab;
+
+    fstab_file = fopen(fstab_path, "r");
+    if (!fstab_file) {
+        ERROR("Cannot open file %s\n", fstab_path);
+        return NULL;
+    }
+    fstab = fs_mgr_read_fstab_file(fstab_file);
+    if (fstab) {
+        fstab->fstab_filename = strdup(fstab_path);
+    }
+    fclose(fstab_file);
+    return fstab;
+}
+
 void fs_mgr_free_fstab(struct fstab *fstab)
 {
     int i;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 031b042..7fe6763 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -341,17 +341,6 @@
     return 0;
 }
 
-static int test_access(char *device) {
-    int tries = 25;
-    while (tries--) {
-        if (!access(device, F_OK) || errno != ENOENT) {
-            return 0;
-        }
-        usleep(40 * 1000);
-    }
-    return -1;
-}
-
 static int check_verity_restart(const char *fname)
 {
     char buffer[VERITY_KMSG_BUFSIZE + 1];
@@ -1042,11 +1031,6 @@
     fstab->blk_device = verity_blk_name;
     verity_blk_name = 0;
 
-    // make sure we've set everything up properly
-    if (test_access(fstab->blk_device) < 0) {
-        goto out;
-    }
-
     retval = FS_MGR_SETUP_VERITY_SUCCESS;
 
 out:
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 6f2548d..725ce89 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,6 +17,7 @@
 #ifndef __CORE_FS_MGR_H
 #define __CORE_FS_MGR_H
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <linux/dm-ioctl.h>
@@ -73,6 +74,7 @@
 typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
         const char *mount_point, int mode, int status);
 
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
 struct fstab *fs_mgr_read_fstab(const char *fstab_path);
 void fs_mgr_free_fstab(struct fstab *fstab);
 
@@ -115,6 +117,11 @@
 
 int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
 
+#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2
+#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1
+#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/init/devices.cpp b/init/devices.cpp
index 373177e..830b74c 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -44,6 +44,7 @@
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cutils/list.h>
 #include <cutils/uevent.h>
 
@@ -601,14 +602,17 @@
     return name;
 }
 
+#define DEVPATH_LEN 96
+#define MAX_DEV_NAME 64
+
 static void handle_block_device_event(struct uevent *uevent)
 {
     const char *base = "/dev/block/";
     const char *name;
-    char devpath[96];
+    char devpath[DEVPATH_LEN];
     char **links = NULL;
 
-    name = parse_device_name(uevent, 64);
+    name = parse_device_name(uevent, MAX_DEV_NAME);
     if (!name)
         return;
 
@@ -622,8 +626,6 @@
             uevent->major, uevent->minor, links);
 }
 
-#define DEVPATH_LEN 96
-
 static bool assemble_devpath(char *devpath, const char *dirname,
         const char *devname)
 {
@@ -657,7 +659,7 @@
     char devpath[DEVPATH_LEN] = {0};
     char **links = NULL;
 
-    name = parse_device_name(uevent, 64);
+    name = parse_device_name(uevent, MAX_DEV_NAME);
     if (!name)
         return;
 
@@ -900,7 +902,8 @@
 }
 
 #define UEVENT_MSG_LEN  2048
-void handle_device_fd()
+
+static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
 {
     char msg[UEVENT_MSG_LEN+2];
     int n;
@@ -913,21 +916,28 @@
 
         struct uevent uevent;
         parse_event(msg, &uevent);
-
-        if (selinux_status_updated() > 0) {
-            struct selabel_handle *sehandle2;
-            sehandle2 = selinux_android_file_context_handle();
-            if (sehandle2) {
-                selabel_close(sehandle);
-                sehandle = sehandle2;
-            }
-        }
-
-        handle_device_event(&uevent);
-        handle_firmware_event(&uevent);
+        handle_uevent(&uevent);
     }
 }
 
+void handle_device_fd()
+{
+    handle_device_fd_with(
+        [](struct uevent *uevent) {
+            if (selinux_status_updated() > 0) {
+                struct selabel_handle *sehandle2;
+                sehandle2 = selinux_android_file_context_handle();
+                if (sehandle2) {
+                    selabel_close(sehandle);
+                    sehandle = sehandle2;
+                }
+            }
+
+            handle_device_event(uevent);
+            handle_firmware_event(uevent);
+        });
+}
+
 /* Coldboot walks parts of the /sys tree and pokes the uevent files
 ** to cause the kernel to regenerate device add events that happened
 ** before init's device manager was started
@@ -979,6 +989,65 @@
     }
 }
 
+static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
+{
+    const char *name;
+    char devpath[DEVPATH_LEN];
+
+    if (is_block && strncmp(uevent->subsystem, "block", 5))
+        return;
+
+    name = parse_device_name(uevent, MAX_DEV_NAME);
+    if (!name) {
+        LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
+                   << " " << uevent->partition_name << " " << uevent->partition_num
+                   << " " << uevent->major << ":" << uevent->minor;
+        return;
+    }
+
+    snprintf(devpath, sizeof(devpath), "%s%s", base, name);
+    make_dir(base, 0755);
+
+    dev_t dev = makedev(uevent->major, uevent->minor);
+    mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
+    mknod(devpath, mode, dev);
+}
+
+void early_create_dev(const std::string& syspath, early_device_type dev_type)
+{
+    android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
+    if (dfd < 0) {
+        LOG(ERROR) << "Failed to open " << syspath;
+        return;
+    }
+
+    android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
+    if (fd < 0) {
+        LOG(ERROR) << "Failed to open " << syspath << "/uevent";
+        return;
+    }
+
+    fcntl(device_fd, F_SETFL, O_NONBLOCK);
+
+    write(fd, "add\n", 4);
+    handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
+        [](struct uevent *uevent) {
+            early_uevent_handler(uevent, "/dev/block/", true);
+        } :
+        [](struct uevent *uevent) {
+            early_uevent_handler(uevent, "/dev/", false);
+        });
+}
+
+int early_device_socket_open() {
+    device_fd = uevent_open_socket(256*1024, true);
+    return device_fd < 0;
+}
+
+void early_device_socket_close() {
+    close(device_fd);
+}
+
 void device_init() {
     sehandle = selinux_android_file_context_handle();
     selinux_status_open(true);
diff --git a/init/devices.h b/init/devices.h
index 6cb0a77..8e9ab7d 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -21,6 +21,13 @@
 
 extern void handle_device_fd();
 extern void device_init(void);
+
+enum early_device_type { EARLY_BLOCK_DEV, EARLY_CHAR_DEV };
+
+extern int early_device_socket_open();
+extern void early_device_socket_close();
+extern void early_create_dev(const std::string& syspath, early_device_type dev_type);
+
 extern int add_dev_perms(const char *name, const char *attr,
                          mode_t perm, unsigned int uid,
                          unsigned int gid, unsigned short prefix,
diff --git a/init/init.cpp b/init/init.cpp
index 29e8cbb..7a0e114 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -55,6 +55,7 @@
 #include "action.h"
 #include "bootchart.h"
 #include "devices.h"
+#include "fs_mgr.h"
 #include "import_parser.h"
 #include "init.h"
 #include "init_parser.h"
@@ -450,9 +451,6 @@
 }
 
 static void process_kernel_cmdline() {
-    // Don't expose the raw commandline to unprivileged processes.
-    chmod("/proc/cmdline", 0440);
-
     // The first pass does the common stuff, and finds if we are in qemu.
     // The second pass is only necessary for qemu to export all kernel params
     // as properties.
@@ -563,6 +561,104 @@
     }
 }
 
+/* Returns a new path consisting of base_path and the file name in reference_path. */
+static std::string get_path(const std::string& base_path, const std::string& reference_path) {
+    std::string::size_type pos = reference_path.rfind('/');
+    if (pos == std::string::npos) {
+        return base_path + '/' + reference_path;
+    } else {
+        return base_path + reference_path.substr(pos);
+    }
+}
+
+/* Imports the fstab info from cmdline. */
+static std::string import_cmdline_fstab() {
+    std::string prefix, fstab, fstab_full;
+
+    import_kernel_cmdline(false,
+        [&](const std::string& key, const std::string& value, bool in_qemu __attribute__((__unused__))) {
+            if (key == "android.early.prefix") {
+                prefix = value;
+            } else if (key == "android.early.fstab") {
+                fstab = value;
+            }
+        });
+    if (!fstab.empty()) {
+        // Convert "mmcblk0p09+/odm+ext4+ro+verify" to "mmcblk0p09 /odm ext4 ro verify"
+        std::replace(fstab.begin(), fstab.end(), '+', ' ');
+        for (const auto& entry : android::base::Split(fstab, "\n")) {
+            fstab_full += prefix + entry + '\n';
+        }
+    }
+    return fstab_full;
+}
+
+/* Early mount vendor and ODM partitions. The fstab info is read from kernel cmdline. */
+static void early_mount() {
+    std::string fstab_string = import_cmdline_fstab();
+    if (fstab_string.empty()) {
+        LOG(INFO) << "Failed to load vendor fstab from kernel cmdline";
+        return;
+    }
+    FILE *fstab_file = fmemopen((void *)fstab_string.c_str(), fstab_string.length(), "r");
+    if (!fstab_file) {
+        PLOG(ERROR) << "Failed to open fstab string as FILE";
+        return;
+    }
+    std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_file(fstab_file), fs_mgr_free_fstab);
+    fclose(fstab_file);
+    if (!fstab) {
+        LOG(ERROR) << "Failed to parse fstab string: " << fstab_string;
+        return;
+    }
+    LOG(INFO) << "Loaded vendor fstab from cmdline";
+
+    if (early_device_socket_open()) {
+        LOG(ERROR) << "Failed to open device uevent socket";
+        return;
+    }
+
+    /* Create /dev/device-mapper for dm-verity */
+    early_create_dev("/sys/devices/virtual/misc/device-mapper", EARLY_CHAR_DEV);
+
+    for (int i = 0; i < fstab->num_entries; ++i) {
+        struct fstab_rec *rec = &fstab->recs[i];
+        std::string mount_point = rec->mount_point;
+        std::string syspath = rec->blk_device;
+
+        if (mount_point != "/vendor" && mount_point != "/odm")
+            continue;
+
+        /* Create mount target under /dev/block/ from sysfs via uevent */
+        LOG(INFO) << "Mounting " << mount_point << " from " << syspath << "...";
+        char *devpath = strdup(get_path("/dev/block", syspath).c_str());
+        if (!devpath) {
+            PLOG(ERROR) << "Failed to strdup dev path in early mount " << syspath;
+            continue;
+        }
+        rec->blk_device = devpath;
+        early_create_dev(syspath, EARLY_BLOCK_DEV);
+
+        int rc = fs_mgr_early_setup_verity(rec);
+        if (rc == FS_MGR_EARLY_SETUP_VERITY_SUCCESS) {
+            /* Mount target is changed to /dev/block/dm-<n>; initiate its creation from sysfs counterpart */
+            early_create_dev(get_path("/sys/devices/virtual/block", rec->blk_device), EARLY_BLOCK_DEV);
+        } else if (rc == FS_MGR_EARLY_SETUP_VERITY_FAIL) {
+            LOG(ERROR) << "Failed to set up dm-verity on " << rec->blk_device;
+            continue;
+        } else { /* FS_MGR_EARLY_SETUP_VERITY_NO_VERITY */
+            LOG(INFO) << "dm-verity disabled on debuggable device; mount directly on " << rec->blk_device;
+        }
+
+        mkdir(mount_point.c_str(), 0755);
+        rc = mount(rec->blk_device, mount_point.c_str(), rec->fs_type, rec->flags, rec->fs_options);
+        if (rc) {
+            PLOG(ERROR) << "Failed to mount on " << rec->blk_device;
+        }
+    }
+    early_device_socket_close();
+}
+
 int main(int argc, char** argv) {
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
@@ -579,6 +675,9 @@
 
     bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
 
+    // Don't expose the raw commandline to unprivileged processes.
+    chmod("/proc/cmdline", 0440);
+
     // Get the basic filesystem setup we need put together in the initramdisk
     // on / and then we'll let the rc file figure out the rest.
     if (is_first_stage) {
@@ -591,6 +690,7 @@
         mount("sysfs", "/sys", "sysfs", 0, NULL);
         mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
         mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
+        early_mount();
     }
 
     // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
@@ -643,6 +743,8 @@
     restorecon("/dev/__properties__");
     restorecon("/property_contexts");
     restorecon_recursive("/sys");
+    restorecon_recursive("/dev/block");
+    restorecon("/dev/device-mapper");
 
     epoll_fd = epoll_create1(EPOLL_CLOEXEC);
     if (epoll_fd == -1) {
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 4b498c1..ae38519 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -23,7 +23,6 @@
 #include <sys/mman.h>
 
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 #define LOG_TAG "CodeCache"
 #include <cutils/log.h>
 
@@ -101,7 +100,7 @@
 }
 
 Assembly::Assembly(size_t size)
-    : mCount(1), mSize(0)
+    : mCount(0), mSize(0)
 {
     mBase = (uint32_t*)mspace_malloc(getMspace(), size);
     LOG_ALWAYS_FATAL_IF(mBase == NULL,
@@ -117,12 +116,12 @@
 
 void Assembly::incStrong(const void*) const
 {
-    android_atomic_inc(&mCount);
+    mCount.fetch_add(1, std::memory_order_relaxed);
 }
 
 void Assembly::decStrong(const void*) const
 {
-    if (android_atomic_dec(&mCount) == 1) {
+    if (mCount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
         delete this;
     }
 }
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index c0e0684..9326453 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -19,6 +19,7 @@
 #ifndef ANDROID_CODECACHE_H
 #define ANDROID_CODECACHE_H
 
+#include <atomic>
 #include <stdint.h>
 #include <pthread.h>
 #include <sys/types.h>
@@ -69,7 +70,7 @@
     typedef void    weakref_type;
 
 private:
-    mutable int32_t     mCount;
+    mutable std::atomic<int32_t>     mCount;
             uint32_t*   mBase;
             size_t      mSize;
 };
diff --git a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
index 5f58797..63642c4 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
@@ -34,7 +34,6 @@
 
 #include <sys/mman.h>
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 
 #define __STDC_FORMAT_MACROS
 #include <inttypes.h>
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
index b680b60..e8c4626 100644
--- a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
@@ -34,7 +34,6 @@
 
 #include <sys/mman.h>
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 #include <cutils/log.h>
 
 #define __STDC_FORMAT_MACROS
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 1f27500..350be31 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -825,8 +825,9 @@
       // disk does not have enough space.
       result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
       if (result == -1 && errno == ENOSPC) {
-        ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
-              static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+        ALOGW("Zip: unable to allocate  %" PRId64 " bytes at offset %" PRId64 " : %s",
+              static_cast<int64_t>(declared_length), static_cast<int64_t>(current_offset),
+              strerror(errno));
         return std::unique_ptr<FileWriter>(nullptr);
       }
     }
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index da0aecc..c7506ef 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -26,6 +26,7 @@
 #include <syslog.h>
 
 #include <log/logger.h>
+#include <private/android_filesystem_config.h>
 
 #include "LogBuffer.h"
 #include "LogKlog.h"
@@ -614,7 +615,12 @@
     // Parse pid, tid and uid
     const pid_t pid = sniffPid(&p, len - (p - buf));
     const pid_t tid = pid;
-    const uid_t uid = pid ? logbuf->pidToUid(pid) : 0;
+    uid_t uid = AID_ROOT;
+    if (pid) {
+        logbuf->lock();
+        uid = logbuf->pidToUid(pid);
+        logbuf->unlock();
+    }
 
     // Parse (rules at top) to pull out a tag from the incoming kernel message.
     // Some may view the following as an ugly heuristic, the desire is to
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 70e0eca..d728f12 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -3,4 +3,5 @@
 alloc_dealloc_mismatch=0
 allocator_may_return_null=1
 detect_container_overflow=0
+abort_on_error=1
 include_if_exists=/system/asan.options.%b