Merge "Add UID and directory for RELRO sharing support."
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index 7f85dc3..63000f2 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -240,3 +240,20 @@
     This starts the file synchronisation service, used to implement "adb push"
     and "adb pull". Since this service is pretty complex, it will be detailed
     in a companion document named SYNC.TXT
+
+reverse:<forward-command>
+    This implements the 'adb reverse' feature, i.e. the ability to reverse
+    socket connections from a device to the host. <forward-command> is one
+    of the forwarding commands that are described above, as in:
+
+      list-forward
+      forward:<local>;<remote>
+      forward:norebind:<local>;<remote>
+      killforward-all
+      killforward:<local>
+
+    Note that in this case, <local> corresponds to the socket on the device
+    and <remote> corresponds to the socket on the host.
+
+    The output of reverse:list-forward is the same as host:list-forward
+    except that <serial> will be just 'host'.
diff --git a/adb/adb.c b/adb/adb.c
index 0e41b34..8c1f005 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -318,7 +318,18 @@
 #endif
 }
 
-static void send_msg_with_okay(int fd, char* msg, size_t msglen) {
+#if !ADB_HOST
+static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
+    char header[5];
+    if (msglen > 0xffff)
+        msglen = 0xffff;
+    snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
+    writex(fd, header, 4);
+    writex(fd, msg, msglen);
+}
+#endif
+
+static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
     char header[9];
     if (msglen > 0xffff)
         msglen = 0xffff;
@@ -1428,6 +1439,120 @@
     return 0;
 }
 
+// Try to handle a network forwarding request.
+// This returns 1 on success, 0 on failure, and -1 to indicate this is not
+// a forwarding-related request.
+int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
+{
+    if (!strcmp(service, "list-forward")) {
+        // Create the list of forward redirections.
+        int buffer_size = format_listeners(NULL, 0);
+        // Add one byte for the trailing zero.
+        char* buffer = malloc(buffer_size + 1);
+        if (buffer == NULL) {
+            sendfailmsg(reply_fd, "not enough memory");
+            return 1;
+        }
+        (void) format_listeners(buffer, buffer_size + 1);
+#if ADB_HOST
+        send_msg_with_okay(reply_fd, buffer, buffer_size);
+#else
+        send_msg_with_header(reply_fd, buffer, buffer_size);
+#endif
+        free(buffer);
+        return 1;
+    }
+
+    if (!strcmp(service, "killforward-all")) {
+        remove_all_listeners();
+#if ADB_HOST
+        /* On the host: 1st OKAY is connect, 2nd OKAY is status */
+        adb_write(reply_fd, "OKAY", 4);
+#endif
+        adb_write(reply_fd, "OKAY", 4);
+        return 1;
+    }
+
+    if (!strncmp(service, "forward:",8) ||
+        !strncmp(service, "killforward:",12)) {
+        char *local, *remote, *err;
+        int r;
+        atransport *transport;
+
+        int createForward = strncmp(service, "kill", 4);
+        int no_rebind = 0;
+
+        local = strchr(service, ':') + 1;
+
+        // Handle forward:norebind:<local>... here
+        if (createForward && !strncmp(local, "norebind:", 9)) {
+            no_rebind = 1;
+            local = strchr(local, ':') + 1;
+        }
+
+        remote = strchr(local,';');
+
+        if (createForward) {
+            // Check forward: parameter format: '<local>;<remote>'
+            if(remote == 0) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+
+            *remote++ = 0;
+            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+        } else {
+            // Check killforward: parameter format: '<local>'
+            if (local[0] == 0) {
+                sendfailmsg(reply_fd, "malformed forward spec");
+                return 1;
+            }
+        }
+
+        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
+        if (!transport) {
+            sendfailmsg(reply_fd, err);
+            return 1;
+        }
+
+        if (createForward) {
+            r = install_listener(local, remote, transport, no_rebind);
+        } else {
+            r = remove_listener(local, transport);
+        }
+        if(r == 0) {
+#if ADB_HOST
+            /* On the host: 1st OKAY is connect, 2nd OKAY is status */
+            writex(reply_fd, "OKAY", 4);
+#endif
+            writex(reply_fd, "OKAY", 4);
+            return 1;
+        }
+
+        if (createForward) {
+            const char* message;
+            switch (r) {
+              case INSTALL_STATUS_CANNOT_BIND:
+                message = "cannot bind to socket";
+                break;
+              case INSTALL_STATUS_CANNOT_REBIND:
+                message = "cannot rebind existing socket";
+                break;
+              default:
+                message = "internal error";
+            }
+            sendfailmsg(reply_fd, message);
+        } else {
+            sendfailmsg(reply_fd, "cannot remove listener");
+        }
+        return 1;
+    }
+    return 0;
+}
+
 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
 {
     atransport *transport = NULL;
@@ -1548,97 +1673,9 @@
     }
 #endif // ADB_HOST
 
-    if(!strcmp(service,"list-forward")) {
-        // Create the list of forward redirections.
-        int buffer_size = format_listeners(NULL, 0);
-        // Add one byte for the trailing zero.
-        char* buffer = malloc(buffer_size+1);
-        (void) format_listeners(buffer, buffer_size+1);
-        send_msg_with_okay(reply_fd, buffer, buffer_size);
-        free(buffer);
-        return 0;
-    }
-
-    if (!strcmp(service,"killforward-all")) {
-        remove_all_listeners();
-        adb_write(reply_fd, "OKAYOKAY", 8);
-        return 0;
-    }
-
-    if(!strncmp(service,"forward:",8) ||
-       !strncmp(service,"killforward:",12)) {
-        char *local, *remote, *err;
-        int r;
-        atransport *transport;
-
-        int createForward = strncmp(service,"kill",4);
-        int no_rebind = 0;
-
-        local = strchr(service, ':') + 1;
-
-        // Handle forward:norebind:<local>... here
-        if (createForward && !strncmp(local, "norebind:", 9)) {
-            no_rebind = 1;
-            local = strchr(local, ':') + 1;
-        }
-
-        remote = strchr(local,';');
-
-        if (createForward) {
-            // Check forward: parameter format: '<local>;<remote>'
-            if(remote == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
-
-            *remote++ = 0;
-            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
-        } else {
-            // Check killforward: parameter format: '<local>'
-            if (local[0] == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
-        }
-
-        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
-        if (!transport) {
-            sendfailmsg(reply_fd, err);
-            return 0;
-        }
-
-        if (createForward) {
-            r = install_listener(local, remote, transport, no_rebind);
-        } else {
-            r = remove_listener(local, transport);
-        }
-        if(r == 0) {
-                /* 1st OKAY is connect, 2nd OKAY is status */
-            writex(reply_fd, "OKAYOKAY", 8);
-            return 0;
-        }
-
-        if (createForward) {
-            const char* message;
-            switch (r) {
-              case INSTALL_STATUS_CANNOT_BIND:
-                message = "cannot bind to socket";
-                break;
-              case INSTALL_STATUS_CANNOT_REBIND:
-                message = "cannot rebind existing socket";
-                break;
-              default:
-                message = "internal error";
-            }
-            sendfailmsg(reply_fd, message);
-        } else {
-            sendfailmsg(reply_fd, "cannot remove listener");
-        }
-        return 0;
-    }
+    int ret = handle_forward_request(service, ttype, serial, reply_fd);
+    if (ret >= 0)
+      return ret - 1;
 
     if(!strncmp(service,"get-state",strlen("get-state"))) {
         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
diff --git a/adb/adb.h b/adb/adb.h
index 6f5c93c..2504f99 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -323,6 +323,8 @@
 int       create_jdwp_connection_fd(int  jdwp_pid);
 #endif
 
+int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
+
 #if !ADB_HOST
 typedef enum {
     BACKUP,
diff --git a/adb/commandline.c b/adb/commandline.c
index 241cefc..3970ab1 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -136,6 +136,19 @@
         "                                 if <local> is already forwarded\n"
         "  adb forward --remove <local> - remove a specific forward socket connection\n"
         "  adb forward --remove-all     - remove all forward socket connections\n"
+        "  adb reverse --list           - list all reverse socket connections from device\n"
+        "  adb reverse <remote> <local> - reverse socket connections\n"
+        "                                 reverse specs are one of:\n"
+        "                                   tcp:<port>\n"
+        "                                   localabstract:<unix domain socket name>\n"
+        "                                   localreserved:<unix domain socket name>\n"
+        "                                   localfilesystem:<unix domain socket name>\n"
+        "  adb reverse --norebind <remote> <local>\n"
+        "                               - same as 'adb reverse <remote> <local>' but fails\n"
+        "                                 if <remote> is already reversed.\n"
+        "  adb reverse --remove <remote>\n"
+        "                               - remove a specific reversed socket connection\n"
+        "  adb reverse --remove-all     - remove all reversed socket connections from device\n"
         "  adb jdwp                     - list PIDs of processes hosting a JDWP transport\n"
         "  adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
         "                               - push this package file to the device and install it\n"
@@ -1299,8 +1312,11 @@
         return 0;
     }
 
-    if(!strcmp(argv[0], "forward")) {
+    if(!strcmp(argv[0], "forward") ||
+       !strcmp(argv[0], "reverse"))
+    {
         char host_prefix[64];
+        char reverse = (char) !strcmp(argv[0], "reverse");
         char remove = 0;
         char remove_all = 0;
         char list = 0;
@@ -1329,15 +1345,19 @@
         }
 
         // Determine the <host-prefix> for this command.
-        if (serial) {
-            snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
-                    serial);
-        } else if (ttype == kTransportUsb) {
-            snprintf(host_prefix, sizeof host_prefix, "host-usb");
-        } else if (ttype == kTransportLocal) {
-            snprintf(host_prefix, sizeof host_prefix, "host-local");
+        if (reverse) {
+            snprintf(host_prefix, sizeof host_prefix, "reverse");
         } else {
-            snprintf(host_prefix, sizeof host_prefix, "host");
+            if (serial) {
+                snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
+                        serial);
+            } else if (ttype == kTransportUsb) {
+                snprintf(host_prefix, sizeof host_prefix, "host-usb");
+            } else if (ttype == kTransportLocal) {
+                snprintf(host_prefix, sizeof host_prefix, "host-local");
+            } else {
+                snprintf(host_prefix, sizeof host_prefix, "host");
+            }
         }
 
         // Implement forward --list
diff --git a/adb/services.c b/adb/services.c
index 2d3423b..ebe84bb6 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -154,6 +154,17 @@
     adb_close(fd);
 }
 
+void reverse_service(int fd, void* arg)
+{
+    const char* command = arg;
+
+    if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
+        sendfailmsg(fd, "not a reverse forwarding command");
+    }
+    free(arg);
+    adb_close(fd);
+}
+
 #endif
 
 static int create_service_thread(void (*func)(int, void *), void *cookie)
@@ -398,6 +409,16 @@
         ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
     } else if(!strncmp(name, "usb:", 4)) {
         ret = create_service_thread(restart_usb_service, NULL);
+    } else if (!strncmp(name, "reverse:", 8)) {
+        char* cookie = strdup(name + 8);
+        if (cookie == NULL) {
+            ret = -1;
+        } else {
+            ret = create_service_thread(reverse_service, cookie);
+            if (ret < 0) {
+                free(cookie);
+            }
+        }
 #endif
     }
     if (ret >= 0) {
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 0357ced..c7e0ad5 100755
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -172,6 +172,8 @@
 #define VENDOR_ID_TI            0x0451
 // Toshiba's USB Vendor ID
 #define VENDOR_ID_TOSHIBA       0x0930
+// Unowhy's USB Vendor ID
+#define VENDOR_ID_UNOWHY        0x2A49
 // Vizio's USB Vendor ID
 #define VENDOR_ID_VIZIO         0xE040
 // Wacom's USB Vendor ID
@@ -257,6 +259,7 @@
     VENDOR_ID_TELEEPOCH,
     VENDOR_ID_TI,
     VENDOR_ID_TOSHIBA,
+    VENDOR_ID_UNOWHY,
     VENDOR_ID_VIZIO,
     VENDOR_ID_WACOM,
     VENDOR_ID_XIAOMI,
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 1a00146..cdaa09f 100755
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -583,7 +583,6 @@
 static void dump_logs(log_t* log, pid_t pid, unsigned tail) {
   dump_log_file(log, pid, "system", tail);
   dump_log_file(log, pid, "main", tail);
-  dump_log_file(log, pid, "events", tail);
 }
 
 static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t address) {
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index ed2c241..16fe7ee 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -633,11 +633,6 @@
             dev = dev->next = new log_device_t("crash", false, 'c');
             android::g_devCount++;
         }
-        if (android_name_to_log_id("events") == LOG_ID_EVENTS) {
-            dev = dev->next = new log_device_t("events", true, 'e');
-            android::g_devCount++;
-            needBinary = true;
-        }
     }
 
     if (android::g_logRotateSizeKBytes != 0
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 0651a92..f8d6162 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -70,6 +70,11 @@
         return rc;
     }
 
+    char *cp;
+    while ((cp = strstr(str, "  "))) {
+        memmove(cp, cp + 1, strlen(cp + 1) + 1);
+    }
+
     if (fdDmesg >= 0) {
         struct iovec iov[2];
 
@@ -88,12 +93,11 @@
 
     static const char audit_str[] = " audit(";
     char *timeptr = strstr(str, audit_str);
-    char *cp;
     if (timeptr
             && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q")))
             && (*cp == ':')) {
         memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
-        strcpy(timeptr + sizeof(audit_str) - 1 + 3, cp);
+        memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
     } else {
         now.strptime("", ""); // side effect of setting CLOCK_REALTIME
     }
@@ -109,37 +113,88 @@
         }
         tid = pid;
         uid = logbuf->pidToUid(pid);
-        strcpy(pidptr, cp);
+        memmove(pidptr, cp, strlen(cp) + 1);
     }
 
-    size_t n = strlen(str);
-    n += sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
+    // log to events
+
+    size_t l = strlen(str);
+    size_t n = l + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
+
+    bool notify = false;
 
     char *newstr = reinterpret_cast<char *>(malloc(n));
     if (!newstr) {
-        free(str);
-        return -ENOMEM;
+        rc = -ENOMEM;
+    } else {
+        cp = newstr;
+        *cp++ = AUDITD_LOG_TAG & 0xFF;
+        *cp++ = (AUDITD_LOG_TAG >> 8) & 0xFF;
+        *cp++ = (AUDITD_LOG_TAG >> 16) & 0xFF;
+        *cp++ = (AUDITD_LOG_TAG >> 24) & 0xFF;
+        *cp++ = EVENT_TYPE_STRING;
+        *cp++ = l & 0xFF;
+        *cp++ = (l >> 8) & 0xFF;
+        *cp++ = (l >> 16) & 0xFF;
+        *cp++ = (l >> 24) & 0xFF;
+        memcpy(cp, str, l);
+
+        logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr,
+                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        free(newstr);
+
+        notify = true;
     }
 
-    char *msg = newstr;
-    *msg++ = AUDITD_LOG_TAG & 0xFF;
-    *msg++ = (AUDITD_LOG_TAG >> 8) & 0xFF;
-    *msg++ = (AUDITD_LOG_TAG >> 16) & 0xFF;
-    *msg++ = (AUDITD_LOG_TAG >> 24) & 0xFF;
-    *msg++ = EVENT_TYPE_STRING;
-    size_t l = n - sizeof(uint32_t) - sizeof(uint8_t) - sizeof(uint32_t);
-    *msg++ = l & 0xFF;
-    *msg++ = (l >> 8) & 0xFF;
-    *msg++ = (l >> 16) & 0xFF;
-    *msg++ = (l >> 24) & 0xFF;
-    memcpy(msg, str, l);
+    // log to main
+
+    static const char comm_str[] = " comm=\"";
+    const char *comm = strstr(str, comm_str);
+    const char *estr = str + strlen(str);
+    if (comm) {
+        estr = comm;
+        comm += sizeof(comm_str) - 1;
+    } else if (pid == getpid()) {
+        pid = tid;
+        comm = "auditd";
+    } else if (!(comm = logbuf->pidToName(pid))) {
+        comm = "unknown";
+    }
+
+    const char *ecomm = strchr(comm, '"');
+    if (ecomm) {
+        ++ecomm;
+        l = ecomm - comm;
+    } else {
+        l = strlen(comm) + 1;
+        ecomm = "";
+    }
+    n = (estr - str) + strlen(ecomm) + l + 2;
+
+    newstr = reinterpret_cast<char *>(malloc(n));
+    if (!newstr) {
+        rc = -ENOMEM;
+    } else {
+        *newstr = (strstr(str, " permissive=1")
+                || strstr(str, " policy loaded "))
+                    ? ANDROID_LOG_INFO
+                    : ANDROID_LOG_WARN;
+        strlcpy(newstr + 1, comm, l);
+        strncpy(newstr + 1 + l, str, estr - str);
+        strcpy(newstr + 1 + l + (estr - str), ecomm);
+
+        logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
+                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        free(newstr);
+
+        notify = true;
+    }
+
     free(str);
 
-    logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr,
-                (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
-    reader->notifyNewLog();
-
-    free(newstr);
+    if (notify) {
+        reader->notifyNewLog();
+    }
 
     return rc;
 }