Don't receive structs containing pointers over sockets.

Fixes x86-64 netd.

Change-Id: Iee5ef802ebbf2e000b2593643de4eec46f296c04
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 5443999..132a090 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -408,6 +408,15 @@
 	return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
 }
 
+bool readBE32(FILE* fp, int32_t* result) {
+  int32_t tmp;
+  if (fread(&tmp, sizeof(tmp), 1, fp) != 1) {
+    return false;
+  }
+  *result = ntohl(tmp);
+  return true;
+}
+
 // Returns 0 on success, else returns on error.
 static int
 android_getaddrinfo_proxy(
@@ -486,61 +495,62 @@
 	struct addrinfo* ai = NULL;
 	struct addrinfo** nextres = res;
 	while (1) {
-		uint32_t addrinfo_len;
-		if (fread(&addrinfo_len, sizeof(addrinfo_len),
-			  1, proxy) != 1) {
+		int32_t have_more;
+		if (!readBE32(proxy, &have_more)) {
 			break;
 		}
-		addrinfo_len = ntohl(addrinfo_len);
-		if (addrinfo_len == 0) {
+		if (have_more == 0) {
 			success = 1;
 			break;
 		}
 
-		if (addrinfo_len < sizeof(struct addrinfo)) {
-			break;
-		}
-		struct addrinfo* ai = calloc(1, addrinfo_len +
-					     sizeof(struct sockaddr_storage));
+		struct addrinfo* ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
 		if (ai == NULL) {
 			break;
 		}
+		ai->ai_addr = (struct sockaddr*)(ai + 1);
 
-		if (fread(ai, addrinfo_len, 1, proxy) != 1) {
-			// Error; fall through.
+		// 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 */
+		// };
+
+		// Read the struct piece by piece because we might be a 32-bit process
+		// talking to a 64-bit netd.
+		int32_t addr_len;
+		bool success =
+				readBE32(proxy, &ai->ai_flags) &&
+				readBE32(proxy, &ai->ai_family) &&
+				readBE32(proxy, &ai->ai_socktype) &&
+				readBE32(proxy, &ai->ai_protocol) &&
+				readBE32(proxy, &addr_len);
+		if (!success) {
 			break;
 		}
 
-		// Zero out the pointer fields we copied which aren't
-		// valid in this address space.
-		ai->ai_addr = NULL;
-		ai->ai_canonname = NULL;
-		ai->ai_next = NULL;
-
-		// struct sockaddr
-		uint32_t addr_len;
-		if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) {
-			break;
-		}
-		addr_len = ntohl(addr_len);
+		// Set ai_addrlen and read the ai_addr data.
+		ai->ai_addrlen = addr_len;
 		if (addr_len != 0) {
-			if (addr_len > sizeof(struct sockaddr_storage)) {
+			if ((size_t) addr_len > sizeof(struct sockaddr_storage)) {
 				// Bogus; too big.
 				break;
 			}
-			struct sockaddr* addr = (struct sockaddr*)(ai + 1);
-			if (fread(addr, addr_len, 1, proxy) != 1) {
+			if (fread(ai->ai_addr, addr_len, 1, proxy) != 1) {
 				break;
 			}
-			ai->ai_addr = addr;
 		}
 
-		// cannonname
-		uint32_t name_len;
-		if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
+		// The string for ai_cannonname.
+		int32_t name_len;
+		if (!readBE32(proxy, &name_len)) {
 			break;
 		}
-		name_len = ntohl(name_len);
 		if (name_len != 0) {
 			ai->ai_canonname = (char*) malloc(name_len);
 			if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) {