OSDN Git Service

Don't send structs containing pointers over sockets.
authorElliott Hughes <enh@google.com>
Thu, 13 Nov 2014 01:01:46 +0000 (17:01 -0800)
committerElliott Hughes <enh@google.com>
Thu, 13 Nov 2014 06:10:21 +0000 (22:10 -0800)
Fixes x86-64 netd.

Change-Id: Iee5ef802ebbf2e000b2593643de4eec46f296c04

server/DnsProxyListener.cpp

index 6e27057..a0f0a30 100644 (file)
@@ -83,12 +83,15 @@ void* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) {
     return NULL;
 }
 
+static bool sendBE32(SocketClient* c, uint32_t data) {
+    uint32_t be_data = htonl(data);
+    return c->sendData(&be_data, sizeof(be_data)) == 0;
+}
+
 // Sends 4 bytes of big-endian length, followed by the data.
 // Returns true on success.
-static bool sendLenAndData(SocketClient *c, const int len, const void* data) {
-    uint32_t len_be = htonl(len);
-    return c->sendData(&len_be, 4) == 0 &&
-        (len == 0 || c->sendData(data, len) == 0);
+static bool sendLenAndData(SocketClient* c, const int len, const void* data) {
+    return sendBE32(c, len) && (len == 0 || c->sendData(data, len) == 0);
 }
 
 // Returns true on success
@@ -119,6 +122,42 @@ static bool sendhostent(SocketClient *c, struct hostent *hp) {
     return success;
 }
 
+static bool sendaddrinfo(SocketClient* c, struct addrinfo* ai) {
+    // struct addrinfo {
+    //      int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+    //      int     ai_family;      /* PF_xxx */
+    //      int     ai_socktype;    /* SOCK_xxx */
+    //      int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+    //      socklen_t ai_addrlen;   /* length of ai_addr */
+    //      char    *ai_canonname;  /* canonical name for hostname */
+    //      struct  sockaddr *ai_addr;      /* binary address */
+    //      struct  addrinfo *ai_next;      /* next structure in linked list */
+    // };
+
+    // Write the struct piece by piece because we might be a 64-bit netd
+    // talking to a 32-bit process.
+    bool success =
+            sendBE32(c, ai->ai_flags) &&
+            sendBE32(c, ai->ai_family) &&
+            sendBE32(c, ai->ai_socktype) &&
+            sendBE32(c, ai->ai_protocol);
+    if (!success) {
+        return false;
+    }
+
+    // ai_addrlen and ai_addr.
+    if (!sendLenAndData(c, ai->ai_addrlen, ai->ai_addr)) {
+        return false;
+    }
+
+    // strlen(ai_canonname) and ai_canonname.
+    if (!sendLenAndData(c, ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, ai->ai_canonname)) {
+        return false;
+    }
+
+    return true;
+}
+
 void DnsProxyListener::GetAddrInfoHandler::run() {
     if (DBG) {
         ALOGD("GetAddrInfoHandler, now for %s / %s / %u / %u", mHost, mService, mNetId, mMark);
@@ -133,14 +172,10 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
         bool success = !mClient->sendCode(ResponseCode::DnsProxyQueryResult);
         struct addrinfo* ai = result;
         while (ai && success) {
-            success = sendLenAndData(mClient, sizeof(struct addrinfo), ai)
-                && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr)
-                && sendLenAndData(mClient,
-                                  ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0,
-                                  ai->ai_canonname);
+            success = sendBE32(mClient, 1) && sendaddrinfo(mClient, ai);
             ai = ai->ai_next;
         }
-        success = success && sendLenAndData(mClient, 0, "");
+        success = success && sendBE32(mClient, 0);
         if (!success) {
             ALOGW("Error writing DNS result to client");
         }