am d94bbc32: am 6bc08280: Validate sender credentials on netlink msg receive

* commit 'd94bbc326ab0e9ceca6f3f90a2864e40bb584c07':
  Validate sender credentials on netlink msg receive
diff --git a/adb/sockets.c b/adb/sockets.c
index 43925e4..aa4d5fc 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -569,6 +569,32 @@
     return n;
 }
 
+/* skip_host_serial return the position in a string
+   skipping over the 'serial' parameter in the ADB protocol,
+   where parameter string may be a host:port string containing
+   the protocol delimiter (colon). */
+char *skip_host_serial(char *service) {
+    char *first_colon, *serial_end;
+
+    first_colon = strchr(service, ':');
+    if (!first_colon) {
+        /* No colon in service string. */
+        return NULL;
+    }
+    serial_end = first_colon;
+    if (isdigit(serial_end[1])) {
+        serial_end++;
+        while ((*serial_end) && isdigit(*serial_end)) {
+            serial_end++;
+        }
+        if ((*serial_end) != ':') {
+            // Something other than numbers was found, reset the end.
+            serial_end = first_colon;
+        }
+    }
+    return serial_end;
+}
+
 static int smart_socket_enqueue(asocket *s, apacket *p)
 {
     unsigned len;
@@ -624,8 +650,8 @@
         char* serial_end;
         service += strlen("host-serial:");
 
-        // serial number should follow "host:"
-        serial_end = strchr(service, ':');
+        // serial number should follow "host:" and could be a host:port string.
+        serial_end = skip_host_serial(service);
         if (serial_end) {
             *serial_end = 0; // terminate string
             serial = service;
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 1db8065..f23c235 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -55,9 +55,10 @@
 #define AID_DRM           1019  /* DRM server */
 #define AID_AVAILABLE     1020  /* available for use */
 #define AID_GPS           1021  /* GPS daemon */
-#define AID_NFC           1022  /* nfc subsystem */
+#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */
 #define AID_MEDIA_RW      1023  /* internal media storage write access */
 #define AID_MTP           1024  /* MTP USB driver access */
+#define AID_NFC           1025  /* nfc subsystem */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index 2fcc331..d6bb7d5 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -19,6 +19,10 @@
     /* Peer group ID */
     gid_t mGid;
 
+    /* Reference count (starts at 1) */
+    pthread_mutex_t mRefCountMutex;
+    int mRefCount;
+
 public:
     SocketClient(int sock);
     virtual ~SocketClient() {}
@@ -34,6 +38,13 @@
 
     // Sending binary data:
     int sendData(const void *data, int len);
+
+    // Optional reference counting.  Reference count starts at 1.  If
+    // it's decremented to 0, it deletes itself.
+    // SocketListener creates a SocketClient (at refcount 1) and calls
+    // decRef() when it's done with the client.
+    void incRef();
+    bool decRef(); // returns true at 0 (but note: SocketClient already deleted)
 };
 
 typedef android::List<SocketClient *> SocketClientCollection;
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index a6aed26..90ca52e 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -15,8 +15,10 @@
         , mPid(-1)
         , mUid(-1)
         , mGid(-1)
+        , mRefCount(1)
 {
     pthread_mutex_init(&mWriteMutex, NULL);
+    pthread_mutex_init(&mRefCountMutex, NULL);
 
     struct ucred creds;
     socklen_t szCreds = sizeof(creds);
@@ -100,3 +102,25 @@
     pthread_mutex_unlock(&mWriteMutex);
     return 0;
 }
+
+void SocketClient::incRef() {
+    pthread_mutex_lock(&mRefCountMutex);
+    mRefCount++;
+    pthread_mutex_unlock(&mRefCountMutex);
+}
+
+bool SocketClient::decRef() {
+    bool deleteSelf = false;
+    pthread_mutex_lock(&mRefCountMutex);
+    mRefCount--;
+    if (mRefCount == 0) {
+        deleteSelf = true;
+    } else if (mRefCount < 0) {
+        SLOGE("SocketClient refcount went negative!");
+    }
+    pthread_mutex_unlock(&mRefCountMutex);
+    if (deleteSelf) {
+        delete this;
+    }
+    return deleteSelf;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 611d5fe..69ed79e 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -55,7 +55,7 @@
     }
     SocketClientCollection::iterator it;
     for (it = mClients->begin(); it != mClients->end();) {
-        delete (*it);
+        (*it)->decRef();
         it = mClients->erase(it);
     }
     delete mClients;
@@ -225,8 +225,11 @@
                 }
                 pthread_mutex_unlock(&mClientsLock);
                 /* Destroy the client */
-                close(c->getSocket());
-                delete c;
+                int socket = c->getSocket();
+                if (c->decRef()) {
+                    // Note: 'c' is deleted memory at this point.
+                    close(socket);
+                }
             }
         }
     }