1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-01 10:06:57 +03:00

Properly fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer

Instead of trying to guess whether the second buffer needs to be freed
set a flag at the place it is allocated
This commit is contained in:
Andreas Schwab
2014-02-18 10:57:25 +01:00
parent c6af2d896c
commit ab09bf616a
8 changed files with 95 additions and 49 deletions

View File

@ -62,7 +62,7 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
{
int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
buf, sizeof (buf), &ansp.ptr, NULL, NULL,
NULL);
NULL, NULL);
if (r > 0)
{
/* We need to decode the response. Just one question record.

View File

@ -190,7 +190,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
1024, &host_buffer.ptr, NULL, NULL, NULL);
1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0)
{
switch (errno)
@ -225,7 +225,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
? MAXPACKET : 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (n < 0)
{
@ -298,23 +298,23 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
name = cp;
}
int anslen = 2048;
union
{
querybuf *buf;
u_char *ptr;
} host_buffer;
querybuf *orig_host_buffer;
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (anslen);
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
u_char *ans2p = NULL;
int nans2p = 0;
int resplen2 = 0;
int ans2p_malloced = 0;
int olderr = errno;
enum nss_status status;
int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
host_buffer.buf->buf, anslen, &host_buffer.ptr,
&ans2p, &nans2p, &resplen2);
host_buffer.buf->buf, 2048, &host_buffer.ptr,
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
if (n >= 0)
{
status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
@ -351,10 +351,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
}
/* Check whether ans2p was separately allocated. */
if (host_buffer.buf != orig_host_buffer)
anslen = MAXPACKET;
if (ans2p != NULL
&& (ans2p < host_buffer.ptr || ans2p >= host_buffer.ptr + anslen))
if (ans2p_malloced)
free (ans2p);
if (host_buffer.buf != orig_host_buffer)
@ -465,7 +462,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
strcpy (qp, "].ip6.arpa");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR,
host_buffer.buf->buf, 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (n >= 0)
goto got_it_already;
}
@ -486,14 +483,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
}
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
1024, &host_buffer.ptr, NULL, NULL, NULL);
1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0)
{
strcpy (qp, "ip6.int");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
? MAXPACKET : 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
}
if (n < 0)
{

View File

@ -129,7 +129,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
1024, &net_buffer.ptr, NULL, NULL, NULL);
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
@ -205,7 +205,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
1024, &net_buffer.ptr, NULL, NULL, NULL);
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */