OSDN Git Service

Prevent potential stall on dns proxy operations.
authorSelim Gurun <sgurun@google.com>
Mon, 27 Feb 2012 23:58:54 +0000 (15:58 -0800)
committerSelim Gurun <sgurun@google.com>
Wed, 7 Mar 2012 23:09:05 +0000 (15:09 -0800)
Update wire protocol to return and process error code first.
This will make sure dns proxy operations do not stall when
an internal error happens.
Also fix a compiler warning.
Also fix a potential buffer overflow.
And use correct types (uint32_t) rather than int when reading from network.

Change-Id: I9f99c16d6fd5e9137491a4d1b293a7c78e31b9c3

libc/netbsd/net/getaddrinfo.c
libc/netbsd/net/getnameinfo.c

index 6ae6e3e..7dd65ff 100644 (file)
@@ -130,6 +130,9 @@ static const char in6_loopback[] = {
 };
 #endif
 
+// This should be synchronized to ResponseCode.h
+static const int DnsProxyQueryResult = 222;
+
 static const struct afd {
        int a_af;
        int a_addrlen;
@@ -476,12 +479,15 @@ android_getaddrinfo_proxy(
                goto exit;
        }
 
-       int remote_rv;
-       if (fread(&remote_rv, sizeof(int), 1, proxy) != 1) {
+       char buf[5];
+       // read result code for gethostbyaddr
+       if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) {
                goto exit;
        }
 
-       if (remote_rv != 0) {
+       int result_code = (int)strtol(buf, NULL, 10);
+       // verify the code itself
+       if (result_code != DnsProxyQueryResult ) {
                goto exit;
        }
 
index d3d0011..eed23a7 100644 (file)
@@ -108,6 +108,10 @@ static int getnameinfo_link __P((const struct sockaddr *, socklen_t, char *,
     socklen_t, char *, socklen_t, int));
 static int hexname __P((const u_int8_t *, size_t, char *, socklen_t));
 
+// This should be synchronized to ResponseCode.h
+static const int DnsProxyQueryResult = 222;
+
+
 /*
  * Top-level getnameinfo() code.  Look at the address family, and pick an
  * appropriate function to call.
@@ -135,7 +139,7 @@ int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t h
  * the address. On failure -1 is returned in which case
  * normal execution flow shall continue. */
 static int
-android_gethostbyaddr_proxy(struct hostent* hp, const void *addr, socklen_t addrLen, int addrFamily) {
+android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily) {
 
        int sock;
        const int one = 1;
@@ -183,7 +187,7 @@ android_gethostbyaddr_proxy(struct hostent* hp, const void *addr, socklen_t addr
        }
 
        char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6
-       const char* addrStr = inet_ntop(addrFamily, addr, &buf, sizeof(buf));
+       const char* addrStr = inet_ntop(addrFamily, addr, buf, sizeof(buf));
        if (addrStr == NULL) {
                goto exit;
        }
@@ -197,17 +201,29 @@ android_gethostbyaddr_proxy(struct hostent* hp, const void *addr, socklen_t addr
        }
 
        result = 0;
+       char msg_buf[5];
+       // read result code for gethostbyaddr
+       if (fread(msg_buf, 1, sizeof(msg_buf), proxy) != sizeof(msg_buf)) {
+               goto exit;
+       }
+
+       int result_code = (int)strtol(msg_buf, NULL, 10);
+       // verify the code itself
+       if (result_code != DnsProxyQueryResult) {
+               goto exit;
+       }
+
        uint32_t name_len;
        if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
                goto exit;
        }
 
        name_len = ntohl(name_len);
-       if (name_len <= 0) {
+       if (name_len <= 0 || name_len >= nameBufLen) {
                goto exit;
        }
 
-       if (fread(hp->h_name, name_len, 1, proxy) != 1) {
+       if (fread(nameBuf, name_len, 1, proxy) != 1) {
                goto exit;
        }
 
@@ -376,12 +392,14 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags)
 #ifdef ANDROID_CHANGES
                struct hostent android_proxy_hostent;
                char android_proxy_buf[MAXDNAME];
-               android_proxy_hostent.h_name = android_proxy_buf;
 
-               int hostnamelen = android_gethostbyaddr_proxy(&android_proxy_hostent,
-                               addr, afd->a_addrlen, afd->a_af);
-               if (hostnamelen >= 0) {
-                       hp = (hostnamelen > 0) ? &android_proxy_hostent : NULL;
+               int hostnamelen = android_gethostbyaddr_proxy(android_proxy_buf,
+                               MAXDNAME, addr, afd->a_addrlen, afd->a_af);
+               if (hostnamelen > 0) {
+                       hp = &android_proxy_hostent;
+                       hp->h_name = android_proxy_buf;
+               } else if (!hostnamelen) {
+                       hp = NULL;
                } else {
                        hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
                }