[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[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: