8597553f96
- Support an arbitrary number of search domains (#168253) - Detect and apply /etc/resolv.conf changes in libresolv (#1374239) - CVE-2015-5180: DNS stub resolver crash with crafted record type (#1251403)
171 lines
5.2 KiB
Diff
171 lines
5.2 KiB
Diff
commit 673cb072a4710bd4bf6029a062d2867cca929c43
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Fri Jun 2 14:54:56 2017 +0200
|
|
|
|
getaddrinfo: Always allocate canonical name on the heap
|
|
|
|
A further simplification could eliminate the canon variable in
|
|
gaih_inet and replace it with canonbuf. However, canonbuf is
|
|
used as a flag in the nscd code, which makes this somewhat
|
|
non-straightforward.
|
|
|
|
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
|
index 987a1c1e17f2d5b1..daa742c260e667a7 100644
|
|
--- a/sysdeps/posix/getaddrinfo.c
|
|
+++ b/sysdeps/posix/getaddrinfo.c
|
|
@@ -308,6 +308,30 @@ typedef enum nss_status (*nss_getcanonname_r)
|
|
int *errnop, int *h_errnop);
|
|
extern service_user *__nss_hosts_database attribute_hidden;
|
|
|
|
+/* This function is called if a canonical name is requested, but if
|
|
+ the service function did not provide it. It tries to obtain the
|
|
+ name using getcanonname_r from the same service NIP. If the name
|
|
+ cannot be canonicalized, return a copy of NAME. Return NULL on
|
|
+ memory allocation failure. The returned string is allocated on the
|
|
+ heap; the caller has to free it. */
|
|
+static char *
|
|
+getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name)
|
|
+{
|
|
+ nss_getcanonname_r cfct = __nss_lookup_function (nip, "getcanonname_r");
|
|
+ char *s = (char *) name;
|
|
+ if (cfct != NULL)
|
|
+ {
|
|
+ char buf[256];
|
|
+ int herrno;
|
|
+ int rc;
|
|
+ if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
|
|
+ &s, &rc, &herrno)) != NSS_STATUS_SUCCESS)
|
|
+ /* If the canonical name cannot be determined, use the passed
|
|
+ string. */
|
|
+ s = (char *) name;
|
|
+ }
|
|
+ return strdup (name);
|
|
+}
|
|
|
|
static int
|
|
gaih_inet (const char *name, const struct gaih_service *service,
|
|
@@ -443,7 +467,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
|
|
|
bool malloc_name = false;
|
|
struct gaih_addrtuple *addrmem = NULL;
|
|
- bool malloc_canonbuf = false;
|
|
char *canonbuf = NULL;
|
|
int result = 0;
|
|
|
|
@@ -702,22 +725,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
|
(*pat)->name = NULL;
|
|
else if (canonbuf == NULL)
|
|
{
|
|
- size_t canonlen = strlen (air->canon) + 1;
|
|
- if ((req->ai_flags & AI_CANONIDN) != 0
|
|
- && __libc_use_alloca (alloca_used + canonlen))
|
|
- canonbuf = alloca_account (canonlen, alloca_used);
|
|
- else
|
|
+ canonbuf = strdup (air->canon);
|
|
+ if (canonbuf == NULL)
|
|
{
|
|
- canonbuf = malloc (canonlen);
|
|
- if (canonbuf == NULL)
|
|
- {
|
|
- result = -EAI_MEMORY;
|
|
- goto free_and_return;
|
|
- }
|
|
- malloc_canonbuf = true;
|
|
+ result = -EAI_MEMORY;
|
|
+ goto free_and_return;
|
|
}
|
|
- canon = (*pat)->name = memcpy (canonbuf, air->canon,
|
|
- canonlen);
|
|
+ canon = (*pat)->name = canonbuf;
|
|
}
|
|
|
|
if (air->family[i] == AF_INET
|
|
@@ -924,55 +938,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
|
if ((req->ai_flags & AI_CANONNAME) != 0
|
|
&& canon == NULL)
|
|
{
|
|
- /* If we need the canonical name, get it
|
|
- from the same service as the result. */
|
|
- nss_getcanonname_r cfct;
|
|
- int herrno;
|
|
-
|
|
- cfct = __nss_lookup_function (nip,
|
|
- "getcanonname_r");
|
|
- if (cfct != NULL)
|
|
+ canonbuf = getcanonname (nip, at, name);
|
|
+ if (canonbuf == NULL)
|
|
{
|
|
- const size_t max_fqdn_len = 256;
|
|
- if ((req->ai_flags & AI_CANONIDN) != 0
|
|
- && __libc_use_alloca (alloca_used
|
|
- + max_fqdn_len))
|
|
- canonbuf = alloca_account (max_fqdn_len,
|
|
- alloca_used);
|
|
- else
|
|
- {
|
|
- canonbuf = malloc (max_fqdn_len);
|
|
- if (canonbuf == NULL)
|
|
- {
|
|
- _res.options
|
|
- |= old_res_options
|
|
- & DEPRECATED_RES_USE_INET6;
|
|
- result = -EAI_MEMORY;
|
|
- goto free_and_return;
|
|
- }
|
|
- malloc_canonbuf = true;
|
|
- }
|
|
- char *s;
|
|
-
|
|
- if (DL_CALL_FCT (cfct, (at->name ?: name,
|
|
- canonbuf,
|
|
- max_fqdn_len,
|
|
- &s, &rc, &herrno))
|
|
- == NSS_STATUS_SUCCESS)
|
|
- canon = s;
|
|
- else
|
|
- {
|
|
- /* If the canonical name cannot be
|
|
- determined, use the passed in
|
|
- string. */
|
|
- if (malloc_canonbuf)
|
|
- {
|
|
- free (canonbuf);
|
|
- malloc_canonbuf = false;
|
|
- }
|
|
- canon = name;
|
|
- }
|
|
+ _res.options
|
|
+ |= old_res_options
|
|
+ & DEPRECATED_RES_USE_INET6;
|
|
+ result = -EAI_MEMORY;
|
|
+ goto free_and_return;
|
|
}
|
|
+ canon = canonbuf;
|
|
}
|
|
status = NSS_STATUS_SUCCESS;
|
|
}
|
|
@@ -1118,9 +1093,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
|
#ifdef HAVE_LIBIDN
|
|
make_copy:
|
|
#endif
|
|
- if (malloc_canonbuf)
|
|
- /* We already allocated the string using malloc. */
|
|
- malloc_canonbuf = false;
|
|
+ if (canonbuf != NULL)
|
|
+ /* We already allocated the string using malloc, but
|
|
+ the buffer is now owned by canon. */
|
|
+ canonbuf = NULL;
|
|
else
|
|
{
|
|
canon = strdup (canon);
|
|
@@ -1215,8 +1191,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
|
if (malloc_name)
|
|
free ((char *) name);
|
|
free (addrmem);
|
|
- if (malloc_canonbuf)
|
|
- free (canonbuf);
|
|
+ free (canonbuf);
|
|
|
|
return result;
|
|
}
|