File 1271-Verify-family-of-struct-addrinfo-replies.patch of Package erlang
From 1f7154fc5fb2ea1f8b532b79bb8adbcb597f344e Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Tue, 24 Aug 2021 17:20:57 +0200
Subject: [PATCH 1/2] Verify family of struct addrinfo replies
---
erts/etc/common/inet_gethost.c | 89 +++++++++++++++++++---------------
1 file changed, 50 insertions(+), 39 deletions(-)
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index 12012a056e..812f282aaa 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -324,8 +324,9 @@ static size_t build_error_reply(SerialType serial, int errnum,
AddrByte **preply,
size_t *preply_size);
#ifdef HAVE_GETADDRINFO
-static size_t build_reply_ai(SerialType serial, int, struct addrinfo *,
- AddrByte **preply, size_t *preply_size);
+static size_t build_reply_ai(SerialType serial, int, int,
+ struct addrinfo *,
+ AddrByte **preply, size_t *preply_size);
#endif
static size_t build_reply(SerialType serial, struct hostent *he,
AddrByte **preply, size_t *preply_size);
@@ -1821,7 +1822,7 @@ static int worker_loop(void)
#endif
#ifdef HAVE_GETADDRINFO
} else if (ai) {
- data_size = build_reply_ai(serial, 16, ai,
+ data_size = build_reply_ai(serial, AF_INET6, 16, ai,
&reply, &reply_size);
freeaddrinfo(ai);
#endif
@@ -1836,17 +1837,17 @@ static int worker_loop(void)
#ifdef HAVE_IN6
case PROTO_IPV6: {
#ifdef HAVE_GETNAMEINFO
- struct sockaddr_in6 *sin;
- socklen_t salen = sizeof(*sin);
+ struct sockaddr_in6 *sin6;
+ socklen_t salen = sizeof(*sin6);
- sin = ALLOC(salen);
+ sin6 = ALLOC(salen);
#ifndef NO_SA_LEN
- sin->sin6_len = salen;
+ sin6->sin6_len = salen;
#endif
- sin->sin6_family = AF_INET6;
- sin->sin6_port = 0;
- memcpy(&sin->sin6_addr, data, 16);
- sa = (struct sockaddr *)sin;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = 0;
+ memcpy(&sin6->sin6_addr, data, 16);
+ sa = (struct sockaddr *)sin6;
DEBUGF(5,("Starting getnameinfo(,,%s,16,,,)",
format_address(16, data)));
error_num = getnameinfo(sa, salen, name, sizeof(name),
@@ -1916,8 +1917,9 @@ static int worker_loop(void)
memset(&res, 0, sizeof(res));
res.ai_canonname = name;
res.ai_addr = sa;
+ res.ai_family = sa->sa_family;
res.ai_next = NULL;
- data_size = build_reply_ai(serial, 16, &res,
+ data_size = build_reply_ai(serial, AF_INET6, 16, &res,
&reply, &reply_size);
free(sa);
#endif
@@ -2144,7 +2146,8 @@ static size_t build_reply(SerialType serial, struct hostent *he,
}
#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO)
-static size_t build_reply_ai(SerialType serial, int addrlen,
+static size_t build_reply_ai(SerialType serial,
+ int family, int addrlen,
struct addrinfo *res0,
AddrByte **preply, size_t *preply_size)
{
@@ -2161,14 +2164,16 @@ static size_t build_reply_ai(SerialType serial, int addrlen,
4 /* Naddr */ + 4 /* Nnames */;
for (res = res0; res != NULL; res = res->ai_next) {
- if (res->ai_addr) {
- num_addresses++;
- need += addrlen;
- }
- if (res->ai_canonname) {
- num_strings++;
- need += strlen(res->ai_canonname) + 1;
- }
+ if ((res->ai_addr) &&
+ (res->ai_addr->sa_family == family)) {
+ num_addresses++;
+ need += addrlen;
+ }
+ if ((res->ai_canonname) &&
+ (res->ai_family == family)) {
+ num_strings++;
+ need += strlen(res->ai_canonname) + 1;
+ }
}
if (*preply_size < need) {
@@ -2188,28 +2193,34 @@ static size_t build_reply_ai(SerialType serial, int addrlen,
*ptr++ = (AddrByte) addrlen; /* 4 or 16 */
put_int32(ptr, num_addresses);
ptr += 4;
- for (res = res0; res != NULL && num_addresses; res = res->ai_next) {
- if (res->ai_addr == NULL)
- continue;
- if (addrlen == 4)
- memcpy(ptr, &((struct sockaddr_in *)res->ai_addr)->sin_addr, addrlen);
+ for (res = res0; res != NULL; res = res->ai_next) {
+ if ((res->ai_addr) &&
+ (res->ai_addr->sa_family == family)) {
+ const void *src;
+ switch (family) {
+ case AF_INET:
+ src = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ break;
#ifdef AF_INET6
- else if (addrlen == 16)
- memcpy(ptr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, addrlen);
+ case AF_INET6:
+ src = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+ break;
#endif
- else
- memcpy(ptr, res->ai_addr->sa_data, addrlen);
- ptr += addrlen;
- num_addresses--;
+ default:
+ src = res->ai_addr->sa_data;
+ }
+ memcpy(ptr, src, addrlen);
+ ptr += addrlen;
+ }
}
put_int32(ptr, num_strings);
ptr += 4;
- for (res = res0; res != NULL && num_strings; res = res->ai_next) {
- if (res->ai_canonname == NULL)
- continue;
- strcpy((char *)ptr, res->ai_canonname);
- ptr += strlen(res->ai_canonname) + 1;
- num_strings--;
+ for (res = res0; res != NULL; res = res->ai_next) {
+ if ((res->ai_canonname) &&
+ (res->ai_family == family)) {
+ strcpy((char *)ptr, res->ai_canonname);
+ ptr += strlen(res->ai_canonname) + 1;
+ }
}
return need;
}
--
2.31.1