Don't receive structs containing pointers over sockets.

Fixes x86-64 netd.

Change-Id: Iee5ef802ebbf2e000b2593643de4eec46f296c04
This commit is contained in:
Elliott Hughes 2014-11-12 17:00:30 -08:00
parent 5d05d025b5
commit 55293c1dad

View File

@ -408,6 +408,15 @@ _have_ipv4(unsigned mark) {
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 @@ android_getaddrinfo_proxy(
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) {