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

Bug#825699: marked as done (jessie-pu: package glibc/2.19-18+deb8u5)



Your message dated Sat, 17 Sep 2016 13:08:06 +0100
with message-id <1474114086.2011.126.camel@adam-barratt.org.uk>
and subject line Closing p-u bugs for updates in 8.6
has caused the Debian Bug report #825699,
regarding jessie-pu: package glibc/2.19-18+deb8u5
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
825699: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=825699
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Dear stable release managers,

I would like to upload a new glibc package for the next jessie release.
It's basically a pull from the upstream stable branch. It mostly fixes
security issues which do not warrant a separate DSA, a regression
introduced by CVE-2015-7547, and issues with *context functions on s390x
preventing docker to work.

All those changes are already in testing/unstable/experimental for a few
weeks. You will find the diff below. It is a bit big given the patch we
were using for CVE-2015-7547 has been merged upstream, so it actually
appears twice in the diff.

I am really sorry for sending that so late with regards to the deadline,
I really hope it can be included in the 8.5 release.

Thanks,
Aurelien


diff --git a/debian/changelog b/debian/changelog
index db98ce0..c96e478 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+glibc (2.19-18+deb8u5) UNRELEASED; urgency=medium
+
+  [ Aurelien Jarno ]
+  * Update from upstream stable branch:
+    - Drop debian/patches/any/local-CVE-2015-7547.diff.
+    - Refresh debian/patches/any/cvs-resolv-first-query-failure.diff.
+    - Fix assertion failure with unconnectable name server addresses.
+      (regression introduced by CVE-2015-7547).  Closes: #816669.
+    - Fix *context functions on s390x.
+    - Fix a buffer overflow in the glob function (CVE-2016-1234).
+    - Fix a stack overflow in nss_dns_getnetbyname_r (CVE-2016-3075).
+    - Fix a stack overflow in getaddrinfo function (CVE-2016-3706).
+
+ -- Aurelien Jarno <aurel32@debian.org>  Sun, 01 May 2016 16:38:48 +0200
+
 glibc (2.19-18+deb8u4) stable; urgency=medium
 
   [ Aurelien Jarno ]
diff --git a/debian/patches/any/cvs-resolv-first-query-failure.diff b/debian/patches/any/cvs-resolv-first-query-failure.diff
index d99e636..856d850 100644
--- a/debian/patches/any/cvs-resolv-first-query-failure.diff
+++ b/debian/patches/any/cvs-resolv-first-query-failure.diff
@@ -44,11 +44,11 @@ diff --git a/resolv/res_send.c b/resolv/res_send.c
  			if (recvresp1 || (buf2 != NULL && recvresp2)) {
  			  *resplen2 = 0;
  			  return resplen;
-@@ -1368,7 +1369,6 @@ send_dg(res_state statp,
+@@ -1527,7 +1528,6 @@  send_dg(res_state statp,
  			    goto wait;
  			  }
  
 -		next_ns:
- 			__res_iclose(statp, false);
  			/* don't retry if called from dig */
  			if (!statp->pfcode)
+ 			  return close_and_return_error (statp, resplen2);
diff --git a/debian/patches/any/local-CVE-2015-7547.diff b/debian/patches/any/local-CVE-2015-7547.diff
deleted file mode 100644
index 0a93cd5..0000000
--- a/debian/patches/any/local-CVE-2015-7547.diff
+++ /dev/null
@@ -1,541 +0,0 @@
---- a/resolv/nss_dns/dns-host.c
-+++ b/resolv/nss_dns/dns-host.c
-@@ -1052,7 +1052,10 @@
-   int h_namelen = 0;
- 
-   if (ancount == 0)
--    return NSS_STATUS_NOTFOUND;
-+    {
-+      *h_errnop = HOST_NOT_FOUND;
-+      return NSS_STATUS_NOTFOUND;
-+    }
- 
-   while (ancount-- > 0 && cp < end_of_message && had_error == 0)
-     {
-@@ -1229,7 +1232,14 @@
-   /* Special case here: if the resolver sent a result but it only
-      contains a CNAME while we are looking for a T_A or T_AAAA record,
-      we fail with NOTFOUND instead of TRYAGAIN.  */
--  return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-+  if (canon != NULL)
-+    {
-+      *h_errnop = HOST_NOT_FOUND;
-+      return NSS_STATUS_NOTFOUND;
-+    }
-+
-+  *h_errnop = NETDB_INTERNAL;
-+  return NSS_STATUS_TRYAGAIN;
- }
- 
- 
-@@ -1243,11 +1253,101 @@
- 
-   enum nss_status status = NSS_STATUS_NOTFOUND;
- 
-+  /* Combining the NSS status of two distinct queries requires some
-+     compromise and attention to symmetry (A or AAAA queries can be
-+     returned in any order).  What follows is a breakdown of how this
-+     code is expected to work and why. We discuss only SUCCESS,
-+     TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
-+     that apply (though RETURN and MERGE exist).  We make a distinction
-+     between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
-+     A recoverable TRYAGAIN is almost always due to buffer size issues
-+     and returns ERANGE in errno and the caller is expected to retry
-+     with a larger buffer.
-+
-+     Lastly, you may be tempted to make significant changes to the
-+     conditions in this code to bring about symmetry between responses.
-+     Please don't change anything without due consideration for
-+     expected application behaviour.  Some of the synthesized responses
-+     aren't very well thought out and sometimes appear to imply that
-+     IPv4 responses are always answer 1, and IPv6 responses are always
-+     answer 2, but that's not true (see the implemetnation of send_dg
-+     and send_vc to see response can arrive in any order, particlarly
-+     for UDP). However, we expect it holds roughly enough of the time
-+     that this code works, but certainly needs to be fixed to make this
-+     a more robust implementation.
-+
-+     ----------------------------------------------
-+     | Answer 1 Status /   | Synthesized | Reason |
-+     | Answer 2 Status     | Status      |        |
-+     |--------------------------------------------|
-+     | SUCCESS/SUCCESS     | SUCCESS     | [1]    |
-+     | SUCCESS/TRYAGAIN    | TRYAGAIN    | [5]    |
-+     | SUCCESS/TRYAGAIN'   | SUCCESS     | [1]    |
-+     | SUCCESS/NOTFOUND    | SUCCESS     | [1]    |
-+     | SUCCESS/UNAVAIL     | SUCCESS     | [1]    |
-+     | TRYAGAIN/SUCCESS    | TRYAGAIN    | [2]    |
-+     | TRYAGAIN/TRYAGAIN   | TRYAGAIN    | [2]    |
-+     | TRYAGAIN/TRYAGAIN'  | TRYAGAIN    | [2]    |
-+     | TRYAGAIN/NOTFOUND   | TRYAGAIN    | [2]    |
-+     | TRYAGAIN/UNAVAIL    | TRYAGAIN    | [2]    |
-+     | TRYAGAIN'/SUCCESS   | SUCCESS     | [3]    |
-+     | TRYAGAIN'/TRYAGAIN  | TRYAGAIN    | [3]    |
-+     | TRYAGAIN'/TRYAGAIN' | TRYAGAIN'   | [3]    |
-+     | TRYAGAIN'/NOTFOUND  | TRYAGAIN'   | [3]    |
-+     | TRYAGAIN'/UNAVAIL   | UNAVAIL     | [3]    |
-+     | NOTFOUND/SUCCESS    | SUCCESS     | [3]    |
-+     | NOTFOUND/TRYAGAIN   | TRYAGAIN    | [3]    |
-+     | NOTFOUND/TRYAGAIN'  | TRYAGAIN'   | [3]    |
-+     | NOTFOUND/NOTFOUND   | NOTFOUND    | [3]    |
-+     | NOTFOUND/UNAVAIL    | UNAVAIL     | [3]    |
-+     | UNAVAIL/SUCCESS     | UNAVAIL     | [4]    |
-+     | UNAVAIL/TRYAGAIN    | UNAVAIL     | [4]    |
-+     | UNAVAIL/TRYAGAIN'   | UNAVAIL     | [4]    |
-+     | UNAVAIL/NOTFOUND    | UNAVAIL     | [4]    |
-+     | UNAVAIL/UNAVAIL     | UNAVAIL     | [4]    |
-+     ----------------------------------------------
-+
-+     [1] If the first response is a success we return success.
-+         This ignores the state of the second answer and in fact
-+         incorrectly sets errno and h_errno to that of the second
-+	 answer.  However because the response is a success we ignore
-+	 *errnop and *h_errnop (though that means you touched errno on
-+         success).  We are being conservative here and returning the
-+         likely IPv4 response in the first answer as a success.
-+
-+     [2] If the first response is a recoverable TRYAGAIN we return
-+	 that instead of looking at the second response.  The
-+	 expectation here is that we have failed to get an IPv4 response
-+	 and should retry both queries.
-+
-+     [3] If the first response was not a SUCCESS and the second
-+	 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
-+	 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
-+	 result from the second response, otherwise the first responses
-+	 status is used.  Again we have some odd side-effects when the
-+	 second response is NOTFOUND because we overwrite *errnop and
-+	 *h_errnop that means that a first answer of NOTFOUND might see
-+	 its *errnop and *h_errnop values altered.  Whether it matters
-+	 in practice that a first response NOTFOUND has the wrong
-+	 *errnop and *h_errnop is undecided.
-+
-+     [4] If the first response is UNAVAIL we return that instead of
-+	 looking at the second response.  The expectation here is that
-+	 it will have failed similarly e.g. configuration failure.
-+
-+     [5] Testing this code is complicated by the fact that truncated
-+	 second response buffers might be returned as SUCCESS if the
-+	 first answer is a SUCCESS.  To fix this we add symmetry to
-+	 TRYAGAIN with the second response.  If the second response
-+	 is a recoverable error we now return TRYAGIN even if the first
-+	 response was SUCCESS.  */
-+
-   if (anslen1 > 0)
-     status = gaih_getanswer_slice(answer1, anslen1, qname,
- 				  &pat, &buffer, &buflen,
- 				  errnop, h_errnop, ttlp,
- 				  &first);
-+
-   if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
-        || (status == NSS_STATUS_TRYAGAIN
- 	   /* We want to look at the second answer in case of an
-@@ -1263,8 +1363,15 @@
- 						     &pat, &buffer, &buflen,
- 						     errnop, h_errnop, ttlp,
- 						     &first);
-+      /* Use the second response status in some cases.  */
-       if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
- 	status = status2;
-+      /* Do not return a truncated second response (unless it was
-+         unavoidable e.g. unrecoverable TRYAGAIN).  */
-+      if (status == NSS_STATUS_SUCCESS
-+	  && (status2 == NSS_STATUS_TRYAGAIN
-+	      && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
-+	status = NSS_STATUS_TRYAGAIN;
-     }
- 
-   return status;
---- a/resolv/res_query.c
-+++ b/resolv/res_query.c
-@@ -396,6 +396,7 @@
- 		  {
- 		    free (*answerp2);
- 		    *answerp2 = NULL;
-+		    *nanswerp2 = 0;
- 		    *answerp2_malloced = 0;
- 		  }
- 	}
-@@ -436,6 +437,7 @@
- 			  {
- 			    free (*answerp2);
- 			    *answerp2 = NULL;
-+			    *nanswerp2 = 0;
- 			    *answerp2_malloced = 0;
- 			  }
- 
-@@ -509,6 +511,7 @@
- 	  {
- 	    free (*answerp2);
- 	    *answerp2 = NULL;
-+	    *nanswerp2 = 0;
- 	    *answerp2_malloced = 0;
- 	  }
- 	if (saved_herrno != -1)
---- a/resolv/res_send.c
-+++ b/resolv/res_send.c
-@@ -1,3 +1,20 @@
-+/* Copyright (C) 2016 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+
- /*
-  * Copyright (c) 1985, 1989, 1993
-  *    The Regents of the University of California.  All rights reserved.
-@@ -360,6 +377,8 @@
- #ifdef USE_HOOKS
- 	if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
- 		if (anssiz < MAXPACKET && ansp) {
-+			/* Always allocate MAXPACKET, callers expect
-+			   this specific size.  */
- 			u_char *buf = malloc (MAXPACKET);
- 			if (buf == NULL)
- 				return (-1);
-@@ -653,6 +672,77 @@
- 
- /* Private */
- 
-+/* The send_vc function is responsible for sending a DNS query over TCP
-+   to the nameserver numbered NS from the res_state STATP i.e.
-+   EXT(statp).nssocks[ns].  The function supports sending both IPv4 and
-+   IPv6 queries at the same serially on the same socket.
-+
-+   Please note that for TCP there is no way to disable sending both
-+   queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
-+   and sends the queries serially and waits for the result after each
-+   sent query.  This implemetnation should be corrected to honour these
-+   options.
-+
-+   Please also note that for TCP we send both queries over the same
-+   socket one after another.  This technically violates best practice
-+   since the server is allowed to read the first query, respond, and
-+   then close the socket (to service another client).  If the server
-+   does this, then the remaining second query in the socket data buffer
-+   will cause the server to send the client an RST which will arrive
-+   asynchronously and the client's OS will likely tear down the socket
-+   receive buffer resulting in a potentially short read and lost
-+   response data.  This will force the client to retry the query again,
-+   and this process may repeat until all servers and connection resets
-+   are exhausted and then the query will fail.  It's not known if this
-+   happens with any frequency in real DNS server implementations.  This
-+   implementation should be corrected to use two sockets by default for
-+   parallel queries.
-+
-+   The query stored in BUF of BUFLEN length is sent first followed by
-+   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
-+   serially on the same socket.
-+
-+   Answers to the query are stored firstly in *ANSP up to a max of
-+   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
-+   is non-NULL (to indicate that modifying the answer buffer is allowed)
-+   then malloc is used to allocate a new response buffer and ANSCP and
-+   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
-+   are needed but ANSCP is NULL, then as much of the response as
-+   possible is read into the buffer, but the results will be truncated.
-+   When truncation happens because of a small answer buffer the DNS
-+   packets header feild TC will bet set to 1, indicating a truncated
-+   message and the rest of the socket data will be read and discarded.
-+
-+   Answers to the query are stored secondly in *ANSP2 up to a max of
-+   *ANSSIZP2 bytes, with the actual response length stored in
-+   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
-+   is non-NULL (required for a second query) then malloc is used to
-+   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
-+   size and *ANSP2_MALLOCED is set to 1.
-+
-+   The ANSP2_MALLOCED argument will eventually be removed as the
-+   change in buffer pointer can be used to detect the buffer has
-+   changed and that the caller should use free on the new buffer.
-+
-+   Note that the answers may arrive in any order from the server and
-+   therefore the first and second answer buffers may not correspond to
-+   the first and second queries.
-+
-+   It is not supported to call this function with a non-NULL ANSP2
-+   but a NULL ANSCP.  Put another way, you can call send_vc with a
-+   single unmodifiable buffer or two modifiable buffers, but no other
-+   combination is supported.
-+
-+   It is the caller's responsibility to free the malloc allocated
-+   buffers by detecting that the pointers have changed from their
-+   original values i.e. *ANSCP or *ANSP2 has changed.
-+
-+   If errors are encountered then *TERRNO is set to an appropriate
-+   errno value and a zero result is returned for a recoverable error,
-+   and a less-than zero result is returned for a non-recoverable error.
-+
-+   If no errors are encountered then *TERRNO is left unmodified and
-+   a the length of the first response in bytes is returned.  */
- static int
- send_vc(res_state statp,
- 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
-@@ -662,11 +752,7 @@
- {
- 	const HEADER *hp = (HEADER *) buf;
- 	const HEADER *hp2 = (HEADER *) buf2;
--	u_char *ans = *ansp;
--	int orig_anssizp = *anssizp;
--	// XXX REMOVE
--	// int anssiz = *anssizp;
--	HEADER *anhp = (HEADER *) ans;
-+	HEADER *anhp = (HEADER *) *ansp;
- 	struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
- 	int truncating, connreset, resplen, n;
- 	struct iovec iov[4];
-@@ -742,6 +828,8 @@
- 	 * Receive length & response
- 	 */
- 	int recvresp1 = 0;
-+	/* Skip the second response if there is no second query.
-+           To do that we mark the second response as received.  */
- 	int recvresp2 = buf2 == NULL;
- 	uint16_t rlen16;
-  read_len:
-@@ -778,33 +866,14 @@
- 	u_char **thisansp;
- 	int *thisresplenp;
- 	if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
-+		/* We have not received any responses
-+		   yet or we only have one response to
-+		   receive.  */
- 		thisanssizp = anssizp;
- 		thisansp = anscp ?: ansp;
- 		assert (anscp != NULL || ansp2 == NULL);
- 		thisresplenp = &resplen;
- 	} else {
--		if (*anssizp != MAXPACKET) {
--			/* No buffer allocated for the first
--			   reply.  We can try to use the rest
--			   of the user-provided buffer.  */
--#ifdef _STRING_ARCH_unaligned
--			*anssizp2 = orig_anssizp - resplen;
--			*ansp2 = *ansp + resplen;
--#else
--			int aligned_resplen
--			  = ((resplen + __alignof__ (HEADER) - 1)
--			     & ~(__alignof__ (HEADER) - 1));
--			*anssizp2 = orig_anssizp - aligned_resplen;
--			*ansp2 = *ansp + aligned_resplen;
--#endif
--		} else {
--			/* The first reply did not fit into the
--			   user-provided buffer.  Maybe the second
--			   answer will.  */
--			*anssizp2 = orig_anssizp;
--			*ansp2 = *ansp;
--		}
--
- 		thisanssizp = anssizp2;
- 		thisansp = ansp2;
- 		thisresplenp = resplen2;
-@@ -812,10 +881,14 @@
- 	anhp = (HEADER *) *thisansp;
- 
- 	*thisresplenp = rlen;
--	if (rlen > *thisanssizp) {
--		/* Yes, we test ANSCP here.  If we have two buffers
--		   both will be allocatable.  */
--		if (__builtin_expect (anscp != NULL, 1)) {
-+	/* Is the answer buffer too small?  */
-+	if (*thisanssizp < rlen) {
-+		/* If the current buffer is non-NULL and it's not
-+		   pointing at the static user-supplied buffer then
-+		   we can reallocate it.  */
-+		if (thisansp != NULL && thisansp != ansp) {
-+			/* Always allocate MAXPACKET, callers expect
-+			   this specific size.  */
- 			u_char *newp = malloc (MAXPACKET);
- 			if (newp == NULL) {
- 				*terrno = ENOMEM;
-@@ -827,6 +900,9 @@
- 			if (thisansp == ansp2)
- 			  *ansp2_malloced = 1;
- 			anhp = (HEADER *) newp;
-+			/* A uint16_t can't be larger than MAXPACKET
-+			   thus it's safe to allocate MAXPACKET but
-+			   read RLEN bytes instead.  */
- 			len = rlen;
- 		} else {
- 			Dprint(statp->options & RES_DEBUG,
-@@ -998,6 +1074,66 @@
- 	return 1;
- }
- 
-+/* The send_dg function is responsible for sending a DNS query over UDP
-+   to the nameserver numbered NS from the res_state STATP i.e.
-+   EXT(statp).nssocks[ns].  The function supports IPv4 and IPv6 queries
-+   along with the ability to send the query in parallel for both stacks
-+   (default) or serially (RES_SINGLKUP).  It also supports serial lookup
-+   with a close and reopen of the socket used to talk to the server
-+   (RES_SNGLKUPREOP) to work around broken name servers.
-+
-+   The query stored in BUF of BUFLEN length is sent first followed by
-+   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
-+   in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
-+
-+   Answers to the query are stored firstly in *ANSP up to a max of
-+   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
-+   is non-NULL (to indicate that modifying the answer buffer is allowed)
-+   then malloc is used to allocate a new response buffer and ANSCP and
-+   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
-+   are needed but ANSCP is NULL, then as much of the response as
-+   possible is read into the buffer, but the results will be truncated.
-+   When truncation happens because of a small answer buffer the DNS
-+   packets header feild TC will bet set to 1, indicating a truncated
-+   message, while the rest of the UDP packet is discarded.
-+
-+   Answers to the query are stored secondly in *ANSP2 up to a max of
-+   *ANSSIZP2 bytes, with the actual response length stored in
-+   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
-+   is non-NULL (required for a second query) then malloc is used to
-+   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
-+   size and *ANSP2_MALLOCED is set to 1.
-+
-+   The ANSP2_MALLOCED argument will eventually be removed as the
-+   change in buffer pointer can be used to detect the buffer has
-+   changed and that the caller should use free on the new buffer.
-+
-+   Note that the answers may arrive in any order from the server and
-+   therefore the first and second answer buffers may not correspond to
-+   the first and second queries.
-+
-+   It is not supported to call this function with a non-NULL ANSP2
-+   but a NULL ANSCP.  Put another way, you can call send_vc with a
-+   single unmodifiable buffer or two modifiable buffers, but no other
-+   combination is supported.
-+
-+   It is the caller's responsibility to free the malloc allocated
-+   buffers by detecting that the pointers have changed from their
-+   original values i.e. *ANSCP or *ANSP2 has changed.
-+
-+   If an answer is truncated because of UDP datagram DNS limits then
-+   *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
-+   the caller to retry with TCP.  The value *GOTSOMEWHERE is set to 1
-+   if any progress was made reading a response from the nameserver and
-+   is used by the caller to distinguish between ECONNREFUSED and
-+   ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
-+
-+   If errors are encountered then *TERRNO is set to an appropriate
-+   errno value and a zero result is returned for a recoverable error,
-+   and a less-than zero result is returned for a non-recoverable error.
-+
-+   If no errors are encountered then *TERRNO is left unmodified and
-+   a the length of the first response in bytes is returned.  */
- static int
- send_dg(res_state statp,
- 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
-@@ -1007,8 +1143,6 @@
- {
- 	const HEADER *hp = (HEADER *) buf;
- 	const HEADER *hp2 = (HEADER *) buf2;
--	u_char *ans = *ansp;
--	int orig_anssizp = *anssizp;
- 	struct timespec now, timeout, finish;
- 	struct pollfd pfd[1];
- 	int ptimeout;
-@@ -1041,6 +1175,8 @@
- 	int need_recompute = 0;
- 	int nwritten = 0;
- 	int recvresp1 = 0;
-+	/* Skip the second response if there is no second query.
-+           To do that we mark the second response as received.  */
- 	int recvresp2 = buf2 == NULL;
- 	pfd[0].fd = EXT(statp).nssocks[ns];
- 	pfd[0].events = POLLOUT;
-@@ -1204,55 +1340,56 @@
- 		int *thisresplenp;
- 
- 		if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
-+			/* We have not received any responses
-+			   yet or we only have one response to
-+			   receive.  */
- 			thisanssizp = anssizp;
- 			thisansp = anscp ?: ansp;
- 			assert (anscp != NULL || ansp2 == NULL);
- 			thisresplenp = &resplen;
- 		} else {
--			if (*anssizp != MAXPACKET) {
--				/* No buffer allocated for the first
--				   reply.  We can try to use the rest
--				   of the user-provided buffer.  */
--#ifdef _STRING_ARCH_unaligned
--				*anssizp2 = orig_anssizp - resplen;
--				*ansp2 = *ansp + resplen;
--#else
--				int aligned_resplen
--				  = ((resplen + __alignof__ (HEADER) - 1)
--				     & ~(__alignof__ (HEADER) - 1));
--				*anssizp2 = orig_anssizp - aligned_resplen;
--				*ansp2 = *ansp + aligned_resplen;
--#endif
--			} else {
--				/* The first reply did not fit into the
--				   user-provided buffer.  Maybe the second
--				   answer will.  */
--				*anssizp2 = orig_anssizp;
--				*ansp2 = *ansp;
--			}
--
- 			thisanssizp = anssizp2;
- 			thisansp = ansp2;
- 			thisresplenp = resplen2;
- 		}
- 
- 		if (*thisanssizp < MAXPACKET
--		    /* Yes, we test ANSCP here.  If we have two buffers
--		       both will be allocatable.  */
--		    && anscp
-+		    /* If the current buffer is non-NULL and it's not
-+		       pointing at the static user-supplied buffer then
-+		       we can reallocate it.  */
-+		    && (thisansp != NULL && thisansp != ansp)
- #ifdef FIONREAD
-+		    /* Is the size too small?  */
- 		    && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
- 			|| *thisanssizp < *thisresplenp)
- #endif
-                     ) {
-+			/* Always allocate MAXPACKET, callers expect
-+			   this specific size.  */
- 			u_char *newp = malloc (MAXPACKET);
- 			if (newp != NULL) {
--				*anssizp = MAXPACKET;
--				*thisansp = ans = newp;
-+				*thisanssizp = MAXPACKET;
-+				*thisansp = newp;
- 				if (thisansp == ansp2)
- 				  *ansp2_malloced = 1;
- 			}
- 		}
-+		/* We could end up with truncation if anscp was NULL
-+		   (not allowed to change caller's buffer) and the
-+		   response buffer size is too small.  This isn't a
-+		   reliable way to detect truncation because the ioctl
-+		   may be an inaccurate report of the UDP message size.
-+		   Therefore we use this only to issue debug output.
-+		   To do truncation accurately with UDP we need
-+		   MSG_TRUNC which is only available on Linux.  We
-+		   can abstract out the Linux-specific feature in the
-+		   future to detect truncation.  */
-+		if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
-+			Dprint(statp->options & RES_DEBUG,
-+			       (stdout, ";; response may be truncated (UDP)\n")
-+			);
-+		}
-+
- 		HEADER *anhp = (HEADER *) *thisansp;
- 		socklen_t fromlen = sizeof(struct sockaddr_in6);
- 		assert (sizeof(from) <= fromlen);
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff
index 1a24dd0..b77210d 100644
--- a/debian/patches/git-updates.diff
+++ b/debian/patches/git-updates.diff
@@ -1,10 +1,118 @@
 GIT update of git://sourceware.org/git/glibc.git/release/2.19/master from glibc-2.19
 
 diff --git a/ChangeLog b/ChangeLog
-index 81c393a..9907019 100644
+index 81c393a..f9a9e33 100644
 --- a/ChangeLog
 +++ b/ChangeLog
-@@ -1,3 +1,443 @@
+@@ -1,3 +1,551 @@
++2016-03-25  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #19791]
++	* resolv/res_send.c (close_and_return_error): New function.
++	(send_dg): Initialize *resplen2 after reopen failure.  Call
++	close_and_return_error for error returns.  On error paths without
++	__res_iclose, initialze *resplen2 explicitly.  Update comment for
++	successful return.
++
++2016-02-15  Carlos O'Donell  <carlos@redhat.com>
++
++	[BZ #18665]
++	* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
++	*herrno_p.
++	(gaih_getanswer): Document functional behviour. Return tryagain
++	if any result is tryagain.
++	* resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
++	when freed.
++	* resolv/res_send.c: Add copyright text.
++	(__libc_res_nsend): Document that MAXPACKET is expected.
++	(send_vc): Document. Remove buffer reuse.
++	(send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
++	size of the buffer. Add Dprint for truncated UDP buffer.
++
++2016-04-29  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #20010]
++	CVE-2016-3706
++	* sysdeps/posix/getaddrinfo.c
++	(convert_hostent_to_gaih_addrtuple): New function.
++	(gethosts): Call convert_hostent_to_gaih_addrtuple.
++	(gaih_inet): Use convert_hostent_to_gaih_addrtuple to convert
++	AF_INET data.
++
++2016-05-04  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #19779]
++	CVE-2016-1234
++	Avoid copying names of directory entries.
++	* posix/glob.c (DIRENT_MUST_BE, DIRENT_MIGHT_BE_SYMLINK)
++	(DIRENT_MIGHT_BE_DIR, CONVERT_D_INO, CONVERT_D_TYPE)
++	(CONVERT_DIRENT_DIRENT64, REAL_DIR_ENTRY): Remove macros.
++	(struct readdir_result): New type.
++	(D_TYPE_TO_RESULT, D_INO_TO_RESULT, READDIR_RESULT_INITIALIZER)
++	(GL_READDIR): New macros.
++	(readdir_result_might_be_symlink, readdir_result_might_be_dir)
++	(convert_dirent, convert_dirent64): New functions.
++	(glob_in_dir): Use struct readdir_result.  Call convert_dirent or
++	convert_dirent64.  Adjust references to the readdir result.
++	* sysdeps/unix/sysv/linux/i386/glob64.c:
++	(convert_dirent, GL_READDIR): Redefine for second file inclusion.
++	* posix/bug-glob2.c (LONG_NAME): Define.
++	(filesystem): Add LONG_NAME.
++	(my_DIR): Increase the size of room_for_dirent.
++
++2016-04-29  Florian Weimer  <fweimer@redhat.com>
++
++	glob: Simplify and document the interface for the GLOB_ALTDIRFUNC
++	callback function gl_readdir.
++	* posix/glob.c (NAMELEN, CONVERT_D_NAMLEN): Remove.
++	(CONVERT_DIRENT_DIRENT64): Use strcpy instead of memcpy.
++	(glob_in_dir): Remove len.  Use strdup instead of malloc and
++	memcpy to copy the name.
++	* manual/pattern.texi (Calling Glob): Document requirements for
++	implementations of the gl_readdir callback function.
++	* manual/examples/mkdirent.c: New example.
++	* posix/bug-glob2.c (my_readdir): Set d_ino to 1 unconditionally,
++	per the manual guidance.
++	* posix/tst-gnuglob.c (my_readdir): Likewise.
++
++2016-04-28  Stefan Liebler  <stli@linux.vnet.ibm.com>
++
++	[BZ #18508]
++	* stdlib/Makefile ($(objpfx)tst-makecontext3):
++	Depend on $(libdl).
++	* stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
++	is not called infinitely times.
++	(backtrace_helper): New function.
++	(trace_arg): New struct.
++	(st1): Enlarge stack size.
++	* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
++	(__makecontext_ret): Omit cfi_startproc and cfi_endproc.
++	* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
++	Likewise.
++
++2016-04-28  Stefan Liebler  <stli@linux.vnet.ibm.com>
++
++	[BZ #18080]
++	* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
++	(__setcontext): Use SIG_SETMASK instead of SIG_BLOCK.
++	* sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
++	(__setcontext): Likewise.
++	* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
++	(__swapcontext): Use SIG_SETMASK instead of SIG_BLOCK.
++	Call rt_sigprocmask syscall one time to set new signal mask
++	and retrieve the current signal mask instead of two calls.
++	* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
++	(__swapcontext): Likewise.
++	* stdlib/Makefile (tests): Add new testcase tst-setcontext2.
++	* stdlib/tst-setcontext2.c: New file.
++
++2016-04-01  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #19879]
++	CVE-2016-3075
++	* resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Do not
++	copy name.
++
 +2016-02-12  Florian Weimer  <fweimer@redhat.com>
 +
 +	* misc/bug18240.c (do_test): Set RLIMIT_AS.
@@ -449,10 +557,10 @@ index 81c393a..9907019 100644
  
  	[BZ #16529]
 diff --git a/NEWS b/NEWS
-index 98b479e..0d1952c 100644
+index 98b479e..d14f9ed 100644
 --- a/NEWS
 +++ b/NEWS
-@@ -5,6 +5,65 @@ See the end for copying conditions.
+@@ -5,6 +5,94 @@ See the end for copying conditions.
  Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
  using `glibc' in the "product" field.
  
@@ -463,7 +571,8 @@ index 98b479e..0d1952c 100644
 +  15946, 16545, 16574, 16623, 16657, 16695, 16743, 16758, 16759, 16760,
 +  16878, 16882, 16885, 16916, 16932, 16943, 16958, 17048, 17062, 17069,
 +  17079, 17137, 17153, 17213, 17263, 17269, 17325, 17555, 17905, 18007,
-+  18032, 18240, 18287, 18905.
++  18032, 18080, 18240, 18287, 18508, 18665, 18905, 19779, 19791, 19879,
++  20010.
 +
 +* A buffer overflow in gethostbyname_r and related functions performing DNS
 +  requests has been fixed.  If the NSS functions were called with a
@@ -514,6 +623,34 @@ index 98b479e..0d1952c 100644
 +  the get*ent functions if any of the query functions for the same database
 +  are used during the iteration, causing a denial-of-service condition in
 +  some applications.
++
++* The getnetbyname implementation in nss_dns had a potentially unbounded
++  alloca call (in the form of a call to strdupa), leading to a stack
++  overflow (stack exhaustion) and a crash if getnetbyname is invoked
++  on a very long name.  (CVE-2016-3075)
++
++* The glob function suffered from a stack-based buffer overflow when it was
++  called with the GLOB_ALTDIRFUNC flag and encountered a long file name.
++  Reported by Alexander Cherepanov.  (CVE-2016-1234)
++
++* Previously, getaddrinfo copied large amounts of address data to the stack,
++  even after the fix for CVE-2013-4458 has been applied, potentially
++  resulting in a stack overflow.  getaddrinfo now uses a heap allocation
++  instead.  Reported by Michael Petlan.  (CVE-2016-3706)
++
++* A stack-based buffer overflow was found in libresolv when invoked from
++  libnss_dns, allowing specially crafted DNS responses to seize control
++  of execution flow in the DNS client.  The buffer overflow occurs in
++  the functions send_dg (send datagram) and send_vc (send TCP) for the
++  NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
++  family.  The use of AF_UNSPEC triggers the low-level resolver code to
++  send out two parallel queries for A and AAAA.  A mismanagement of the
++  buffers used for those queries could result in the response of a query
++  writing beyond the alloca allocated buffer created by
++  _nss_dns_gethostbyname4_r.  Buffer management is simplified to remove
++  the overflow.  Thanks to the Google Security Team and Red Hat for
++  reporting the security impact of this issue, and Robert Holiday of
++  Ciena for reporting the related bug 18665. (CVE-2015-7547)
 +
  Version 2.19
  
@@ -1639,6 +1776,9 @@ index 0000000..e3b21a9
 +
 +#define TEST_FUNCTION do_test ()
 +#include "../test-skeleton.c"
+diff --git a/manual/examples/mkdirent.c b/manual/examples/mkdirent.c
+new file mode 100644
+index 0000000..f8400f4
 diff --git a/misc/Makefile b/misc/Makefile
 index b039182..ad9e921 100644
 --- a/misc/Makefile
@@ -2759,6 +2899,54 @@ index 6709900..8f6e6b5 100644
  tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace
  
  $(objpfx)tst-vfork3-mem: $(objpfx)tst-vfork3.out
+diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c
+index 8e21deb..3f9c620 100644
+--- a/posix/bug-glob2.c
++++ b/posix/bug-glob2.c
+@@ -40,6 +40,17 @@
+ # define PRINTF(fmt, args...)
+ #endif
+ 
++#define LONG_NAME \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
++  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ 
+ static struct
+ {
+@@ -58,6 +69,7 @@ static struct
+       { ".", 3, DT_DIR, 0755 },
+       { "..", 3, DT_DIR, 0755 },
+       { "a", 3, DT_REG, 0644 },
++      { LONG_NAME, 3, DT_REG, 0644 },
+     { "unreadable", 2, DT_DIR, 0111 },
+       { ".", 3, DT_DIR, 0111 },
+       { "..", 3, DT_DIR, 0755 },
+@@ -75,7 +87,7 @@ typedef struct
+   int level;
+   int idx;
+   struct dirent d;
+-  char room_for_dirent[NAME_MAX];
++  char room_for_dirent[sizeof (LONG_NAME)];
+ } my_DIR;
+ 
+ 
+@@ -193,7 +205,7 @@ my_readdir (void *gdir)
+       return NULL;
+     }
+ 
+-  dir->d.d_ino = dir->idx;
++  dir->d.d_ino = 1;		/* glob should not skip this entry.  */
+ 
+ #ifdef _DIRENT_HAVE_D_TYPE
+   dir->d.d_type = filesystem[dir->idx].type;
 diff --git a/posix/bug-regex36.c b/posix/bug-regex36.c
 new file mode 100644
 index 0000000..59e2b6d
@@ -2854,6 +3042,316 @@ index f79d051..733cccb 100644
  	    if (not)
  	      return FNM_NOMATCH;
  	  }
+diff --git a/posix/glob.c b/posix/glob.c
+index f143108..ae3b8b7 100644
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -24,7 +24,9 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <stdbool.h>
+ #include <stddef.h>
++#include <stdint.h>
+ 
+ /* Outcomment the following line for production quality code.  */
+ /* #define NDEBUG 1 */
+@@ -57,10 +59,8 @@
+ 
+ #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+ # include <dirent.h>
+-# define NAMLEN(dirent) strlen((dirent)->d_name)
+ #else
+ # define dirent direct
+-# define NAMLEN(dirent) (dirent)->d_namlen
+ # ifdef HAVE_SYS_NDIR_H
+ #  include <sys/ndir.h>
+ # endif
+@@ -75,82 +75,8 @@
+ # endif /* HAVE_VMSDIR_H */
+ #endif
+ 
+-
+-/* In GNU systems, <dirent.h> defines this macro for us.  */
+-#ifdef _D_NAMLEN
+-# undef NAMLEN
+-# define NAMLEN(d) _D_NAMLEN(d)
+-#endif
+-
+-/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+-   if the `d_type' member for `struct dirent' is available.
+-   HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB.  */
+-#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+-/* True if the directory entry D must be of type T.  */
+-# define DIRENT_MUST_BE(d, t)	((d)->d_type == (t))
+-
+-/* True if the directory entry D might be a symbolic link.  */
+-# define DIRENT_MIGHT_BE_SYMLINK(d) \
+-    ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
+-
+-/* True if the directory entry D might be a directory.  */
+-# define DIRENT_MIGHT_BE_DIR(d)	 \
+-    ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
+-
+-#else /* !HAVE_D_TYPE */
+-# define DIRENT_MUST_BE(d, t)		false
+-# define DIRENT_MIGHT_BE_SYMLINK(d)	true
+-# define DIRENT_MIGHT_BE_DIR(d)		true
+-#endif /* HAVE_D_TYPE */
+-
+-/* If the system has the `struct dirent64' type we use it internally.  */
+-#if defined _LIBC && !defined COMPILE_GLOB64
+-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+-#  define CONVERT_D_NAMLEN(d64, d32)
+-# else
+-#  define CONVERT_D_NAMLEN(d64, d32) \
+-  (d64)->d_namlen = (d32)->d_namlen;
+-# endif
+-
+-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+-#  define CONVERT_D_INO(d64, d32)
+-# else
+-#  define CONVERT_D_INO(d64, d32) \
+-  (d64)->d_ino = (d32)->d_ino;
+-# endif
+-
+-# ifdef _DIRENT_HAVE_D_TYPE
+-#  define CONVERT_D_TYPE(d64, d32) \
+-  (d64)->d_type = (d32)->d_type;
+-# else
+-#  define CONVERT_D_TYPE(d64, d32)
+-# endif
+-
+-# define CONVERT_DIRENT_DIRENT64(d64, d32) \
+-  memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1);		      \
+-  CONVERT_D_NAMLEN (d64, d32)						      \
+-  CONVERT_D_INO (d64, d32)						      \
+-  CONVERT_D_TYPE (d64, d32)
+-#endif
+-
+-
+-#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+-/* Posix does not require that the d_ino field be present, and some
+-   systems do not provide it. */
+-# define REAL_DIR_ENTRY(dp) 1
+-#else
+-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+-#endif /* POSIX */
+-
+ #include <stdlib.h>
+ #include <string.h>
+-
+-/* NAME_MAX is usually defined in <dirent.h> or <limits.h>.  */
+-#include <limits.h>
+-#ifndef NAME_MAX
+-# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
+-#endif
+-
+ #include <alloca.h>
+ 
+ #ifdef _LIBC
+@@ -195,8 +121,111 @@
+ 
+ static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+ 
++/* A representation of a directory entry which does not depend on the
++   layout of struct dirent, or the size of ino_t.  */
++struct readdir_result
++{
++  const char *name;
++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++  uint8_t type;
++# endif
++  bool skip_entry;
++};
++
++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++/* Initializer based on the d_type member of struct dirent.  */
++#  define D_TYPE_TO_RESULT(source) (source)->d_type,
++
++/* True if the directory entry D might be a symbolic link.  */
++static bool
++readdir_result_might_be_symlink (struct readdir_result d)
++{
++  return d.type == DT_UNKNOWN || d.type == DT_LNK;
++}
++
++/* True if the directory entry D might be a directory.  */
++static bool
++readdir_result_might_be_dir (struct readdir_result d)
++{
++  return d.type == DT_DIR || readdir_result_might_be_symlink (d);
++}
++# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
++#  define D_TYPE_TO_RESULT(source)
++
++/* If we do not have type information, symbolic links and directories
++   are always a possibility.  */
++
++static bool
++readdir_result_might_be_symlink (struct readdir_result d)
++{
++  return true;
++}
++
++static bool
++readdir_result_might_be_dir (struct readdir_result d)
++{
++  return true;
++}
++
++# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
++
++# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
++/* Initializer for skip_entry.  POSIX does not require that the d_ino
++   field be present, and some systems do not provide it. */
++#  define D_INO_TO_RESULT(source) false,
++# else
++#  define D_INO_TO_RESULT(source) (source)->d_ino == 0,
++# endif
++
++/* Construct an initializer for a struct readdir_result object from a
++   struct dirent *.  No copy of the name is made.  */
++#define READDIR_RESULT_INITIALIZER(source) \
++  {					   \
++    source->d_name,			   \
++    D_TYPE_TO_RESULT (source)		   \
++    D_INO_TO_RESULT (source)		   \
++  }
++
+ #endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+ 
++/* Call gl_readdir on STREAM.  This macro can be overridden to reduce
++   type safety if an old interface version needs to be supported.  */
++#ifndef GL_READDIR
++# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
++#endif
++
++/* Extract name and type from directory entry.  No copy of the name is
++   made.  If SOURCE is NULL, result name is NULL.  Keep in sync with
++   convert_dirent64 below.  */
++static struct readdir_result
++convert_dirent (const struct dirent *source)
++{
++  if (source == NULL)
++    {
++      struct readdir_result result = { NULL, };
++      return result;
++    }
++  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
++  return result;
++}
++
++#ifndef COMPILE_GLOB64
++/* Like convert_dirent, but works on struct dirent64 instead.  Keep in
++   sync with convert_dirent above.  */
++static struct readdir_result
++convert_dirent64 (const struct dirent64 *source)
++{
++  if (source == NULL)
++    {
++      struct readdir_result result = { NULL, };
++      return result;
++    }
++  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
++  return result;
++}
++#endif
++
++
+ #ifndef attribute_hidden
+ # define attribute_hidden
+ #endif
+@@ -1561,56 +1590,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 
+ 	  while (1)
+ 	    {
+-	      const char *name;
+-	      size_t len;
+-#if defined _LIBC && !defined COMPILE_GLOB64
+-	      struct dirent64 *d;
+-	      union
+-		{
+-		  struct dirent64 d64;
+-		  char room [offsetof (struct dirent64, d_name[0])
+-			     + NAME_MAX + 1];
+-		}
+-	      d64buf;
+-
+-	      if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+-		{
+-		  struct dirent *d32 = (*pglob->gl_readdir) (stream);
+-		  if (d32 != NULL)
+-		    {
+-		      CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
+-		      d = &d64buf.d64;
+-		    }
+-		  else
+-		    d = NULL;
+-		}
+-	      else
+-		d = __readdir64 (stream);
++	      struct readdir_result d;
++	      {
++		if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
++		  d = convert_dirent (GL_READDIR (pglob, stream));
++		else
++		  {
++#ifdef COMPILE_GLOB64
++		    d = convert_dirent (__readdir (stream));
+ #else
+-	      struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+-				  ? ((struct dirent *)
+-				     (*pglob->gl_readdir) (stream))
+-				  : __readdir (stream));
++		    d = convert_dirent64 (__readdir64 (stream));
+ #endif
+-	      if (d == NULL)
++		  }
++	      }
++	      if (d.name == NULL)
+ 		break;
+-	      if (! REAL_DIR_ENTRY (d))
++	      if (d.skip_entry)
+ 		continue;
+ 
+ 	      /* If we shall match only directories use the information
+ 		 provided by the dirent call if possible.  */
+-	      if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
++	      if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
+ 		continue;
+ 
+-	      name = d->d_name;
+-
+-	      if (fnmatch (pattern, name, fnm_flags) == 0)
++	      if (fnmatch (pattern, d.name, fnm_flags) == 0)
+ 		{
+ 		  /* If the file we found is a symlink we have to
+ 		     make sure the target file exists.  */
+-		  if (!DIRENT_MIGHT_BE_SYMLINK (d)
+-		      || link_exists_p (dfd, directory, dirlen, name, pglob,
+-					flags))
++		  if (!readdir_result_might_be_symlink (d)
++		      || link_exists_p (dfd, directory, dirlen, d.name,
++					pglob, flags))
+ 		    {
+ 		      if (cur == names->count)
+ 			{
+@@ -1630,12 +1639,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 			  names = newnames;
+ 			  cur = 0;
+ 			}
+-		      len = NAMLEN (d);
+-		      names->name[cur] = (char *) malloc (len + 1);
++		      names->name[cur] = strdup (d.name);
+ 		      if (names->name[cur] == NULL)
+ 			goto memory_error;
+-		      *((char *) mempcpy (names->name[cur++], name, len))
+-			= '\0';
++		      ++cur;
+ 		      ++nfound;
+ 		    }
+ 		}
 diff --git a/posix/regcomp.c b/posix/regcomp.c
 index 921d0f4..076eca3 100644
 --- a/posix/regcomp.c
@@ -3021,6 +3519,19 @@ index 0000000..2a83c1b
 +
 +#define TEST_FUNCTION do_test ()
 +#include "../test-skeleton.c"
+diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c
+index 1c72357..48c7527 100644
+--- a/posix/tst-gnuglob.c
++++ b/posix/tst-gnuglob.c
+@@ -211,7 +211,7 @@ my_readdir (void *gdir)
+       return NULL;
+     }
+ 
+-  dir->d.d_ino = dir->idx;
++  dir->d.d_ino = 1;		/* glob should not skip this entry.  */
+ 
+ #ifdef _DIRENT_HAVE_D_TYPE
+   dir->d.d_type = filesystem[dir->idx].type;
 diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c
 index 84cecf2..6cd874a 100644
 --- a/posix/tst-spawn.c
@@ -3100,7 +3611,7 @@ index a9db232..e8c112c 100644
  	{
  	  /* 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 f8f192e..f36d28b 100644
+index f8f192e..63029d9 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,
@@ -3200,20 +3711,178 @@ index f8f192e..f36d28b 100644
      {
        /* The buffer is too small.  */
      too_small:
+@@ -1049,7 +1052,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+   int h_namelen = 0;
+ 
+   if (ancount == 0)
+-    return NSS_STATUS_NOTFOUND;
++    {
++      *h_errnop = HOST_NOT_FOUND;
++      return NSS_STATUS_NOTFOUND;
++    }
+ 
+   while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+     {
+@@ -1226,7 +1232,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+   /* Special case here: if the resolver sent a result but it only
+      contains a CNAME while we are looking for a T_A or T_AAAA record,
+      we fail with NOTFOUND instead of TRYAGAIN.  */
+-  return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
++  if (canon != NULL)
++    {
++      *h_errnop = HOST_NOT_FOUND;
++      return NSS_STATUS_NOTFOUND;
++    }
++
++  *h_errnop = NETDB_INTERNAL;
++  return NSS_STATUS_TRYAGAIN;
+ }
+ 
+ 
+@@ -1240,11 +1253,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
+ 
+   enum nss_status status = NSS_STATUS_NOTFOUND;
+ 
++  /* Combining the NSS status of two distinct queries requires some
++     compromise and attention to symmetry (A or AAAA queries can be
++     returned in any order).  What follows is a breakdown of how this
++     code is expected to work and why. We discuss only SUCCESS,
++     TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
++     that apply (though RETURN and MERGE exist).  We make a distinction
++     between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
++     A recoverable TRYAGAIN is almost always due to buffer size issues
++     and returns ERANGE in errno and the caller is expected to retry
++     with a larger buffer.
++
++     Lastly, you may be tempted to make significant changes to the
++     conditions in this code to bring about symmetry between responses.
++     Please don't change anything without due consideration for
++     expected application behaviour.  Some of the synthesized responses
++     aren't very well thought out and sometimes appear to imply that
++     IPv4 responses are always answer 1, and IPv6 responses are always
++     answer 2, but that's not true (see the implementation of send_dg
++     and send_vc to see response can arrive in any order, particularly
++     for UDP). However, we expect it holds roughly enough of the time
++     that this code works, but certainly needs to be fixed to make this
++     a more robust implementation.
++
++     ----------------------------------------------
++     | Answer 1 Status /   | Synthesized | Reason |
++     | Answer 2 Status     | Status      |        |
++     |--------------------------------------------|
++     | SUCCESS/SUCCESS     | SUCCESS     | [1]    |
++     | SUCCESS/TRYAGAIN    | TRYAGAIN    | [5]    |
++     | SUCCESS/TRYAGAIN'   | SUCCESS     | [1]    |
++     | SUCCESS/NOTFOUND    | SUCCESS     | [1]    |
++     | SUCCESS/UNAVAIL     | SUCCESS     | [1]    |
++     | TRYAGAIN/SUCCESS    | TRYAGAIN    | [2]    |
++     | TRYAGAIN/TRYAGAIN   | TRYAGAIN    | [2]    |
++     | TRYAGAIN/TRYAGAIN'  | TRYAGAIN    | [2]    |
++     | TRYAGAIN/NOTFOUND   | TRYAGAIN    | [2]    |
++     | TRYAGAIN/UNAVAIL    | TRYAGAIN    | [2]    |
++     | TRYAGAIN'/SUCCESS   | SUCCESS     | [3]    |
++     | TRYAGAIN'/TRYAGAIN  | TRYAGAIN    | [3]    |
++     | TRYAGAIN'/TRYAGAIN' | TRYAGAIN'   | [3]    |
++     | TRYAGAIN'/NOTFOUND  | TRYAGAIN'   | [3]    |
++     | TRYAGAIN'/UNAVAIL   | UNAVAIL     | [3]    |
++     | NOTFOUND/SUCCESS    | SUCCESS     | [3]    |
++     | NOTFOUND/TRYAGAIN   | TRYAGAIN    | [3]    |
++     | NOTFOUND/TRYAGAIN'  | TRYAGAIN'   | [3]    |
++     | NOTFOUND/NOTFOUND   | NOTFOUND    | [3]    |
++     | NOTFOUND/UNAVAIL    | UNAVAIL     | [3]    |
++     | UNAVAIL/SUCCESS     | UNAVAIL     | [4]    |
++     | UNAVAIL/TRYAGAIN    | UNAVAIL     | [4]    |
++     | UNAVAIL/TRYAGAIN'   | UNAVAIL     | [4]    |
++     | UNAVAIL/NOTFOUND    | UNAVAIL     | [4]    |
++     | UNAVAIL/UNAVAIL     | UNAVAIL     | [4]    |
++     ----------------------------------------------
++
++     [1] If the first response is a success we return success.
++	 This ignores the state of the second answer and in fact
++	 incorrectly sets errno and h_errno to that of the second
++	 answer.  However because the response is a success we ignore
++	 *errnop and *h_errnop (though that means you touched errno on
++	 success).  We are being conservative here and returning the
++	 likely IPv4 response in the first answer as a success.
++
++     [2] If the first response is a recoverable TRYAGAIN we return
++	 that instead of looking at the second response.  The
++	 expectation here is that we have failed to get an IPv4 response
++	 and should retry both queries.
++
++     [3] If the first response was not a SUCCESS and the second
++	 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
++	 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
++	 result from the second response, otherwise the first responses
++	 status is used.  Again we have some odd side-effects when the
++	 second response is NOTFOUND because we overwrite *errnop and
++	 *h_errnop that means that a first answer of NOTFOUND might see
++	 its *errnop and *h_errnop values altered.  Whether it matters
++	 in practice that a first response NOTFOUND has the wrong
++	 *errnop and *h_errnop is undecided.
++
++     [4] If the first response is UNAVAIL we return that instead of
++	 looking at the second response.  The expectation here is that
++	 it will have failed similarly e.g. configuration failure.
++
++     [5] Testing this code is complicated by the fact that truncated
++	 second response buffers might be returned as SUCCESS if the
++	 first answer is a SUCCESS.  To fix this we add symmetry to
++	 TRYAGAIN with the second response.  If the second response
++	 is a recoverable error we now return TRYAGIN even if the first
++	 response was SUCCESS.  */
++
+   if (anslen1 > 0)
+     status = gaih_getanswer_slice(answer1, anslen1, qname,
+ 				  &pat, &buffer, &buflen,
+ 				  errnop, h_errnop, ttlp,
+ 				  &first);
++
+   if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
+        || (status == NSS_STATUS_TRYAGAIN
+ 	   /* We want to look at the second answer in case of an
+@@ -1260,8 +1363,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
+ 						     &pat, &buffer, &buflen,
+ 						     errnop, h_errnop, ttlp,
+ 						     &first);
++      /* Use the second response status in some cases.  */
+       if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
+ 	status = status2;
++      /* Do not return a truncated second response (unless it was
++	 unavoidable e.g. unrecoverable TRYAGAIN).  */
++      if (status == NSS_STATUS_SUCCESS
++	  && (status2 == NSS_STATUS_TRYAGAIN
++	      && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
++	status = NSS_STATUS_TRYAGAIN;
+     }
+ 
+   return status;
 diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
-index 8e80a60..13ad38c 100644
+index 8e80a60..37de664 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,
+@@ -118,18 +118,15 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
+   } net_buffer;
+   querybuf *orig_net_buffer;
+   int anslen;
+-  char *qbuf;
+   enum nss_status status;
+ 
+   if (__res_maybe_init (&_res, 0) == -1)
+     return NSS_STATUS_UNAVAIL;
+ 
+-  qbuf = strdupa (name);
+-
    net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
  
-   anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
+-  anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
 -			       1024, &net_buffer.ptr, NULL, NULL, NULL);
++  anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
 +			       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,
+@@ -205,7 +202,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,
@@ -3223,7 +3892,7 @@ index 8e80a60..13ad38c 100644
      {
        /* Nothing found.  */
 diff --git a/resolv/res_query.c b/resolv/res_query.c
-index 1325f97..c5c3402 100644
+index 1325f97..6f5280d 100644
 --- a/resolv/res_query.c
 +++ b/resolv/res_query.c
 @@ -98,7 +98,7 @@ static int
@@ -3293,7 +3962,7 @@ index 1325f97..c5c3402 100644
  		if (ret > 0 || trailing_dot)
  			return (ret);
  		saved_herrno = h_errno;
-@@ -386,11 +390,11 @@ __libc_res_nsearch(res_state statp,
+@@ -386,11 +390,12 @@ __libc_res_nsearch(res_state statp,
  			answer = *answerp;
  			anslen = MAXPACKET;
  		}
@@ -3303,11 +3972,12 @@ index 1325f97..c5c3402 100644
  		  {
  		    free (*answerp2);
  		    *answerp2 = NULL;
++		    *nanswerp2 = 0;
 +		    *answerp2_malloced = 0;
  		  }
  	}
  
-@@ -417,7 +421,7 @@ __libc_res_nsearch(res_state statp,
+@@ -417,7 +422,7 @@ __libc_res_nsearch(res_state statp,
  						      class, type,
  						      answer, anslen, answerp,
  						      answerp2, nanswerp2,
@@ -3316,7 +3986,7 @@ index 1325f97..c5c3402 100644
  			if (ret > 0)
  				return (ret);
  
-@@ -425,12 +429,11 @@ __libc_res_nsearch(res_state statp,
+@@ -425,12 +430,12 @@ __libc_res_nsearch(res_state statp,
  				answer = *answerp;
  				anslen = MAXPACKET;
  			}
@@ -3327,11 +3997,12 @@ index 1325f97..c5c3402 100644
  			  {
  			    free (*answerp2);
  			    *answerp2 = NULL;
++			    *nanswerp2 = 0;
 +			    *answerp2_malloced = 0;
  			  }
  
  			/*
-@@ -486,7 +489,8 @@ __libc_res_nsearch(res_state statp,
+@@ -486,7 +491,8 @@ __libc_res_nsearch(res_state statp,
  	    && !(tried_as_is || root_on_list)) {
  		ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
  					      answer, anslen, answerp,
@@ -3341,7 +4012,7 @@ index 1325f97..c5c3402 100644
  		if (ret > 0)
  			return (ret);
  	}
-@@ -498,10 +502,11 @@ __libc_res_nsearch(res_state statp,
+@@ -498,10 +504,12 @@ __libc_res_nsearch(res_state statp,
  	 * else send back meaningless H_ERRNO, that being the one from
  	 * the last DNSRCH we did.
  	 */
@@ -3350,11 +4021,12 @@ index 1325f97..c5c3402 100644
  	  {
  	    free (*answerp2);
  	    *answerp2 = NULL;
++	    *nanswerp2 = 0;
 +	    *answerp2_malloced = 0;
  	  }
  	if (saved_herrno != -1)
  		RES_SET_H_ERRNO(statp, saved_herrno);
-@@ -521,7 +526,7 @@ res_nsearch(res_state statp,
+@@ -521,7 +529,7 @@ res_nsearch(res_state statp,
  	    int anslen)		/* size of answer */
  {
  	return __libc_res_nsearch(statp, name, class, type, answer,
@@ -3363,7 +4035,7 @@ index 1325f97..c5c3402 100644
  }
  libresolv_hidden_def (res_nsearch)
  
-@@ -539,7 +544,8 @@ __libc_res_nquerydomain(res_state statp,
+@@ -539,7 +547,8 @@ __libc_res_nquerydomain(res_state statp,
  			u_char **answerp,
  			u_char **answerp2,
  			int *nanswerp2,
@@ -3373,7 +4045,7 @@ index 1325f97..c5c3402 100644
  {
  	char nbuf[MAXDNAME];
  	const char *longname = nbuf;
-@@ -581,7 +587,7 @@ __libc_res_nquerydomain(res_state statp,
+@@ -581,7 +590,7 @@ __libc_res_nquerydomain(res_state statp,
  	}
  	return (__libc_res_nquery(statp, longname, class, type, answer,
  				  anslen, answerp, answerp2, nanswerp2,
@@ -3382,7 +4054,7 @@ index 1325f97..c5c3402 100644
  }
  
  int
-@@ -593,7 +599,8 @@ res_nquerydomain(res_state statp,
+@@ -593,7 +602,8 @@ res_nquerydomain(res_state statp,
  	    int anslen)		/* size of answer */
  {
  	return __libc_res_nquerydomain(statp, name, domain, class, type,
@@ -3393,10 +4065,31 @@ index 1325f97..c5c3402 100644
  libresolv_hidden_def (res_nquerydomain)
  
 diff --git a/resolv/res_send.c b/resolv/res_send.c
-index 7f2e85f..416da87 100644
+index 7f2e85f..11d0bbd 100644
 --- a/resolv/res_send.c
 +++ b/resolv/res_send.c
-@@ -186,12 +186,12 @@ evNowTime(struct timespec *res) {
+@@ -1,3 +1,20 @@
++/* Copyright (C) 2016 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
+ /*
+  * Copyright (c) 1985, 1989, 1993
+  *    The Regents of the University of California.  All rights reserved.
+@@ -186,12 +203,12 @@ evNowTime(struct timespec *res) {
  static int		send_vc(res_state, const u_char *, int,
  				const u_char *, int,
  				u_char **, int *, int *, int, u_char **,
@@ -3411,7 +4104,7 @@ index 7f2e85f..416da87 100644
  #ifdef DEBUG
  static void		Aerror(const res_state, FILE *, const char *, int,
  			       const struct sockaddr *);
-@@ -343,7 +343,7 @@ int
+@@ -343,7 +360,7 @@ int
  __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,
@@ -3420,7 +4113,16 @@ index 7f2e85f..416da87 100644
  {
    int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
  
-@@ -546,7 +546,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
+@@ -360,6 +377,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
+ #ifdef USE_HOOKS
+ 	if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
+ 		if (anssiz < MAXPACKET && ansp) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *buf = malloc (MAXPACKET);
+ 			if (buf == NULL)
+ 				return (-1);
+@@ -546,7 +565,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
  			try = statp->retry;
  			n = send_vc(statp, buf, buflen, buf2, buflen2,
  				    &ans, &anssiz, &terrno,
@@ -3430,7 +4132,7 @@ index 7f2e85f..416da87 100644
  			if (n < 0)
  				return (-1);
  			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
-@@ -556,7 +557,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
+@@ -556,7 +576,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
  			n = send_dg(statp, buf, buflen, buf2, buflen2,
  				    &ans, &anssiz, &terrno,
  				    ns, &v_circuit, &gotsomewhere, ansp,
@@ -3439,7 +4141,7 @@ index 7f2e85f..416da87 100644
  			if (n < 0)
  				return (-1);
  			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
-@@ -646,7 +647,7 @@ res_nsend(res_state statp,
+@@ -646,26 +666,105 @@ res_nsend(res_state statp,
  	  const u_char *buf, int buflen, u_char *ans, int anssiz)
  {
    return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
@@ -3448,7 +4150,93 @@ index 7f2e85f..416da87 100644
  }
  libresolv_hidden_def (res_nsend)
  
-@@ -657,7 +658,7 @@ send_vc(res_state statp,
+ /* Private */
+ 
++/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
++   is not NULL, and return zero.  */
++static int
++__attribute__ ((warn_unused_result))
++close_and_return_error (res_state statp, int *resplen2)
++{
++  __res_iclose(statp, false);
++  if (resplen2 != NULL)
++    *resplen2 = 0;
++  return 0;
++}
++
++/* The send_vc function is responsible for sending a DNS query over TCP
++   to the nameserver numbered NS from the res_state STATP i.e.
++   EXT(statp).nssocks[ns].  The function supports sending both IPv4 and
++   IPv6 queries at the same serially on the same socket.
++
++   Please note that for TCP there is no way to disable sending both
++   queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
++   and sends the queries serially and waits for the result after each
++   sent query.  This implemetnation should be corrected to honour these
++   options.
++
++   Please also note that for TCP we send both queries over the same
++   socket one after another.  This technically violates best practice
++   since the server is allowed to read the first query, respond, and
++   then close the socket (to service another client).  If the server
++   does this, then the remaining second query in the socket data buffer
++   will cause the server to send the client an RST which will arrive
++   asynchronously and the client's OS will likely tear down the socket
++   receive buffer resulting in a potentially short read and lost
++   response data.  This will force the client to retry the query again,
++   and this process may repeat until all servers and connection resets
++   are exhausted and then the query will fail.  It's not known if this
++   happens with any frequency in real DNS server implementations.  This
++   implementation should be corrected to use two sockets by default for
++   parallel queries.
++
++   The query stored in BUF of BUFLEN length is sent first followed by
++   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
++   serially on the same socket.
++
++   Answers to the query are stored firstly in *ANSP up to a max of
++   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
++   is non-NULL (to indicate that modifying the answer buffer is allowed)
++   then malloc is used to allocate a new response buffer and ANSCP and
++   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
++   are needed but ANSCP is NULL, then as much of the response as
++   possible is read into the buffer, but the results will be truncated.
++   When truncation happens because of a small answer buffer the DNS
++   packets header feild TC will bet set to 1, indicating a truncated
++   message and the rest of the socket data will be read and discarded.
++
++   Answers to the query are stored secondly in *ANSP2 up to a max of
++   *ANSSIZP2 bytes, with the actual response length stored in
++   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
++   is non-NULL (required for a second query) then malloc is used to
++   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
++   size and *ANSP2_MALLOCED is set to 1.
++
++   The ANSP2_MALLOCED argument will eventually be removed as the
++   change in buffer pointer can be used to detect the buffer has
++   changed and that the caller should use free on the new buffer.
++
++   Note that the answers may arrive in any order from the server and
++   therefore the first and second answer buffers may not correspond to
++   the first and second queries.
++
++   It is not supported to call this function with a non-NULL ANSP2
++   but a NULL ANSCP.  Put another way, you can call send_vc with a
++   single unmodifiable buffer or two modifiable buffers, but no other
++   combination is supported.
++
++   It is the caller's responsibility to free the malloc allocated
++   buffers by detecting that the pointers have changed from their
++   original values i.e. *ANSCP or *ANSP2 has changed.
++
++   If errors are encountered then *TERRNO is set to an appropriate
++   errno value and a zero result is returned for a recoverable error,
++   and a less-than zero result is returned for a non-recoverable error.
++
++   If no errors are encountered then *TERRNO is left unmodified and
++   a the length of the first response in bytes is returned.  */
+ static int
+ send_vc(res_state statp,
  	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,
@@ -3457,16 +4245,159 @@ index 7f2e85f..416da87 100644
  {
  	const HEADER *hp = (HEADER *) buf;
  	const HEADER *hp2 = (HEADER *) buf2;
-@@ -823,6 +824,8 @@ send_vc(res_state statp,
+-	u_char *ans = *ansp;
+-	int orig_anssizp = *anssizp;
+-	// XXX REMOVE
+-	// int anssiz = *anssizp;
+-	HEADER *anhp = (HEADER *) ans;
++	HEADER *anhp = (HEADER *) *ansp;
+ 	struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
+ 	int truncating, connreset, resplen, n;
+ 	struct iovec iov[4];
+@@ -741,6 +840,8 @@ send_vc(res_state statp,
+ 	 * Receive length & response
+ 	 */
+ 	int recvresp1 = 0;
++	/* Skip the second response if there is no second query.
++	   To do that we mark the second response as received.  */
+ 	int recvresp2 = buf2 == NULL;
+ 	uint16_t rlen16;
+  read_len:
+@@ -777,33 +878,14 @@ send_vc(res_state statp,
+ 	u_char **thisansp;
+ 	int *thisresplenp;
+ 	if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
++		/* We have not received any responses
++		   yet or we only have one response to
++		   receive.  */
+ 		thisanssizp = anssizp;
+ 		thisansp = anscp ?: ansp;
+ 		assert (anscp != NULL || ansp2 == NULL);
+ 		thisresplenp = &resplen;
+ 	} else {
+-		if (*anssizp != MAXPACKET) {
+-			/* No buffer allocated for the first
+-			   reply.  We can try to use the rest
+-			   of the user-provided buffer.  */
+-#ifdef _STRING_ARCH_unaligned
+-			*anssizp2 = orig_anssizp - resplen;
+-			*ansp2 = *ansp + resplen;
+-#else
+-			int aligned_resplen
+-			  = ((resplen + __alignof__ (HEADER) - 1)
+-			     & ~(__alignof__ (HEADER) - 1));
+-			*anssizp2 = orig_anssizp - aligned_resplen;
+-			*ansp2 = *ansp + aligned_resplen;
+-#endif
+-		} else {
+-			/* The first reply did not fit into the
+-			   user-provided buffer.  Maybe the second
+-			   answer will.  */
+-			*anssizp2 = orig_anssizp;
+-			*ansp2 = *ansp;
+-		}
+-
+ 		thisanssizp = anssizp2;
+ 		thisansp = ansp2;
+ 		thisresplenp = resplen2;
+@@ -811,10 +893,14 @@ send_vc(res_state statp,
+ 	anhp = (HEADER *) *thisansp;
+ 
+ 	*thisresplenp = rlen;
+-	if (rlen > *thisanssizp) {
+-		/* Yes, we test ANSCP here.  If we have two buffers
+-		   both will be allocatable.  */
+-		if (__builtin_expect (anscp != NULL, 1)) {
++	/* Is the answer buffer too small?  */
++	if (*thisanssizp < rlen) {
++		/* If the current buffer is non-NULL and it's not
++		   pointing at the static user-supplied buffer then
++		   we can reallocate it.  */
++		if (thisansp != NULL && thisansp != ansp) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *newp = malloc (MAXPACKET);
+ 			if (newp == NULL) {
+ 				*terrno = ENOMEM;
+@@ -823,7 +909,12 @@ send_vc(res_state statp,
  			}
  			*thisanssizp = MAXPACKET;
  			*thisansp = newp;
 +			if (thisansp == ansp2)
 +			  *ansp2_malloced = 1;
  			anhp = (HEADER *) newp;
++			/* A uint16_t can't be larger than MAXPACKET
++			   thus it's safe to allocate MAXPACKET but
++			   read RLEN bytes instead.  */
  			len = rlen;
  		} else {
-@@ -992,7 +995,7 @@ send_dg(res_state statp,
+ 			Dprint(statp->options & RES_DEBUG,
+@@ -987,17 +1078,75 @@ reopen (res_state statp, int *terrno, int ns)
+ 	return 1;
+ }
+ 
++/* The send_dg function is responsible for sending a DNS query over UDP
++   to the nameserver numbered NS from the res_state STATP i.e.
++   EXT(statp).nssocks[ns].  The function supports IPv4 and IPv6 queries
++   along with the ability to send the query in parallel for both stacks
++   (default) or serially (RES_SINGLKUP).  It also supports serial lookup
++   with a close and reopen of the socket used to talk to the server
++   (RES_SNGLKUPREOP) to work around broken name servers.
++
++   The query stored in BUF of BUFLEN length is sent first followed by
++   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
++   in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
++
++   Answers to the query are stored firstly in *ANSP up to a max of
++   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
++   is non-NULL (to indicate that modifying the answer buffer is allowed)
++   then malloc is used to allocate a new response buffer and ANSCP and
++   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
++   are needed but ANSCP is NULL, then as much of the response as
++   possible is read into the buffer, but the results will be truncated.
++   When truncation happens because of a small answer buffer the DNS
++   packets header feild TC will bet set to 1, indicating a truncated
++   message, while the rest of the UDP packet is discarded.
++
++   Answers to the query are stored secondly in *ANSP2 up to a max of
++   *ANSSIZP2 bytes, with the actual response length stored in
++   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
++   is non-NULL (required for a second query) then malloc is used to
++   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
++   size and *ANSP2_MALLOCED is set to 1.
++
++   The ANSP2_MALLOCED argument will eventually be removed as the
++   change in buffer pointer can be used to detect the buffer has
++   changed and that the caller should use free on the new buffer.
++
++   Note that the answers may arrive in any order from the server and
++   therefore the first and second answer buffers may not correspond to
++   the first and second queries.
++
++   It is not supported to call this function with a non-NULL ANSP2
++   but a NULL ANSCP.  Put another way, you can call send_vc with a
++   single unmodifiable buffer or two modifiable buffers, but no other
++   combination is supported.
++
++   It is the caller's responsibility to free the malloc allocated
++   buffers by detecting that the pointers have changed from their
++   original values i.e. *ANSCP or *ANSP2 has changed.
++
++   If an answer is truncated because of UDP datagram DNS limits then
++   *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
++   the caller to retry with TCP.  The value *GOTSOMEWHERE is set to 1
++   if any progress was made reading a response from the nameserver and
++   is used by the caller to distinguish between ECONNREFUSED and
++   ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
++
++   If errors are encountered then *TERRNO is set to an appropriate
++   errno value and a zero result is returned for a recoverable error,
++   and a less-than zero result is returned for a non-recoverable error.
++
++   If no errors are encountered then *TERRNO is left unmodified and
++   a the length of the first response in bytes is returned.  */
+ static int
+ send_dg(res_state statp,
  	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,
@@ -3475,23 +4406,574 @@ index 7f2e85f..416da87 100644
  {
  	const HEADER *hp = (HEADER *) buf;
  	const HEADER *hp2 = (HEADER *) buf2;
-@@ -1238,6 +1241,8 @@ send_dg(res_state statp,
+-	u_char *ans = *ansp;
+-	int orig_anssizp = *anssizp;
+ 	struct timespec now, timeout, finish;
+ 	struct pollfd pfd[1];
+ 	int ptimeout;
+@@ -1022,7 +1171,11 @@ send_dg(res_state statp,
+  retry_reopen:
+ 	retval = reopen (statp, terrno, ns);
+ 	if (retval <= 0)
+-		return retval;
++	  {
++	    if (resplen2 != NULL)
++	      *resplen2 = 0;
++	    return retval;
++	  }
+  retry:
+ 	evNowTime(&now);
+ 	evConsTime(&timeout, seconds, 0);
+@@ -1030,11 +1183,11 @@ send_dg(res_state statp,
+ 	int need_recompute = 0;
+ 	int nwritten = 0;
+ 	int recvresp1 = 0;
++	/* Skip the second response if there is no second query.
++           To do that we mark the second response as received.  */
+ 	int recvresp2 = buf2 == NULL;
+ 	pfd[0].fd = EXT(statp).nssocks[ns];
+ 	pfd[0].events = POLLOUT;
+-	if (resplen2 != NULL)
+-	  *resplen2 = 0;
+  wait:
+ 	if (need_recompute) {
+ 	recompute_resend:
+@@ -1042,9 +1195,7 @@ send_dg(res_state statp,
+ 		if (evCmpTime(finish, now) <= 0) {
+ 		poll_err_out:
+ 			Perror(statp, stderr, "poll", errno);
+-		err_out:
+-			__res_iclose(statp, false);
+-			return (0);
++			return close_and_return_error (statp, resplen2);
+ 		}
+ 		evSubTime(&timeout, &finish, &now);
+ 		need_recompute = 0;
+@@ -1091,7 +1242,9 @@ send_dg(res_state statp,
+ 		  }
+ 
+ 		*gotsomewhere = 1;
+-		return (0);
++		if (resplen2 != NULL)
++		  *resplen2 = 0;
++		return 0;
+ 	}
+ 	if (n < 0) {
+ 		if (errno == EINTR)
+@@ -1159,7 +1312,7 @@ send_dg(res_state statp,
+ 
+ 		      fail_sendmmsg:
+ 			Perror(statp, stderr, "sendmmsg", errno);
+-			goto err_out;
++			return close_and_return_error (statp, resplen2);
+ 		      }
+ 		  }
+ 		else
+@@ -1177,7 +1330,7 @@ send_dg(res_state statp,
+ 		      if (errno == EINTR || errno == EAGAIN)
+ 			goto recompute_resend;
+ 		      Perror(statp, stderr, "send", errno);
+-		      goto err_out;
++		      return close_and_return_error (statp, resplen2);
+ 		    }
+ 		  just_one:
+ 		    if (nwritten != 0 || buf2 == NULL || single_request)
+@@ -1193,53 +1346,56 @@ send_dg(res_state statp,
+ 		int *thisresplenp;
+ 
+ 		if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
++			/* We have not received any responses
++			   yet or we only have one response to
++			   receive.  */
+ 			thisanssizp = anssizp;
+ 			thisansp = anscp ?: ansp;
+ 			assert (anscp != NULL || ansp2 == NULL);
+ 			thisresplenp = &resplen;
+ 		} else {
+-			if (*anssizp != MAXPACKET) {
+-				/* No buffer allocated for the first
+-				   reply.  We can try to use the rest
+-				   of the user-provided buffer.  */
+-#ifdef _STRING_ARCH_unaligned
+-				*anssizp2 = orig_anssizp - resplen;
+-				*ansp2 = *ansp + resplen;
+-#else
+-				int aligned_resplen
+-				  = ((resplen + __alignof__ (HEADER) - 1)
+-				     & ~(__alignof__ (HEADER) - 1));
+-				*anssizp2 = orig_anssizp - aligned_resplen;
+-				*ansp2 = *ansp + aligned_resplen;
+-#endif
+-			} else {
+-				/* The first reply did not fit into the
+-				   user-provided buffer.  Maybe the second
+-				   answer will.  */
+-				*anssizp2 = orig_anssizp;
+-				*ansp2 = *ansp;
+-			}
+-
+ 			thisanssizp = anssizp2;
+ 			thisansp = ansp2;
+ 			thisresplenp = resplen2;
+ 		}
+ 
+ 		if (*thisanssizp < MAXPACKET
+-		    /* Yes, we test ANSCP here.  If we have two buffers
+-		       both will be allocatable.  */
+-		    && anscp
++		    /* If the current buffer is non-NULL and it's not
++		       pointing at the static user-supplied buffer then
++		       we can reallocate it.  */
++		    && (thisansp != NULL && thisansp != ansp)
+ #ifdef FIONREAD
++		    /* Is the size too small?  */
+ 		    && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
+ 			|| *thisanssizp < *thisresplenp)
+ #endif
+                     ) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *newp = malloc (MAXPACKET);
  			if (newp != NULL) {
- 				*anssizp = MAXPACKET;
- 				*thisansp = ans = newp;
+-				*anssizp = MAXPACKET;
+-				*thisansp = ans = newp;
++				*thisanssizp = MAXPACKET;
++				*thisansp = newp;
 +				if (thisansp == ansp2)
 +				  *ansp2_malloced = 1;
  			}
  		}
++		/* We could end up with truncation if anscp was NULL
++		   (not allowed to change caller's buffer) and the
++		   response buffer size is too small.  This isn't a
++		   reliable way to detect truncation because the ioctl
++		   may be an inaccurate report of the UDP message size.
++		   Therefore we use this only to issue debug output.
++		   To do truncation accurately with UDP we need
++		   MSG_TRUNC which is only available on Linux.  We
++		   can abstract out the Linux-specific feature in the
++		   future to detect truncation.  */
++		if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
++			Dprint(statp->options & RES_DEBUG,
++			       (stdout, ";; response may be truncated (UDP)\n")
++			);
++		}
++
  		HEADER *anhp = (HEADER *) *thisansp;
-@@ -1405,6 +1410,7 @@ send_dg(res_state statp,
+ 		socklen_t fromlen = sizeof(struct sockaddr_in6);
+ 		assert (sizeof(from) <= fromlen);
+@@ -1252,7 +1408,7 @@ send_dg(res_state statp,
+ 				goto wait;
+ 			}
+ 			Perror(statp, stderr, "recvfrom", errno);
+-			goto err_out;
++			return close_and_return_error (statp, resplen2);
+ 		}
+ 		*gotsomewhere = 1;
+ 		if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
+@@ -1263,7 +1419,7 @@ send_dg(res_state statp,
+ 			       (stdout, ";; undersized: %d\n",
+ 				*thisresplenp));
+ 			*terrno = EMSGSIZE;
+-			goto err_out;
++			return close_and_return_error (statp, resplen2);
+ 		}
+ 		if ((recvresp1 || hp->id != anhp->id)
+ 		    && (recvresp2 || hp2->id != anhp->id)) {
+@@ -1312,7 +1468,7 @@ send_dg(res_state statp,
+ 				? *thisanssizp : *thisresplenp);
+ 			/* record the error */
+ 			statp->_flags |= RES_F_EDNS0ERR;
+-			goto err_out;
++			return close_and_return_error (statp, resplen2);
+ 	}
+ #endif
+ 		if (!(statp->options & RES_INSECURE2)
+@@ -1364,10 +1520,10 @@ send_dg(res_state statp,
+ 			  }
+ 
+ 		next_ns:
+-			__res_iclose(statp, false);
+ 			/* don't retry if called from dig */
+ 			if (!statp->pfcode)
+-				return (0);
++			  return close_and_return_error (statp, resplen2);
++			__res_iclose(statp, false);
+ 		}
+ 		if (anhp->rcode == NOERROR && anhp->ancount == 0
+ 		    && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
+@@ -1389,6 +1545,8 @@ send_dg(res_state statp,
+ 			__res_iclose(statp, false);
+ 			// XXX if we have received one reply we could
+ 			// XXX use it and not repeat it over TCP...
++			if (resplen2 != NULL)
++			  *resplen2 = 0;
+ 			return (1);
+ 		}
+ 		/* Mark which reply we received.  */
+@@ -1404,20 +1562,22 @@ send_dg(res_state statp,
+ 					__res_iclose (statp, false);
  					retval = reopen (statp, terrno, ns);
  					if (retval <= 0)
- 						return retval;
+-						return retval;
++					  {
++					    if (resplen2 != NULL)
++					      *resplen2 = 0;
++					    return retval;
++					  }
 +					pfd[0].fd = EXT(statp).nssocks[ns];
  				}
  			}
  			goto wait;
+ 		}
+-		/*
+-		 * All is well, or the error is fatal.  Signal that the
+-		 * next nameserver ought not be tried.
+-		 */
++		/* All is well.  We have received both responses (if
++		   two responses were requested).  */
+ 		return (resplen);
+-	} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
+-		/* Something went wrong.  We can stop trying.  */
+-		goto err_out;
+-	}
++	} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
++	  /* Something went wrong.  We can stop trying.  */
++	  return close_and_return_error (statp, resplen2);
+ 	else {
+ 		/* poll should not have returned > 0 in this case.  */
+ 		abort ();
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index 1be16eb..8a34b83 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -64,11 +64,11 @@ test-srcs	:= tst-fmtmsg
+ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
+ 		   test-canon test-canon2 tst-strtoll tst-environ	    \
+ 		   tst-xpg-basename tst-random tst-random2 tst-bsearch	    \
+-		   tst-limits tst-rand48 bug-strtod tst-setcontext	    \
+-		   test-a64l tst-qsort tst-system testmb2 bug-strtod2	    \
+-		   tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
+-		   tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2	    \
+-		   tst-makecontext2 tst-strtod6 tst-unsetenv1		    \
++		   tst-limits tst-rand48 bug-strtod tst-setcontext          \
++		   tst-setcontext2 test-a64l tst-qsort tst-system testmb2   \
++		   bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3  \
++		   tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5     \
++		   tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1    \
+ 		   tst-makecontext3 bug-getcontext bug-fmtmsg1		    \
+ 		   tst-secure-getenv tst-strtod-overflow tst-strtod-round   \
+ 		   tst-tininess tst-strtod-underflow tst-tls-atexit
+@@ -164,3 +164,5 @@ tst-tls-atexit-lib.so-no-z-defs = yes
+ $(objpfx)tst-tls-atexit: $(common-objpfx)nptl/libpthread.so \
+ 			 $(common-objpfx)dlfcn/libdl.so
+ $(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
++
++$(objpfx)tst-makecontext: $(libdl)
+diff --git a/stdlib/tst-makecontext.c b/stdlib/tst-makecontext.c
+index 7968a6d..ef1e27a 100644
+--- a/stdlib/tst-makecontext.c
++++ b/stdlib/tst-makecontext.c
+@@ -19,23 +19,62 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <ucontext.h>
++#include <assert.h>
++#include <unwind.h>
++#include <dlfcn.h>
++#include <gnu/lib-names.h>
+ 
+ ucontext_t ucp;
+-char st1[8192];
++char st1[16384];
+ __thread int thr;
+ 
+ int somevar = -76;
+ long othervar = -78L;
+ 
++struct trace_arg
++{
++  int cnt, size;
++};
++
++static _Unwind_Reason_Code
++backtrace_helper (struct _Unwind_Context *ctx, void *a)
++{
++  struct trace_arg *arg = a;
++  if (++arg->cnt == arg->size)
++    return _URC_END_OF_STACK;
++  return _URC_NO_REASON;
++}
++
+ void
+ cf (int i)
+ {
++  struct trace_arg arg = { .size = 100, .cnt = -1 };
++  void *handle;
++  _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
++
+   if (i != othervar || thr != 94)
+     {
+       printf ("i %d thr %d\n", i, thr);
+       exit (1);
+     }
+ 
++  /* Test if callback function of _Unwind_Backtrace is not called infinitely
++     times. See Bug 18508 or gcc bug "Bug 66303 - runtime.Caller() returns
++     infinitely deep stack frames on s390x.".
++     The go runtime calls backtrace_full() in
++     <gcc-src>/libbacktrace/backtrace.c, which uses _Unwind_Backtrace().  */
++  handle = dlopen (LIBGCC_S_SO, RTLD_LAZY);
++  if (handle != NULL)
++    {
++      unwind_backtrace = dlsym (handle, "_Unwind_Backtrace");
++      if (unwind_backtrace != NULL)
++	{
++	  unwind_backtrace (backtrace_helper, &arg);
++	  assert (arg.cnt != -1 && arg.cnt < 100);
++	}
++      dlclose (handle);
++    }
++
+   /* Since uc_link below has been set to NULL, setcontext is supposed to
+      terminate the process normally after this function returns.  */
+ }
+diff --git a/stdlib/tst-setcontext2.c b/stdlib/tst-setcontext2.c
+new file mode 100644
+index 0000000..8582cc0
+--- /dev/null
++++ b/stdlib/tst-setcontext2.c
+@@ -0,0 +1,230 @@
++/* Testcase checks, if setcontext(), swapcontext() restores signal-mask
++   and if pending signals are delivered after those calls.
++   Copyright (C) 2015 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <ucontext.h>
++#include <unistd.h>
++
++volatile int global;
++volatile sig_atomic_t handlerCalled;
++
++static void
++check (const char *funcName)
++{
++  sigset_t set;
++
++  /* check if SIGUSR2 is unblocked after setcontext-call.  */
++  sigprocmask (SIG_BLOCK, NULL, &set);
++
++  if (sigismember (&set, SIGUSR2) != 0)
++    {
++      printf ("FAIL: SIGUSR2 is blocked after %s.\n", funcName);
++      exit (1);
++    }
++
++  if (sigismember (&set, SIGUSR1) != 1)
++    {
++      printf ("FAIL: SIGUSR1 is not blocked after %s.\n", funcName);
++      exit (1);
++    }
++}
++
++static void
++signalmask (int how, int signum)
++{
++  sigset_t set;
++  sigemptyset (&set);
++  sigaddset (&set, signum);
++  if (sigprocmask (how, &set, NULL) != 0)
++    {
++      printf ("FAIL: sigprocmaks (%d, %d, NULL): %m\n", how, signum);
++      exit (1);
++    }
++}
++
++static void
++signalpending (int signum, const char *msg)
++{
++  sigset_t set;
++  sigemptyset (&set);
++  if (sigpending (&set) != 0)
++    {
++      printf ("FAIL: sigpending: %m\n");
++      exit (1);
++    }
++  if (sigismember (&set, SIGUSR2) != 1)
++    {
++      printf ("FAIL: Signal %d is not pending %s\n", signum, msg);
++      exit (1);
++    }
++}
++
++static void
++handler (int __attribute__ ((unused)) signum)
++{
++  handlerCalled ++;
++}
++
++static int
++do_test (void)
++{
++  ucontext_t ctx, oldctx;
++  struct sigaction action;
++  pid_t pid;
++
++  pid = getpid ();
++
++  /* unblock SIGUSR2 */
++  signalmask (SIG_UNBLOCK, SIGUSR2);
++
++  /* block SIGUSR1 */
++  signalmask (SIG_BLOCK, SIGUSR1);
++
++  /* register handler for SIGUSR2  */
++  action.sa_flags = 0;
++  action.sa_handler = handler;
++  sigemptyset (&action.sa_mask);
++  sigaction (SIGUSR2, &action, NULL);
++
++  if (getcontext (&ctx) != 0)
++    {
++      printf ("FAIL: getcontext: %m\n");
++      exit (1);
++    }
++
++  global++;
++
++  if (global == 1)
++    {
++      puts ("after getcontext");
++
++      /* block SIGUSR2  */
++      signalmask (SIG_BLOCK, SIGUSR2);
++
++      /* send SIGUSR2 to me  */
++      handlerCalled = 0;
++      kill (pid, SIGUSR2);
++
++      /* was SIGUSR2 handler called?  */
++      if (handlerCalled != 0)
++	{
++	  puts ("FAIL: signal handler was called, but signal was blocked.");
++	  exit (1);
++	}
++
++      /* is SIGUSR2 pending?  */
++      signalpending (SIGUSR2, "before setcontext");
++
++      /* SIGUSR2 will be unblocked by setcontext-call.  */
++      if (setcontext (&ctx) != 0)
++	{
++	  printf ("FAIL: setcontext: %m\n");
++	  exit (1);
++	}
++    }
++  else if (global == 2)
++    {
++      puts ("after setcontext");
++
++      /* check SIGUSR1/2  */
++      check ("setcontext");
++
++      /* was SIGUSR2 handler called? */
++      if (handlerCalled != 1)
++	{
++	  puts ("FAIL: signal handler was not called after setcontext.");
++	  exit (1);
++	}
++
++      /* block SIGUSR2 */
++      signalmask (SIG_BLOCK, SIGUSR2);
++
++      /* send SIGUSR2 to me  */
++      handlerCalled = 0;
++      kill (pid, SIGUSR2);
++
++      /* was SIGUSR2 handler called?  */
++      if (handlerCalled != 0)
++	{
++	  puts ("FAIL: signal handler was called, but signal was blocked.");
++	  exit (1);
++	}
++
++      /* is SIGUSR2 pending?  */
++      signalpending (SIGUSR2, "before swapcontext");
++
++      if (swapcontext (&oldctx, &ctx) != 0)
++	{
++	  printf ("FAIL: swapcontext: %m\n");
++	  exit (1);
++	}
++
++      puts ("after returned from swapcontext");
++
++      if (global != 3)
++	{
++	  puts ("FAIL: returned from swapcontext without ctx-context called.");
++	  exit (1);
++	}
++
++      puts ("test succeeded");
++      return 0;
++    }
++  else if ( global != 3 )
++    {
++      puts ("FAIL: 'global' not incremented three times");
++      exit (1);
++    }
++
++  puts ("after swapcontext");
++  /* check SIGUSR1/2  */
++  check ("swapcontext");
++
++  /* was SIGUSR2 handler called? */
++  if (handlerCalled != 1)
++    {
++      puts ("FAIL: signal handler was not called after swapcontext.");
++      exit (1);
++    }
++
++  /* check sigmask in old context of swapcontext-call  */
++  if (sigismember (&oldctx.uc_sigmask, SIGUSR2) != 1)
++    {
++      puts ("FAIL: SIGUSR2 is not blocked in oldctx.uc_sigmask.");
++      exit (1);
++    }
++
++  if (sigismember (&oldctx.uc_sigmask, SIGUSR1) != 1)
++    {
++      puts ("FAIL: SIGUSR1 is not blocked in oldctx.uc_sigmaks.");
++      exit (1);
++    }
++
++  /* change to old context, which was gathered by swapcontext() call.  */
++  setcontext (&oldctx);
++
++  puts ("FAIL: returned from setcontext (&oldctx)");
++  exit (1);
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
 diff --git a/string/test-strcmp.c b/string/test-strcmp.c
 index b395dc7..fcd059f 100644
 --- a/string/test-strcmp.c
@@ -3586,10 +5068,171 @@ index 6105e9f..50109b8 100644
  	      cor = (cor > 0) ? 1.035 * cor + eps : 1.035 * cor - eps;
  	      retval = ((res == res + cor) ? ((m) ? res : -res)
 diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
-index 8218237..d2283bc 100644
+index 8218237..df6ce8b 100644
 --- a/sysdeps/posix/getaddrinfo.c
 +++ b/sysdeps/posix/getaddrinfo.c
-@@ -712,6 +712,18 @@ gaih_inet (const char *name, const struct gaih_service *service,
+@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
+   return 0;
+ }
+ 
++/* Convert struct hostent to a list of struct gaih_addrtuple objects.
++   h_name is not copied, and the struct hostent object must not be
++   deallocated prematurely.  *RESULT must be NULL or a pointer to an
++   object allocated using malloc, which is freed.  */
++static bool
++convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
++				   int family,
++				   struct hostent *h,
++				   struct gaih_addrtuple **result)
++{
++  free (*result);
++  *result = NULL;
++
++  /* Count the number of addresses in h->h_addr_list.  */
++  size_t count = 0;
++  for (char **p = h->h_addr_list; *p != NULL; ++p)
++    ++count;
++
++  /* Report no data if no addresses are available, or if the incoming
++     address size is larger than what we can store.  */
++  if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
++    return true;
++
++  struct gaih_addrtuple *array = calloc (count, sizeof (*array));
++  if (array == NULL)
++    return false;
++
++  for (size_t i = 0; i < count; ++i)
++    {
++      if (family == AF_INET && req->ai_family == AF_INET6)
++	{
++	  /* Perform address mapping. */
++	  array[i].family = AF_INET6;
++	  memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
++	  array[i].addr[2] = htonl (0xffff);
++	}
++      else
++	{
++	  array[i].family = family;
++	  memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
++	}
++      array[i].next = array + i + 1;
++    }
++  array[0].name = h->h_name;
++  array[count - 1].next = NULL;
++
++  *result = array;
++  return true;
++}
++
+ #define gethosts(_family, _type) \
+  {									      \
+-  int i;								      \
+   int herrno;								      \
+   struct hostent th;							      \
+   struct hostent *h;							      \
+@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
+     }									      \
+   else if (h != NULL)							      \
+     {									      \
+-      for (i = 0; h->h_addr_list[i]; i++)				      \
++      /* Make sure that addrmem can be freed.  */			      \
++      if (!malloc_addrmem)						      \
++	addrmem = NULL;							      \
++      if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem))      \
+ 	{								      \
+-	  if (*pat == NULL)						      \
+-	    {								      \
+-	      *pat = __alloca (sizeof (struct gaih_addrtuple));		      \
+-	      (*pat)->scopeid = 0;					      \
+-	    }								      \
+-	  uint32_t *addr = (*pat)->addr;				      \
+-	  (*pat)->next = NULL;						      \
+-	  (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;		      \
+-	  if (_family == AF_INET && req->ai_family == AF_INET6)		      \
+-	    {								      \
+-	      (*pat)->family = AF_INET6;				      \
+-	      addr[3] = *(uint32_t *) h->h_addr_list[i];		      \
+-	      addr[2] = htonl (0xffff);					      \
+-	      addr[1] = 0;						      \
+-	      addr[0] = 0;						      \
+-	    }								      \
+-	  else								      \
+-	    {								      \
+-	      (*pat)->family = _family;					      \
+-	      memcpy (addr, h->h_addr_list[i], sizeof(_type));		      \
+-	    }								      \
+-	  pat = &((*pat)->next);					      \
++	  _res.options |= old_res_options & RES_USE_INET6;		      \
++	  result = -EAI_SYSTEM;						      \
++	  goto free_and_return;						      \
+ 	}								      \
++      *pat = addrmem;							      \
++      /* The conversion uses malloc unconditionally.  */		      \
++      malloc_addrmem = true;						      \
+ 									      \
+       if (localcanon !=	NULL && canon == NULL)				      \
+ 	canon = strdupa (localcanon);					      \
+ 									      \
+-      if (_family == AF_INET6 && i > 0)					      \
++      if (_family == AF_INET6 && *pat != NULL)				      \
+ 	got_ipv6 = true;						      \
+     }									      \
+  }
+@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ 		{
+ 		  if (h != NULL)
+ 		    {
+-		      int i;
+-		      /* We found data, count the number of addresses.  */
+-		      for (i = 0; h->h_addr_list[i]; ++i)
+-			;
+-		      if (i > 0 && *pat != NULL)
+-			--i;
+-
+-		      if (__libc_use_alloca (alloca_used
+-					     + i * sizeof (struct gaih_addrtuple)))
+-			addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
+-						  alloca_used);
+-		      else
++		      /* We found data, convert it.  */
++		      if (!convert_hostent_to_gaih_addrtuple
++			  (req, AF_INET, h, &addrmem))
+ 			{
+-			  addrmem = malloc (i
+-					    * sizeof (struct gaih_addrtuple));
+-			  if (addrmem == NULL)
+-			    {
+-			      result = -EAI_MEMORY;
+-			      goto free_and_return;
+-			    }
+-			  malloc_addrmem = true;
+-			}
+-
+-		      /* Now convert it into the list.  */
+-		      struct gaih_addrtuple *addrfree = addrmem;
+-		      for (i = 0; h->h_addr_list[i]; ++i)
+-			{
+-			  if (*pat == NULL)
+-			    {
+-			      *pat = addrfree++;
+-			      (*pat)->scopeid = 0;
+-			    }
+-			  (*pat)->next = NULL;
+-			  (*pat)->family = AF_INET;
+-			  memcpy ((*pat)->addr, h->h_addr_list[i],
+-				  h->h_length);
+-			  pat = &((*pat)->next);
++			  result = -EAI_MEMORY;
++			  goto free_and_return;
+ 			}
++		      *pat = addrmem;
++		      /* The conversion uses malloc unconditionally.  */
++		      malloc_addrmem = true;
+ 		    }
+ 		}
+ 	      else
+@@ -712,6 +720,18 @@ gaih_inet (const char *name, const struct gaih_service *service,
  		    {
  		      socklen_t size = (air->family[i] == AF_INET
  					? INADDRSZ : IN6ADDRSZ);
@@ -4963,6 +6606,48 @@ index 8925396..f32b0fc 100644
  	cmp	rTMP1, rSTRXOR
  	retl
  	 movgu	%xcc, 0, %o0
+diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c
+index b4fcd1a..802c957 100644
+--- a/sysdeps/unix/sysv/linux/i386/glob64.c
++++ b/sysdeps/unix/sysv/linux/i386/glob64.c
+@@ -1,3 +1,21 @@
++/* Two glob variants with 64-bit support, for dirent64 and __olddirent64.
++   Copyright (C) 1998-2016 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
+ #include <dirent.h>
+ #include <glob.h>
+ #include <sys/stat.h>
+@@ -38,11 +56,15 @@ int __old_glob64 (const char *__pattern, int __flags,
+ 
+ #undef dirent
+ #define dirent __old_dirent64
++#undef GL_READDIR
++# define GL_READDIR(pglob, stream) \
++  ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
+ #undef __readdir
+ #define __readdir(dirp) __old_readdir64 (dirp)
+ #undef glob
+ #define glob(pattern, flags, errfunc, pglob) \
+   __old_glob64 (pattern, flags, errfunc, pglob)
++#define convert_dirent __old_convert_dirent
+ #define glob_in_dir __old_glob_in_dir
+ #define GLOB_ATTRIBUTE attribute_compat_text_section
+ 
 diff --git a/sysdeps/unix/sysv/linux/s390/Makefile b/sysdeps/unix/sysv/linux/s390/Makefile
 index f91179d..45b1922 100644
 --- a/sysdeps/unix/sysv/linux/s390/Makefile
@@ -5145,6 +6830,25 @@ index a1b7a6a..e74f335 100644
 -# endif
 -#endif /* !NOT_IN_libc */
 +#include "__longjmp.c"
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S b/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
+index 83cf0d8..67ea206 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
++++ b/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
+@@ -17,6 +17,14 @@
+ 
+ #include <sysdep.h>
+ 
++/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
++   if backtrace was called within a context created by makecontext. (There
++   is also no .eh_frame info for _start or thread_start.)  */
++#undef cfi_startproc
++#define cfi_startproc
++#undef cfi_endproc
++#define cfi_endproc
++
+ ENTRY(__makecontext_ret)
+ 	basr  %r14,%r7
+ 	ltr   %r8,%r8			/* Check whether uc_link is 0.  */
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S b/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S
 deleted file mode 100644
 index 4992030..0000000
@@ -5368,9 +7072,18 @@ index 03f2e83..0194f0b 100644
   _longjmp F
   _setjmp F
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
-index fbe8b77..42839e2 100644
+index fbe8b77..b263773 100644
 --- a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
 +++ b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
+@@ -34,7 +34,7 @@ ENTRY(__setcontext)
+ 	lr	%r1,%r2
+ 
+ 	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
+-	la      %r2,SIG_BLOCK
++	la      %r2,SIG_SETMASK
+ 	la	%r3,SC_MASK(%r1)
+ 	slr	%r4,%r4
+ 	lhi	%r5,_NSIG8
 @@ -62,16 +62,8 @@ ENTRY(__setcontext)
  	/* Don't touch %a0, used for thread purposes.  */
  	lam	%a1,%a15,SC_ACRS+4(%r1)
@@ -5390,10 +7103,33 @@ index fbe8b77..42839e2 100644
  	/* Return.  */
  	br	%r14
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
-index 41ede4b..9206aa3 100644
+index 41ede4b..8f9cfd8 100644
 --- a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
 +++ b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
-@@ -65,31 +65,19 @@ ENTRY(__swapcontext)
+@@ -24,7 +24,7 @@
+ /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
+ 
+   Saves the machine context in oucp such that when it is activated,
+-  it appears as if __swapcontextt() returned again, restores the
++  it appears as if __swapcontext() returned again, restores the
+   machine context in ucp and thereby resumes execution in that
+   context.
+ 
+@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
+ 	lr	%r1,%r2
+ 	lr      %r0,%r3
+ 
+-	/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
+-	la      %r2,SIG_BLOCK
+-	slr	%r3,%r3
+-	la	%r4,SC_MASK(%r1)
+-	lhi	%r5,_NSIG8
+-	svc	SYS_ify(rt_sigprocmask)
+-
+ 	/* Store fpu context.  */
+ 	stfpc   SC_FPC(%r1)
+ 	std     %f0,SC_FPRS(%r1)
+@@ -65,32 +58,21 @@ ENTRY(__swapcontext)
  	std     %f14,SC_FPRS+112(%r1)
  	std     %f15,SC_FPRS+120(%r1)
  
@@ -5410,8 +7146,9 @@ index 41ede4b..9206aa3 100644
  	stm     %r0,%r15,SC_GPRS(%r1)
  
 -	/* Copy uc_flags into the new ucontext_t.  */
-+	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-+	la      %r2,SIG_BLOCK
++	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
++	   sigsetsize).  */
++	la      %r2,SIG_SETMASK
  	lr	%r5,%r0
 -	l	%r2,SC_FLGS(%r5)
 -	st	%r2,SC_FLGS(%r1)
@@ -5427,10 +7164,12 @@ index 41ede4b..9206aa3 100644
 -	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
 -0:	la      %r2,SIG_BLOCK
 -	la      %r3,SC_MASK(%r5)
+-	slr	%r4,%r4
 +	la	%r3,SC_MASK(%r5)
- 	slr	%r4,%r4
++	la	%r4,SC_MASK(%r1)
  	lhi	%r5,_NSIG8
  	svc	SYS_ify(rt_sigprocmask)
+ 
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym
 deleted file mode 100644
 index 705c7ab..0000000
@@ -5503,6 +7242,25 @@ index bc27b08..a3b1375 100644
 -# endif
 -#endif /* !NOT_IN_libc */
 +#include "__longjmp.c"
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S b/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
+index 71ecbab..a2bf3ca 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
+@@ -17,6 +17,14 @@
+ 
+ #include <sysdep.h>
+ 
++/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
++   if backtrace was called within a context created by makecontext. (There
++   is also no .eh_frame info for _start or thread_start.)  */
++#undef cfi_startproc
++#define cfi_startproc
++#undef cfi_endproc
++#define cfi_endproc
++
+ ENTRY(__makecontext_ret)
+ 	basr	%r14,%r7
+ 	ltgr	%r8,%r8			/* Check whether uc_link is 0.  */
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S b/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S
 deleted file mode 100644
 index 3e61e30..0000000
@@ -5692,11 +7450,47 @@ index 4576fc8..807f702 100644
   __sigsetjmp F
   _longjmp F
   _setjmp F
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S b/sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
+index 83df5ce..1464e6a 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
+@@ -34,7 +34,7 @@ ENTRY(__setcontext)
+ 	lgr	%r1,%r2
+ 
+ 	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
+-	la      %r2,SIG_BLOCK
++	la      %r2,SIG_SETMASK
+ 	la	%r3,SC_MASK(%r1)
+ 	slgr	%r4,%r4
+ 	lghi	%r5,_NSIG8
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
-index ac74b6b..e3e624c 100644
+index ac74b6b..8346fd5 100644
 --- a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
 +++ b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
-@@ -65,25 +65,21 @@ ENTRY(__swapcontext)
+@@ -24,7 +24,7 @@
+ /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
+ 
+   Saves the machine context in oucp such that when it is activated,
+-  it appears as if __swapcontextt() returned again, restores the
++  it appears as if __swapcontext() returned again, restores the
+   machine context in ucp and thereby resumes execution in that
+   context.
+ 
+@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
+ 	lgr	%r1,%r2
+ 	lgr     %r0,%r3
+ 
+-	/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
+-	la      %r2,SIG_BLOCK
+-	slgr	%r3,%r3
+-	la	%r4,SC_MASK(%r1)
+-	lghi	%r5,_NSIG8
+-	svc	SYS_ify(rt_sigprocmask)
+-
+ 	/* Store fpu context.  */
+ 	stfpc   SC_FPC(%r1)
+ 	std     %f0,SC_FPRS(%r1)
+@@ -65,24 +58,21 @@ ENTRY(__swapcontext)
  	std     %f14,SC_FPRS+112(%r1)
  	std     %f15,SC_FPRS+120(%r1)
  
@@ -5713,20 +7507,21 @@ index ac74b6b..e3e624c 100644
  	stmg    %r0,%r15,SC_GPRS(%r1)
  
 -	/* Copy uc_flags into the new ucontext_t.  */
--	lgr	%r5,%r0
++	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
++	   sigsetsize).  */
++	la      %r2,SIG_SETMASK
+ 	lgr	%r5,%r0
 -	lg	%r2,SC_FLGS(%r5)
 -	stg	%r2,SC_FLGS(%r1)
 -
- 	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
- 	la      %r2,SIG_BLOCK
-+	lgr	%r5,%r0
+-	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
+-	la      %r2,SIG_BLOCK
  	la	%r3,SC_MASK(%r5)
 -	slgr	%r4,%r4
++	la	%r4,SC_MASK(%r1)
  	lghi	%r5,_NSIG8
-+	slgr	%r4,%r4
  	svc	SYS_ify(rt_sigprocmask)
  
- 	/* Load fpu context.  */
 diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym
 deleted file mode 100644
 index 6cc9f19..0000000
diff --git a/debian/patches/series b/debian/patches/series
index 7421910..0ab9a1c 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -275,5 +275,4 @@ any/cvs-ldconfig-aux-cache.diff
 any/cvs-ld_pointer_guard.diff
 any/cvs-mangle-tls_dtor_list.diff
 any/cvs-strxfrm-buffer-overflows.diff
-any/local-CVE-2015-7547.diff
 any/cvs-grantpt-pty-owner.diff


-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.6.0-trunk-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

--- End Message ---
--- Begin Message ---
Version: 8.6

The updates referred to in each of these bugs were included in today's
stable point release.

Regards,

Adam

--- End Message ---

Reply to: