From ab09bf616ad527b249aca5f2a4956fd526f0712f Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 18 Feb 2014 10:57:25 +0100 Subject: 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 --- resolv/nss_dns/dns-canon.c | 2 +- resolv/nss_dns/dns-host.c | 23 ++++++++++------------- resolv/nss_dns/dns-network.c | 4 ++-- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'resolv/nss_dns') diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c index a9db232..e8c112c 100644 --- a/resolv/nss_dns/dns-canon.c +++ b/resolv/nss_dns/dns-canon.c @@ -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. diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index 47f998c..a5f2c0a 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -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) { diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index b8aee21..0a77c8b 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -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. */ -- cgit v1.1