[glibc] 01/03: patches/any/cvs-gethostbyname4-memory-leak.diff: new patch from upstream to fix a memory leak in _nss_dns_gethostbyname4_r with big DNS answers.
This is an automated email from the git hooks/post-receive script.
aurel32 pushed a commit to branch wheezy
in repository glibc.
commit 61200ac9d6700a13ad561676ac20861ed8e82b2f
Author: Aurelien Jarno <aurelien@aurel32.net>
Date: Mon Feb 1 09:55:01 2016 +0100
patches/any/cvs-gethostbyname4-memory-leak.diff: new patch from upstream to fix a memory leak in _nss_dns_gethostbyname4_r with big DNS answers.
---
debian/changelog | 3 +
.../any/cvs-gethostbyname4-memory-leak.diff | 447 +++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 451 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 62a7344..7e23804 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,9 @@ eglibc (2.13-38+deb7u10) UNRELEASED; urgency=medium
* patches/any/cvs-catopen.diff: new patch from upstream to fix multiple
unbounded stack allocations in catopen() (CVE-2015-8779). Closes:
#812455.
+ * patches/any/cvs-gethostbyname4-memory-leak.diff: new patch from
+ upstream to fix a memory leak in _nss_dns_gethostbyname4_r with big
+ DNS answers.
-- Aurelien Jarno <aurel32@debian.org> Sun, 31 Jan 2016 12:55:29 +0100
diff --git a/debian/patches/any/cvs-gethostbyname4-memory-leak.diff b/debian/patches/any/cvs-gethostbyname4-memory-leak.diff
new file mode 100644
index 0000000..15eb6eb
--- /dev/null
+++ b/debian/patches/any/cvs-gethostbyname4-memory-leak.diff
@@ -0,0 +1,447 @@
+2014-02-18 Andreas Schwab <schwab@suse.de>
+
+ [BZ #16574]
+ * resolv/res_send.c (send_vc): Add parameter ansp2_malloced.
+ Store non-zero if the second buffer was newly allocated.
+ (send_dg): Likewise.
+ (__libc_res_nsend): Add parameter ansp2_malloced and pass it down
+ to send_vc and send_dg.
+ (res_nsend): Pass NULL for ansp2_malloced.
+ * resolv/res_query.c (__libc_res_nquery): Add parameter
+ answerp2_malloced and pass it down to __libc_res_nsend.
+ (res_nquery): Pass additional NULL to __libc_res_nquery.
+ (__libc_res_nsearch): Add parameter answerp2_malloced and pass it
+ down to __libc_res_nquery and __libc_res_nquerydomain. Deallocate
+ second answer buffer if answerp2_malloced was set.
+ (res_nsearch): Pass additional NULL to __libc_res_nsearch.
+ (__libc_res_nquerydomain): Add parameter
+ answerp2_malloced and pass it down to __libc_res_nquery.
+ (res_nquerydomain): Pass additional NULL to
+ __libc_res_nquerydomain.
+ * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Pass
+ additional NULL to __libc_res_nsend and __libc_res_nquery.
+ * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname3_r): Pass
+ additional NULL to __libc_res_nsearch.
+ (_nss_dns_gethostbyname4_r): Revert last change. Use new
+ parameter of __libc_res_nsearch to check for separately allocated
+ second buffer.
+ (_nss_dns_gethostbyaddr2_r): Pass additional NULL to
+ __libc_res_nquery.
+ * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Pass
+ additional NULL to __libc_res_nquery.
+ * resolv/gethnamaddr.c (gethostbyname2): Pass additional NULL to
+ __libc_res_nsearch.
+ (gethostbyaddr): Pass additional NULL to __libc_res_nquery.
+ * include/resolv.h: Update prototypes of __libc_res_nquery,
+ __libc_res_nsearch, __libc_res_nsend.
+
+2014-02-13 Andreas Schwab <schwab@suse.de>
+
+ [BZ #16574]
+ * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Free the
+ second answer buffer if it was separately allocated.
+
+--- a/include/resolv.h
++++ b/include/resolv.h
+@@ -58,11 +58,11 @@
+ libc_hidden_proto (__res_state)
+
+ int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
+- u_char **, u_char **, int *, int *);
++ u_char **, u_char **, int *, int *, int *);
+ int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
+- u_char **, u_char **, int *, int *);
++ u_char **, u_char **, int *, int *, int *);
+ int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
+- u_char *, int, u_char **, u_char **, int *, int *)
++ u_char *, int, u_char **, u_char **, int *, int *, int *)
+ attribute_hidden;
+
+ libresolv_hidden_proto (_sethtent)
+--- a/resolv/gethnamaddr.c
++++ b/resolv/gethnamaddr.c
+@@ -621,7 +621,7 @@
+ buf.buf = origbuf = (querybuf *) alloca (1024);
+
+ if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
+- &buf.ptr, NULL, NULL, NULL)) < 0) {
++ &buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
+ if (buf.buf != origbuf)
+ free (buf.buf);
+ Dprintf("res_nsearch failed (%d)\n", n);
+@@ -716,12 +716,12 @@
+ buf.buf = orig_buf = (querybuf *) alloca (1024);
+
+ n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
+- &buf.ptr, NULL, NULL, NULL);
++ &buf.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, buf.buf->buf,
+ buf.buf != orig_buf ? MAXPACKET : 1024,
+- &buf.ptr, NULL, NULL, NULL);
++ &buf.ptr, NULL, NULL, NULL, NULL);
+ }
+ if (n < 0) {
+ if (buf.buf != orig_buf)
+--- a/resolv/nss_dns/dns-canon.c
++++ b/resolv/nss_dns/dns-canon.c
+@@ -62,7 +62,7 @@
+ {
+ 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.
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -195,7 +195,7 @@
+ 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 @@
+ 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)
+ {
+@@ -308,12 +308,13 @@
+ 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, 2048, &host_buffer.ptr,
+- &ans2p, &nans2p, &resplen2);
++ &ans2p, &nans2p, &resplen2, &ans2p_malloced);
+ if (n < 0)
+ {
+ if (errno == ESRCH)
+@@ -340,6 +341,10 @@
+ resplen2, name, pat, buffer, buflen,
+ errnop, herrnop, ttlp);
+
++ /* Check whether ans2p was separately allocated. */
++ if (ans2p_malloced)
++ free (ans2p);
++
+ if (host_buffer.buf != orig_host_buffer)
+ free (host_buffer.buf);
+
+@@ -448,7 +453,7 @@
+ 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;
+ }
+@@ -469,14 +474,14 @@
+ }
+
+ 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)
+ {
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -130,7 +130,7 @@
+ 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. */
+@@ -206,7 +206,7 @@
+ 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. */
+--- a/resolv/res_query.c
++++ b/resolv/res_query.c
+@@ -98,7 +98,7 @@
+ __libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
+ int class, int type, u_char *answer, int anslen,
+ u_char **answerp, u_char **answerp2, int *nanswerp2,
+- int *resplen2);
++ int *resplen2, int *answerp2_malloced);
+
+ /*
+ * Formulate a normal query, send, and await answer.
+@@ -119,7 +119,8 @@
+ u_char **answerp, /* if buffer needs to be enlarged */
+ u_char **answerp2,
+ int *nanswerp2,
+- int *resplen2)
++ int *resplen2,
++ int *answerp2_malloced)
+ {
+ HEADER *hp = (HEADER *) answer;
+ HEADER *hp2;
+@@ -224,7 +225,8 @@
+ }
+ assert (answerp == NULL || (void *) *answerp == (void *) answer);
+ n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
+- anslen, answerp, answerp2, nanswerp2, resplen2);
++ anslen, answerp, answerp2, nanswerp2, resplen2,
++ answerp2_malloced);
+ if (use_malloc)
+ free (buf);
+ if (n < 0) {
+@@ -316,7 +318,7 @@
+ int anslen) /* size of answer buffer */
+ {
+ return __libc_res_nquery(statp, name, class, type, answer, anslen,
+- NULL, NULL, NULL, NULL);
++ NULL, NULL, NULL, NULL, NULL);
+ }
+ libresolv_hidden_def (res_nquery)
+
+@@ -335,7 +337,8 @@
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2,
+- int *resplen2)
++ int *resplen2,
++ int *answerp2_malloced)
+ {
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+@@ -360,7 +363,7 @@
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (__libc_res_nquery(statp, cp, class, type, answer,
+ anslen, answerp, answerp2,
+- nanswerp2, resplen2));
++ nanswerp2, resplen2, answerp2_malloced));
+
+ #ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+@@ -377,7 +380,8 @@
+ if (dots >= statp->ndots || trailing_dot) {
+ ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen, answerp,
+- answerp2, nanswerp2, resplen2);
++ answerp2, nanswerp2, resplen2,
++ answerp2_malloced);
+ if (ret > 0 || (ret == 0 && *resplen2 > 0) || trailing_dot)
+ return (ret);
+ saved_herrno = h_errno;
+@@ -386,11 +390,11 @@
+ answer = *answerp;
+ anslen = MAXPACKET;
+ }
+- if (answerp2
+- && (*answerp2 < answer || *answerp2 >= answer + anslen))
++ if (answerp2 && *answerp2_malloced)
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
++ *answerp2_malloced = 0;
+ }
+ }
+
+@@ -417,7 +421,7 @@
+ class, type,
+ answer, anslen, answerp,
+ answerp2, nanswerp2,
+- resplen2);
++ resplen2, answerp2_malloced);
+ if ((ret > 0) || (ret == 0 && *resplen2 > 0))
+ return (ret);
+
+@@ -425,12 +429,11 @@
+ answer = *answerp;
+ anslen = MAXPACKET;
+ }
+- if (answerp2
+- && (*answerp2 < answer
+- || *answerp2 >= answer + anslen))
++ if (answerp2 && *answerp2_malloced)
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
++ *answerp2_malloced = 0;
+ }
+
+ /*
+@@ -486,7 +489,8 @@
+ && !(tried_as_is || root_on_list)) {
+ ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen, answerp,
+- answerp2, nanswerp2, resplen2);
++ answerp2, nanswerp2, resplen2,
++ answerp2_malloced);
+ if ((ret > 0) || (ret == 0 && *resplen2 > 0))
+ return (ret);
+ }
+@@ -498,10 +502,11 @@
+ * else send back meaningless H_ERRNO, that being the one from
+ * the last DNSRCH we did.
+ */
+- if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
++ if (answerp2 && *answerp2_malloced)
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
++ *answerp2_malloced = 0;
+ }
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(statp, saved_herrno);
+@@ -521,7 +526,7 @@
+ int anslen) /* size of answer */
+ {
+ return __libc_res_nsearch(statp, name, class, type, answer,
+- anslen, NULL, NULL, NULL, NULL);
++ anslen, NULL, NULL, NULL, NULL, NULL);
+ }
+ libresolv_hidden_def (res_nsearch)
+
+@@ -539,7 +544,8 @@
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2,
+- int *resplen2)
++ int *resplen2,
++ int *answerp2_malloced)
+ {
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+@@ -577,7 +583,7 @@
+ }
+ return (__libc_res_nquery(statp, longname, class, type, answer,
+ anslen, answerp, answerp2, nanswerp2,
+- resplen2));
++ resplen2, answerp2_malloced));
+ }
+
+ int
+@@ -589,7 +595,8 @@
+ int anslen) /* size of answer */
+ {
+ return __libc_res_nquerydomain(statp, name, domain, class, type,
+- answer, anslen, NULL, NULL, NULL, NULL);
++ answer, anslen, NULL, NULL, NULL, NULL,
++ NULL);
+ }
+ libresolv_hidden_def (res_nquerydomain)
+
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -186,12 +186,12 @@
+ static int send_vc(res_state, const u_char *, int,
+ const u_char *, int,
+ u_char **, int *, int *, int, u_char **,
+- u_char **, int *, int *);
++ u_char **, int *, int *, int *);
+ static int send_dg(res_state, const u_char *, int,
+ const u_char *, int,
+ u_char **, int *, int *, int,
+ int *, int *, u_char **,
+- u_char **, int *, int *);
++ u_char **, int *, int *, int *);
+ #ifdef DEBUG
+ static void Aerror(const res_state, FILE *, const char *, int,
+ const struct sockaddr *);
+@@ -343,7 +343,7 @@
+ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
+ const u_char *buf2, int buflen2,
+ u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
+- int *nansp2, int *resplen2)
++ int *nansp2, int *resplen2, int *ansp2_malloced)
+ {
+ int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+
+@@ -546,7 +546,8 @@
+ try = statp->retry;
+ n = send_vc(statp, buf, buflen, buf2, buflen2,
+ &ans, &anssiz, &terrno,
+- ns, ansp, ansp2, nansp2, resplen2);
++ ns, ansp, ansp2, nansp2, resplen2,
++ ansp2_malloced);
+ if (n < 0)
+ return (-1);
+ if (n == 0 && (buf2 == NULL || *resplen2 == 0))
+@@ -556,7 +557,7 @@
+ n = send_dg(statp, buf, buflen, buf2, buflen2,
+ &ans, &anssiz, &terrno,
+ ns, &v_circuit, &gotsomewhere, ansp,
+- ansp2, nansp2, resplen2);
++ ansp2, nansp2, resplen2, ansp2_malloced);
+ if (n < 0)
+ return (-1);
+ if (n == 0 && (buf2 == NULL || *resplen2 == 0))
+@@ -646,7 +647,7 @@
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
+ {
+ return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
+- NULL, NULL, NULL, NULL);
++ NULL, NULL, NULL, NULL, NULL);
+ }
+ libresolv_hidden_def (res_nsend)
+
+@@ -657,7 +658,7 @@
+ const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+ u_char **ansp, int *anssizp,
+ int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
+- int *resplen2)
++ int *resplen2, int *ansp2_malloced)
+ {
+ const HEADER *hp = (HEADER *) buf;
+ const HEADER *hp2 = (HEADER *) buf2;
+@@ -823,6 +824,8 @@
+ }
+ *thisanssizp = MAXPACKET;
+ *thisansp = newp;
++ if (thisansp == ansp2)
++ *ansp2_malloced = 1;
+ anhp = (HEADER *) newp;
+ len = rlen;
+ } else {
+@@ -1000,7 +1003,7 @@
+ const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+ u_char **ansp, int *anssizp,
+ int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
+- u_char **ansp2, int *anssizp2, int *resplen2)
++ u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
+ {
+ const HEADER *hp = (HEADER *) buf;
+ const HEADER *hp2 = (HEADER *) buf2;
+@@ -1175,6 +1178,8 @@
+ if (newp != NULL) {
+ *anssizp = MAXPACKET;
+ *thisansp = ans = newp;
++ if (thisansp == ansp2)
++ *ansp2_malloced = 1;
+ }
+ }
+ HEADER *anhp = (HEADER *) *thisansp;
diff --git a/debian/patches/series b/debian/patches/series
index 0d0c9b1..6a9bcd8 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -412,3 +412,4 @@ any/cvs-strxfrm-buffer-overflows.diff
any/cvs-strftime.diff
any/cvs-hcreate.diff
any/cvs-catopen.diff
+any/cvs-gethostbyname4-memory-leak.diff
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-glibc/glibc.git
Reply to: