gethtbyaddr: Reserve space for mapping IPv4 address to IPv6 address
Currently function return address space size is reserved by the address family.
If Netd does reverse DNS query with synthesized IPv6 address failed, Netd
does fallback to try IPv4 DNS query without NAT64 prefix. When Netd receives
answers, hostname and IPv4 address, from hostent structure function returned,
Netd maps the return address from IPv4 to IPv6 in the place. Reserving enough
address space for either IPv4 or IPv6 avoids buffer overflow while doing
address family remapping in Netd.
Bug: 78545619
Test: netd_{unit,integration}_test pass
Change-Id: I69035d1c81b70058d9240c2bad02b80a9883bce3
diff --git a/resolv/gethnamaddr.cpp b/resolv/gethnamaddr.cpp
index dfed7a9..ac6a525 100644
--- a/resolv/gethnamaddr.cpp
+++ b/resolv/gethnamaddr.cpp
@@ -78,6 +78,8 @@
// that they don't actually test or ship with this.
#define _DIAGASSERT(e) /* nothing */
+// TODO: unify macro ALIGNBYTES and ALIGN for all possible data type alignment of hostent
+// buffer.
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
@@ -778,6 +780,11 @@
HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, buflen);
hent->h_addr_list[1] = NULL;
+ /* Reserve space for mapping IPv4 address to IPv6 address in place */
+ if (hent->h_addrtype == AF_INET) {
+ HENT_COPY(buf, NAT64_PAD, sizeof(NAT64_PAD), buf, buflen);
+ }
+
HENT_SCOPY(hent->h_name, name, buf, buflen);
for (size_t i = 0; i < anum; i++) HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
hent->h_aliases[anum] = NULL;
@@ -997,6 +1004,13 @@
hp->h_length = NS_IN6ADDRSZ;
}
+ /* Reserve enough space for mapping IPv4 address to IPv6 address in place */
+ if (info->hp->h_addrtype == AF_INET) {
+ if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
+ // Pad zero to the unused address space
+ memcpy(bf + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD));
+ }
+
res_put_state(res);
*info->he = NETDB_SUCCESS;
return true;