guix-patches
[Top][All Lists]
Advanced

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

[bug#60076] [PATCH RFC] Revert "gnu: glibc: Remove old versions."


From: Maxim Cournoyer
Subject: [bug#60076] [PATCH RFC] Revert "gnu: glibc: Remove old versions."
Date: Wed, 14 Dec 2022 15:39:12 -0500

This reinstates glibc 2.22 through 2.28, by reverting commit
ebd1ba713cbefc9ad5dac609255e1344a328e360 ("gnu: glibc: Remove old versions."),
adding two patches removed in d2bb4847b96e51b71126778bb16daa7674a6690c ("gnu:
Remove leftover patch files."), and partially reverting
1feca4be5296d7f0c0e2269ccb612cadded6573b ("gnu: glibc: Remove versions 2.27
and 2.28.").

Rationale: Keeping older glibc versions around is useful when experimenting
with 'package-with-c-toolchain'.

* gnu/local.mk (dist_patch_DATA): Register any missing patches now re-instated
and sort.
---
 gnu/local.mk                                  |  32 +-
 gnu/packages/base.scm                         |  87 ++-
 .../patches/glibc-2.27-git-fixes.patch        | 702 ++++++++++++++++++
 .../glibc-2.27-supported-locales.patch        |  33 +
 .../patches/glibc-2.28-git-fixes.patch        | 248 +++++++
 .../glibc-2.28-supported-locales.patch        |  33 +
 .../patches/glibc-CVE-2015-5180.patch         | 311 ++++++++
 .../patches/glibc-CVE-2015-7547.patch         | 590 +++++++++++++++
 .../patches/glibc-CVE-2016-3075.patch         |  43 ++
 .../patches/glibc-CVE-2016-3706.patch         | 188 +++++
 .../patches/glibc-CVE-2016-4429.patch         |  58 ++
 .../patches/glibc-CVE-2017-1000366-pt1.patch  |  36 +
 .../patches/glibc-CVE-2017-1000366-pt2.patch  | 124 ++++
 .../patches/glibc-CVE-2017-1000366-pt3.patch  | 206 +++++
 .../patches/glibc-CVE-2018-11236.patch        | 149 ++++
 .../patches/glibc-CVE-2018-11237.patch        |  55 ++
 .../patches/glibc-cvs-common-symbols.patch    |  58 ++
 .../patches/glibc-hurd-magic-pid.patch        | 190 +++++
 gnu/packages/patches/glibc-o-largefile.patch  |  25 +
 .../glibc-vectorized-strcspn-guards.patch     |  23 +
 20 files changed, 3183 insertions(+), 8 deletions(-)
 create mode 100644 gnu/packages/patches/glibc-2.27-git-fixes.patch
 create mode 100644 gnu/packages/patches/glibc-2.27-supported-locales.patch
 create mode 100644 gnu/packages/patches/glibc-2.28-git-fixes.patch
 create mode 100644 gnu/packages/patches/glibc-2.28-supported-locales.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2015-5180.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2015-7547.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2016-3075.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2016-3706.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2016-4429.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2018-11236.patch
 create mode 100644 gnu/packages/patches/glibc-CVE-2018-11237.patch
 create mode 100644 gnu/packages/patches/glibc-cvs-common-symbols.patch
 create mode 100644 gnu/packages/patches/glibc-hurd-magic-pid.patch
 create mode 100644 gnu/packages/patches/glibc-o-largefile.patch
 create mode 100644 gnu/packages/patches/glibc-vectorized-strcspn-guards.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index aae6e23e12..51415eddf0 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1201,36 +1201,54 @@ dist_patch_DATA =                                       
        \
   %D%/packages/patches/glib-networking-gnutls-binding.patch    \
   %D%/packages/patches/glib-networking-32-bit-time.patch       \
   %D%/packages/patches/glib-skip-failing-test.patch            \
+  %D%/packages/patches/glibc-2.27-git-fixes.patch              \
+  %D%/packages/patches/glibc-2.27-supported-locales.patch      \
+  %D%/packages/patches/glibc-2.28-git-fixes.patch              \
+  %D%/packages/patches/glibc-2.28-supported-locales.patch      \
+  %D%/packages/patches/glibc-2.29-git-updates.patch            \
+  %D%/packages/patches/glibc-2.29-supported-locales.patch      \
+  %D%/packages/patches/glibc-2.31-hurd-clock_gettime_monotonic.patch   \
+  %D%/packages/patches/glibc-CVE-2015-5180.patch               \
+  %D%/packages/patches/glibc-CVE-2015-7547.patch               \
+  %D%/packages/patches/glibc-CVE-2016-3075.patch               \
+  %D%/packages/patches/glibc-CVE-2016-3706.patch               \
+  %D%/packages/patches/glibc-CVE-2016-4429.patch               \
+  %D%/packages/patches/glibc-CVE-2017-1000366-pt1.patch                \
+  %D%/packages/patches/glibc-CVE-2017-1000366-pt2.patch                \
+  %D%/packages/patches/glibc-CVE-2017-1000366-pt3.patch                \
+  %D%/packages/patches/glibc-CVE-2018-11236.patch              \
+  %D%/packages/patches/glibc-CVE-2018-11237.patch              \
+  %D%/packages/patches/glibc-CVE-2019-19126.patch              \
   %D%/packages/patches/glibc-CVE-2019-7309.patch               \
   %D%/packages/patches/glibc-CVE-2019-9169.patch               \
-  %D%/packages/patches/glibc-CVE-2019-19126.patch              \
   %D%/packages/patches/glibc-allow-kernel-2.6.32.patch         \
   %D%/packages/patches/glibc-boot-2.16.0.patch                 \
   %D%/packages/patches/glibc-boot-2.2.5.patch                  \
-  %D%/packages/patches/glibc-bootstrap-system-2.2.5.patch      \
   %D%/packages/patches/glibc-bootstrap-system-2.16.0.patch     \
+  %D%/packages/patches/glibc-bootstrap-system-2.2.5.patch      \
   %D%/packages/patches/glibc-bootstrap-system.patch            \
   %D%/packages/patches/glibc-cross-objcopy.patch               \
   %D%/packages/patches/glibc-cross-objdump.patch               \
+  %D%/packages/patches/glibc-cvs-common-symbols.patch          \
   %D%/packages/patches/glibc-dl-cache.patch                    \
   %D%/packages/patches/glibc-hidden-visibility-ldconfig.patch  \
   %D%/packages/patches/glibc-hurd-clock_gettime_monotonic.patch        \
-  %D%/packages/patches/glibc-2.31-hurd-clock_gettime_monotonic.patch   \
   %D%/packages/patches/glibc-hurd-clock_t_centiseconds.patch   \
   %D%/packages/patches/glibc-hurd-gettyent.patch               \
   %D%/packages/patches/glibc-hurd-mach-print.patch             \
+  %D%/packages/patches/glibc-hurd-magic-pid.patch              \
   %D%/packages/patches/glibc-hurd-signal-sa-siginfo.patch      \
   %D%/packages/patches/glibc-ldd-powerpc.patch                 \
   %D%/packages/patches/glibc-ldd-x86_64.patch                  \
-  %D%/packages/patches/glibc-locales.patch                     \
   %D%/packages/patches/glibc-locales-2.28.patch                        \
+  %D%/packages/patches/glibc-locales.patch                     \
+  %D%/packages/patches/glibc-o-largefile.patch                 \
   %D%/packages/patches/glibc-reinstate-prlimit64-fallback.patch        \
   %D%/packages/patches/glibc-skip-c++.patch                    \
-  %D%/packages/patches/glibc-versioned-locpath.patch           \
-  %D%/packages/patches/glibc-2.29-git-updates.patch            \
-  %D%/packages/patches/glibc-2.29-supported-locales.patch      \
   %D%/packages/patches/glibc-static-nss.patch                  \
   %D%/packages/patches/glibc-supported-locales.patch           \
+  %D%/packages/patches/glibc-vectorized-strcspn-guards.patch   \
+  %D%/packages/patches/glibc-versioned-locpath.patch           \
   %D%/packages/patches/gmp-arm-asm-nothumb.patch               \
   %D%/packages/patches/gmp-faulty-test.patch                   \
   %D%/packages/patches/gnash-fix-giflib-version.patch          \
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index b8b0ea241f..ef1b4f135c 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -985,7 +985,8 @@ (define-public glibc-for-fhs
                               (origin-patches (package-source glibc)))))))))
 
 ;; Below are old libc versions, which we use mostly to build locale data in
-;; the old format (which the new libc cannot cope with.)
+;; the old format (which the new libc cannot cope with.).  Older versions are
+;; kept around for the convenience of users of '--with-c-toolchain'.
 (define-public glibc-2.32
   (package
     (inherit glibc)
@@ -1126,6 +1127,90 @@ (define-public glibc-2.29
                                        
"glibc-reinstate-prlimit64-fallback.patch"
                                        
"glibc-2.29-supported-locales.patch"))))))
 
+(define-public glibc-2.28
+  (package
+    (inherit glibc-2.29)
+    (version "2.28")
+    (source (origin
+              (inherit (package-source glibc))
+              (uri (string-append "mirror://gnu/glibc/glibc-" version 
".tar.xz"))
+              (sha256
+               (base32
+                "10iha5ynvdj5m62vgpgqbq4cwvc2yhyl2w9yyyjgfxmdmx8h145i"))
+              (patches (search-patches "glibc-ldd-x86_64.patch"
+                                       "glibc-2.28-git-fixes.patch"
+                                       "glibc-hidden-visibility-ldconfig.patch"
+                                       "glibc-versioned-locpath.patch"
+                                       "glibc-allow-kernel-2.6.32.patch"
+                                       
"glibc-reinstate-prlimit64-fallback.patch"
+                                       "glibc-hurd-magic-pid.patch"
+                                       
"glibc-2.28-supported-locales.patch"))))))
+
+(define-public glibc-2.27
+  (package
+    (inherit glibc-2.28)
+    (version "2.27")
+    (source (origin
+              (inherit (package-source glibc))
+              (uri (string-append "mirror://gnu/glibc/glibc-" version 
".tar.xz"))
+              (sha256
+               (base32
+                "0wpwq7gsm7sd6ysidv0z575ckqdg13cr2njyfgrbgh4f65adwwji"))
+              (patches (search-patches "glibc-ldd-x86_64.patch"
+                                       "glibc-2.27-git-fixes.patch"
+                                       "glibc-hidden-visibility-ldconfig.patch"
+                                       "glibc-versioned-locpath.patch"
+                                       "glibc-allow-kernel-2.6.32.patch"
+                                       
"glibc-reinstate-prlimit64-fallback.patch"
+                                       "glibc-2.27-supported-locales.patch"
+                                       "glibc-CVE-2018-11236.patch"
+                                       "glibc-CVE-2018-11237.patch"))))
+    (properties `((lint-hidden-cve . ("CVE-2017-18269")))))) ; 
glibc-2.27-git-fixes
+
+(define-public glibc-2.26
+  (package
+    (inherit glibc-2.27)
+    ;; This version number corresponds to the output of `git describe` and the
+    ;; archive can be generated by checking out the commit ID and running:
+    ;;  git archive --prefix=$(git describe)/ HEAD | xz > $(git 
describe).tar.xz
+    ;; See <https://bugs.gnu.org/29406> for why this was necessary.
+    (version "2.26.105-g0890d5379c")
+    (source (origin
+              (inherit (package-source glibc))
+              (uri (string-append "https://alpha.gnu.org/gnu/guix/mirror/";
+                                  "glibc-" (version-major+minor version) "-"
+                                  (caddr (string-split version #\.)) 
".tar.xz"))
+              (sha256
+               (base32
+                "1jck0c1i248sn02rvsfjykk77qncma34bjq89dyy2irwm50d7s3g"))
+              (patches (search-patches "glibc-ldd-x86_64.patch"
+                                       "glibc-versioned-locpath.patch"
+                                       "glibc-allow-kernel-2.6.32.patch"))))
+    (native-inputs
+     ;; This fails with a build error in if_index.c when using GCC 8.  Use an
+     ;; older compiler.
+     (modify-inputs (package-native-inputs glibc-2.27)
+       (replace "gcc" gcc-7)))))
+
+(define-public glibc-2.25
+  (package
+    (inherit glibc-2.26)
+    (version "2.25")
+    (source (origin
+              (inherit (package-source glibc))
+              (uri (string-append "mirror://gnu/glibc/glibc-"
+                                  version ".tar.xz"))
+              (sha256
+               (base32
+                "1813dzkgw6v8q8q1m4v96yfis7vjqc9pslqib6j9mrwh6fxxjyq6"))
+              (patches (search-patches "glibc-ldd-x86_64.patch"
+                                       "glibc-versioned-locpath.patch"
+                                       "glibc-vectorized-strcspn-guards.patch"
+                                       "glibc-CVE-2017-1000366-pt1.patch"
+                                       "glibc-CVE-2017-1000366-pt2.patch"
+                                       "glibc-CVE-2017-1000366-pt3.patch"
+                                       "glibc-cvs-common-symbols.patch"))))))
+
 (define-public (make-gcc-libc base-gcc libc)
   "Return a GCC that targets LIBC."
   (package (inherit base-gcc)
diff --git a/gnu/packages/patches/glibc-2.27-git-fixes.patch 
b/gnu/packages/patches/glibc-2.27-git-fixes.patch
new file mode 100644
index 0000000000..4ed67c7c25
--- /dev/null
+++ b/gnu/packages/patches/glibc-2.27-git-fixes.patch
@@ -0,0 +1,702 @@
+These commits are cherry-picked from the "release/2.27/master" branch.
+
+https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.27/master
+
+Currently, we have the following (with NEWS and ChangeLog entries omitted).
+
+56170e064e2b21ce204f0817733e92f1730541ea
+516fa6080481a1433c173320b1c1432868e1e38a
+f36553bf6a4f69070f99badbdab5802b43e6e211
+7c6304182b9f422b782ace1cdd3efbde056aec36
+78a90c2f74a2012dd3eff302189e47ff6779a757
+1e52d8e65a58c49a48549053a1b89c06240e0c6c
+55ad82e45c313454de657931898e974a7a036cad
+
+From 56170e064e2b21ce204f0817733e92f1730541ea Mon Sep 17 00:00:00 2001
+From: Igor Gnatenko <ignatenko@redhat.com>
+Date: Wed, 7 Feb 2018 13:53:10 +0100
+Subject: [PATCH] Linux: use reserved name __key in pkey_get [BZ #22797]
+
+_key is not reserved name and we should avoid using that. It seems that
+it was simple typo when pkey_* was implemented.
+
+(cherry picked from commit 388ff7bd0d57d7061fdd39a2f26f65687e8058da)
+
+diff --git a/sysdeps/unix/sysv/linux/bits/mman-shared.h 
b/sysdeps/unix/sysv/linux/bits/mman-shared.h
+index 7715e680ca..d15ba95c9d 100644
+--- a/sysdeps/unix/sysv/linux/bits/mman-shared.h
++++ b/sysdeps/unix/sysv/linux/bits/mman-shared.h
+@@ -61,7 +61,7 @@ int pkey_set (int __key, unsigned int __access_rights) 
__THROW;
+ 
+ /* Return the access rights for the current thread for KEY, which must
+    have been allocated using pkey_alloc.  */
+-int pkey_get (int _key) __THROW;
++int pkey_get (int __key) __THROW;
+ 
+ /* Free an allocated protection key, which must have been allocated
+    using pkey_alloc.  */
+
+From 516fa6080481a1433c173320b1c1432868e1e38a Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Fri, 29 Dec 2017 23:19:32 +0000
+Subject: [PATCH] linux/aarch64: sync sys/ptrace.h with Linux 4.15 [BZ #22433]
+
+Remove compat-specific constants that were never exported by kernel
+headers under these names.  Before linux commit v3.7-rc1~16^2~1 they
+were exported with COMPAT_ prefix, and since that commit they are not
+exported at all.
+
+* sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h (__ptrace_request):
+Remove arm-specific PTRACE_GET_THREAD_AREA, PTRACE_GETHBPREGS,
+and PTRACE_SETHBPREGS.
+
+(cherry picked from commit 2fd4bbaa1446f1be700e10c526cf585a796c4991)
+
+diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h 
b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
+index 4be45b95ff..444edbb702 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
+@@ -78,18 +78,10 @@ enum __ptrace_request
+   PTRACE_DETACH = 17,
+ #define PT_DETACH PTRACE_DETACH
+ 
+-  PTRACE_GET_THREAD_AREA = 22,
+-
+   /* Continue and stop at the next entry to or return from syscall.  */
+   PTRACE_SYSCALL = 24,
+ #define PT_SYSCALL PTRACE_SYSCALL
+ 
+-  /* Get all hardware breakpoint registers.  */
+-  PTRACE_GETHBPREGS = 29,
+-
+-  /* Set all hardware breakpoint registers.  */
+-  PTRACE_SETHBPREGS = 30,
+-
+   /* Set ptrace filter options.  */
+   PTRACE_SETOPTIONS = 0x4200,
+ #define PT_SETOPTIONS PTRACE_SETOPTIONS
+
+From f36553bf6a4f69070f99badbdab5802b43e6e211 Mon Sep 17 00:00:00 2001
+From: Mike FABIAN <mfabian@redhat.com>
+Date: Mon, 19 Feb 2018 21:59:30 +0100
+Subject: [PATCH] =?UTF-8?q?Add=20missing=20=E2=80=9Creorder-end=E2=80=9D?=
+ =?UTF-8?q?=20in=20LC=5FCOLLATE=20of=20et=5FEE=20[BZ=20#22517]?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+       [BZ #22517]
+       * localedata/locales/et_EE (LC_COLLATE): add missing “reorder-end”
+
+(cherry picked from commit 7ec5f9465e732e668d0dc94ac078ba68056d6d0a)
+
+diff --git a/localedata/locales/et_EE b/localedata/locales/et_EE
+index 9cb55b568f..bab7493c98 100644
+--- a/localedata/locales/et_EE
++++ b/localedata/locales/et_EE
+@@ -103,6 +103,8 @@ reorder-after <w>
+ <U00FC> <u-diaresis>;<BAS>;<MIN>;IGNORE % ü
+ <U00DC> <u-diaresis>;<BAS>;<CAP>;IGNORE % Ü
+ 
++reorder-end
++
+ END LC_COLLATE
+ 
+ LC_CTYPE
+
+From 7c6304182b9f422b782ace1cdd3efbde056aec36 Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Thu, 1 Mar 2018 23:20:45 -0500
+Subject: [PATCH] [BZ #22342] Fix netgroup cache keys.
+
+Unlike other nscd caches, the netgroup cache contains two types of
+records - those for "iterate through a netgroup" (i.e. setnetgrent())
+and those for "is this user in this netgroup" (i.e. innetgr()),
+i.e. full and partial records.  The timeout code assumes these records
+have the same key for the group name, so that the collection of records
+that is "this netgroup" can be expired as a unit.
+
+However, the keys are not the same, as the in-netgroup key is generated
+by nscd rather than being passed to it from elsewhere, and is generated
+without the trailing NUL.  All other keys have the trailing NUL, and as
+noted in the linked BZ, debug statements confirm that two keys for the
+same netgroup are added to the cache with two different lengths.
+
+The result of this is that as records in the cache expire, the purge
+code only cleans out one of the two types of entries, resulting in
+stale, possibly incorrect, and possibly inconsistent cache data.
+
+The patch simply includes the existing NUL in the computation for the
+key length ('key' points to the char after the NUL, and 'group' to the
+first char of the group, so 'key-group' includes the first char to the
+NUL, inclusive).
+
+       [BZ #22342]
+       * nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in
+       key value.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+(cherry picked from commit 1c81d55fc4b07b51adf68558ba74ce975153e580)
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index b832c9315f..2f187b208c 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -480,7 +480,7 @@ addinnetgrX (struct database_dyn *db, int fd, 
request_header *req,
+ {
+   const char *group = key;
+   key = (char *) rawmemchr (key, '\0') + 1;
+-  size_t group_len = key - group - 1;
++  size_t group_len = key - group;
+   const char *host = *key++ ? key : NULL;
+   if (host != NULL)
+     key = (char *) rawmemchr (key, '\0') + 1;
+
+From 78a90c2f74a2012dd3eff302189e47ff6779a757 Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@linux-m68k.org>
+Date: Fri, 2 Mar 2018 23:07:14 +0100
+Subject: [PATCH] Fix multiple definitions of __nss_*_database (bug 22918)
+
+(cherry picked from commit eaf6753f8aac33a36deb98c1031d1bad7b593d2d)
+
+diff --git a/nscd/gai.c b/nscd/gai.c
+index d081747797..576fd0045b 100644
+--- a/nscd/gai.c
++++ b/nscd/gai.c
+@@ -45,3 +45,6 @@
+ #ifdef HAVE_LIBIDN
+ # include <libidn/idn-stub.c>
+ #endif
++
++/* Some variables normally defined in libc.  */
++service_user *__nss_hosts_database attribute_hidden;
+diff --git a/nss/nsswitch.c b/nss/nsswitch.c
+index d5e655974f..b0f0c11a3e 100644
+--- a/nss/nsswitch.c
++++ b/nss/nsswitch.c
+@@ -62,7 +62,7 @@ static service_library *nss_new_service (name_database 
*database,
+ 
+ /* Declare external database variables.  */
+ #define DEFINE_DATABASE(name)                                               \
+-  extern service_user *__nss_##name##_database attribute_hidden;            \
++  service_user *__nss_##name##_database attribute_hidden;                   \
+   weak_extern (__nss_##name##_database)
+ #include "databases.def"
+ #undef DEFINE_DATABASE
+diff --git a/nss/nsswitch.h b/nss/nsswitch.h
+index eccb535ef5..63573b9ebc 100644
+--- a/nss/nsswitch.h
++++ b/nss/nsswitch.h
+@@ -226,10 +226,10 @@ libc_hidden_proto (__nss_hostname_digits_dots)
+ #define MAX_NR_ADDRS    48
+ 
+ /* Prototypes for __nss_*_lookup2 functions.  */
+-#define DEFINE_DATABASE(arg)                              \
+-  service_user *__nss_##arg##_database attribute_hidden;    \
+-  int __nss_##arg##_lookup2 (service_user **, const char *, \
+-                           const char *, void **);        \
++#define DEFINE_DATABASE(arg)                                                \
++  extern service_user *__nss_##arg##_database attribute_hidden;               
      \
++  int __nss_##arg##_lookup2 (service_user **, const char *,                 \
++                           const char *, void **);                          \
+   libc_hidden_proto (__nss_##arg##_lookup2)
+ #include "databases.def"
+ #undef DEFINE_DATABASE
+diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c
+index f509534ca9..8c64ac59ff 100644
+--- a/posix/tst-rfc3484-2.c
++++ b/posix/tst-rfc3484-2.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef        USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
+diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c
+index ae44087a10..1c61aaf844 100644
+--- a/posix/tst-rfc3484-3.c
++++ b/posix/tst-rfc3484-3.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef        USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
+diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c
+index 7f191abbbc..8f45848e44 100644
+--- a/posix/tst-rfc3484.c
++++ b/posix/tst-rfc3484.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef        USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
+
+From 1e52d8e65a58c49a48549053a1b89c06240e0c6c Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Fri, 17 Nov 2017 16:04:29 -0200
+Subject: [PATCH] i386: Fix i386 sigaction sa_restorer initialization
+ (BZ#21269)
+
+This patch fixes the i386 sa_restorer field initialization for sigaction
+syscall for kernel with vDSO.  As described in bug report, i386 Linux
+(and compat on x86_64) interprets SA_RESTORER clear with nonzero
+sa_restorer as a request for stack switching if the SS segment is 'funny'.
+This means that anything that tries to mix glibc's signal handling with
+segmentation (for instance through modify_ldt syscall) is randomly broken
+depending on what values lands in sa_restorer.
+
+The testcase added  is based on Linux test 
tools/testing/selftests/x86/ldt_gdt.c,
+more specifically in do_multicpu_tests function.  The main changes are:
+
+  - C11 atomics instead of plain access.
+
+  - Remove x86_64 support which simplifies the syscall handling and fallbacks.
+
+  - Replicate only the test required to trigger the issue.
+
+Checked on i686-linux-gnu.
+
+       [BZ #21269]
+       * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269.
+       * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear
+       sa_restorer for vDSO case.
+       * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file.
+
+(cherry picked from commit 68448be208ee06e76665918b37b0a57e3e00c8b4)
+
+diff --git a/sysdeps/unix/sysv/linux/i386/Makefile 
b/sysdeps/unix/sysv/linux/i386/Makefile
+index 4080b8c966..da716e2c1b 100644
+--- a/sysdeps/unix/sysv/linux/i386/Makefile
++++ b/sysdeps/unix/sysv/linux/i386/Makefile
+@@ -3,6 +3,9 @@ default-abi := 32
+ 
+ ifeq ($(subdir),misc)
+ sysdep_routines += ioperm iopl vm86
++
++tests += tst-bz21269
++$(objpfx)tst-bz21269: $(shared-thread-library)
+ endif
+ 
+ ifeq ($(subdir),elf)
+diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c 
b/sysdeps/unix/sysv/linux/i386/sigaction.c
+index a5eb9e0d3e..177ff60ee6 100644
+--- a/sysdeps/unix/sysv/linux/i386/sigaction.c
++++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
+@@ -42,7 +42,6 @@ extern void restore_rt (void) asm ("__restore_rt") 
attribute_hidden;
+ #endif
+ extern void restore (void) asm ("__restore") attribute_hidden;
+ 
+-
+ /* If ACT is not NULL, change the action for SIG to *ACT.
+    If OACT is not NULL, put the old action for SIG in *OACT.  */
+ int
+@@ -65,6 +64,8 @@ __libc_sigaction (int sig, const struct sigaction *act, 
struct sigaction *oact)
+         kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
+                             ? &restore_rt : &restore);
+       }
++      else
++      kact.sa_restorer = NULL;
+     }
+ 
+   /* XXX The size argument hopefully will have to be changed to the
+diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c 
b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
+new file mode 100644
+index 0000000000..353e36507d
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c
+@@ -0,0 +1,233 @@
++/* Test for i386 sigaction sa_restorer handling (BZ#21269)
++   Copyright (C) 2017 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/>.  */
++
++/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
++   more specifically in do_multicpu_tests function.  The main changes
++   are:
++
++   - C11 atomics instead of plain access.
++   - Remove x86_64 support which simplifies the syscall handling
++     and fallbacks.
++   - Replicate only the test required to trigger the issue for the
++     BZ#21269.  */
++
++#include <stdatomic.h>
++
++#include <asm/ldt.h>
++#include <linux/futex.h>
++
++#include <setjmp.h>
++#include <signal.h>
++#include <errno.h>
++#include <sys/syscall.h>
++#include <sys/mman.h>
++
++#include <support/xunistd.h>
++#include <support/check.h>
++#include <support/xthread.h>
++
++static int
++xset_thread_area (struct user_desc *u_info)
++{
++  long ret = syscall (SYS_set_thread_area, u_info);
++  TEST_VERIFY_EXIT (ret == 0);
++  return ret;
++}
++
++static void
++xmodify_ldt (int func, const void *ptr, unsigned long bytecount)
++{
++  TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0);
++}
++
++static int
++futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2,
++      int val3)
++{
++  return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
++}
++
++static void
++xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags)
++{
++  struct sigaction sa = { 0 };
++  sa.sa_sigaction = handler;
++  sa.sa_flags = SA_SIGINFO | flags;
++  TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0);
++  TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0);
++}
++
++static jmp_buf jmpbuf;
++
++static void
++sigsegv_handler (int sig, siginfo_t *info, void *ctx_void)
++{
++  siglongjmp (jmpbuf, 1);
++}
++
++/* Points to an array of 1024 ints, each holding its own index.  */
++static const unsigned int *counter_page;
++static struct user_desc *low_user_desc;
++static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry.  */
++static int gdt_entry_num;
++
++static void
++setup_counter_page (void)
++{
++  long page_size = sysconf (_SC_PAGE_SIZE);
++  TEST_VERIFY_EXIT (page_size > 0);
++  unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE,
++                            MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
++  for (int i = 0; i < (page_size / sizeof (unsigned int)); i++)
++    page[i] = i;
++  counter_page = page;
++}
++
++static void
++setup_low_user_desc (void)
++{
++  low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc),
++                       PROT_READ | PROT_WRITE,
++                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1);
++
++  low_user_desc->entry_number    = -1;
++  low_user_desc->base_addr       = (unsigned long) &counter_page[1];
++  low_user_desc->limit           = 0xffff;
++  low_user_desc->seg_32bit       = 1;
++  low_user_desc->contents        = 0;
++  low_user_desc->read_exec_only  = 0;
++  low_user_desc->limit_in_pages  = 1;
++  low_user_desc->seg_not_present = 0;
++  low_user_desc->useable         = 0;
++
++  xset_thread_area (low_user_desc);
++
++  low_user_desc_clear = low_user_desc + 1;
++  low_user_desc_clear->entry_number = gdt_entry_num;
++  low_user_desc_clear->read_exec_only = 1;
++  low_user_desc_clear->seg_not_present = 1;
++}
++
++/* Possible values of futex:
++   0: thread is idle.
++   1: thread armed.
++   2: thread should clear LDT entry 0.
++   3: thread should exit.  */
++static atomic_uint ftx;
++
++static void *
++threadproc (void *ctx)
++{
++  while (1)
++    {
++      futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
++      while (atomic_load (&ftx) != 2)
++      {
++        if (atomic_load (&ftx) >= 3)
++          return NULL;
++      }
++
++      /* clear LDT entry 0.  */
++      const struct user_desc desc = { 0 };
++      xmodify_ldt (1, &desc, sizeof (desc));
++
++      /* If ftx == 2, set it to zero,  If ftx == 100, quit.  */
++      if (atomic_fetch_add (&ftx, -2) != 2)
++      return NULL;
++    }
++}
++
++
++/* As described in testcase, for historical reasons x86_32 Linux (and compat
++   on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a
++   request for stack switching if the SS segment is 'funny' (this is default
++   scenario for vDSO system).  This means that anything that tries to mix
++   signal handling with segmentation should explicit clear the sa_restorer.
++
++   This testcase check if sigaction in fact does it by changing the local
++   descriptor table (LDT) through the modify_ldt syscall and triggering
++   a synchronous segfault on iret fault by trying to install an invalid
++   segment.  With a correct zeroed sa_restorer it should not trigger an
++   'real' SEGSEGV and allows the siglongjmp in signal handler.  */
++
++static int
++do_test (void)
++{
++  setup_counter_page ();
++  setup_low_user_desc ();
++
++  pthread_t thread;
++  unsigned short orig_ss;
++
++  xsethandler (SIGSEGV, sigsegv_handler, 0);
++  /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults.  */
++  xsethandler (SIGILL, sigsegv_handler, 0);
++
++  thread = xpthread_create (0, threadproc, 0);
++
++  asm volatile ("mov %%ss, %0" : "=rm" (orig_ss));
++
++  for (int i = 0; i < 5; i++)
++    {
++      if (sigsetjmp (jmpbuf, 1) != 0)
++      continue;
++
++      /* Make sure the thread is ready after the last test. */
++      while (atomic_load (&ftx) != 0)
++      ;
++
++      struct user_desc desc = {
++      .entry_number       = 0,
++      .base_addr          = 0,
++      .limit              = 0xffff,
++      .seg_32bit          = 1,
++      .contents           = 0,
++      .read_exec_only     = 0,
++      .limit_in_pages     = 1,
++      .seg_not_present    = 0,
++      .useable            = 0
++      };
++
++      xmodify_ldt (0x11, &desc, sizeof (desc));
++
++      /* Arm the thread.  */
++      ftx = 1;
++      futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
++
++      asm volatile ("mov %0, %%ss" : : "r" (0x7));
++
++      /* Fire up thread modify_ldt call.  */
++      atomic_store (&ftx, 2);
++
++      while (atomic_load (&ftx) != 0)
++      ;
++
++      /* On success, modify_ldt will segfault us synchronously and we will
++       escape via siglongjmp.  */
++      support_record_failure ();
++    }
++
++  atomic_store (&ftx, 100);
++  futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
++
++  xpthread_join (thread);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+
+From 55ad82e45c313454de657931898e974a7a036cad Mon Sep 17 00:00:00 2001
+From: Andrew Senkevich <andrew.n.senkevich@gmail.com>
+Date: Fri, 23 Mar 2018 16:19:45 +0100
+Subject: [PATCH] Fix i386 memmove issue (bug 22644).
+
+       [BZ #22644]
+       * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed
+       branch conditions.
+       * string/test-memmove.c (do_test2): New testcase.
+
+(cherry picked from commit cd66c0e584c6d692bc8347b5e72723d02b8a8ada)
+
+diff --git a/string/test-memmove.c b/string/test-memmove.c
+index edc7a4c3bf..64e3651ba4 100644
+--- a/string/test-memmove.c
++++ b/string/test-memmove.c
+@@ -24,6 +24,7 @@
+ # define TEST_NAME "memmove"
+ #endif
+ #include "test-string.h"
++#include <support/test-driver.h>
+ 
+ char *simple_memmove (char *, const char *, size_t);
+ 
+@@ -245,6 +246,60 @@ do_random_tests (void)
+     }
+ }
+ 
++static void
++do_test2 (void)
++{
++  size_t size = 0x20000000;
++  uint32_t * large_buf;
++
++  large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE,
++                  MAP_PRIVATE | MAP_ANON, -1, 0);
++
++  if (large_buf == MAP_FAILED)
++    error (EXIT_UNSUPPORTED, errno, "Large mmap failed");
++
++  if ((uintptr_t) large_buf > 0x80000000 - 128
++      || 0x80000000 - (uintptr_t) large_buf > 0x20000000)
++    {
++      error (0, 0, "Large mmap allocated improperly");
++      ret = EXIT_UNSUPPORTED;
++      munmap ((void *) large_buf, size);
++      return;
++    }
++
++  size_t bytes_move = 0x80000000 - (uintptr_t) large_buf;
++  size_t arr_size = bytes_move / sizeof (uint32_t);
++  size_t i;
++
++  FOR_EACH_IMPL (impl, 0)
++    {
++      for (i = 0; i < arr_size; i++)
++        large_buf[i] = (uint32_t) i;
++
++      uint32_t * dst = &large_buf[33];
++
++#ifdef TEST_BCOPY
++      CALL (impl, (char *) large_buf, (char *) dst, bytes_move);
++#else
++      CALL (impl, (char *) dst, (char *) large_buf, bytes_move);
++#endif
++
++      for (i = 0; i < arr_size; i++)
++      {
++        if (dst[i] != (uint32_t) i)
++          {
++            error (0, 0,
++                   "Wrong result in function %s dst \"%p\" src \"%p\" offset 
\"%zd\"",
++                   impl->name, dst, large_buf, i);
++            ret = 1;
++            break;
++          }
++      }
++    }
++
++  munmap ((void *) large_buf, size);
++}
++
+ int
+ test_main (void)
+ {
+@@ -284,6 +339,9 @@ test_main (void)
+     }
+ 
+   do_random_tests ();
++
++  do_test2 ();
++
+   return ret;
+ }
+ 
+diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S 
b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
+index 9c3bbe7e17..9aa17de99c 100644
+--- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
++++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
+@@ -72,7 +72,7 @@ ENTRY (MEMCPY)
+       cmp     %edx, %eax
+ 
+ # ifdef USE_AS_MEMMOVE
+-      jg      L(check_forward)
++      ja      L(check_forward)
+ 
+ L(mm_len_0_or_more_backward):
+ /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128]
+@@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward):
+       jbe     L(mm_len_0_16_bytes_backward)
+ 
+       cmpl    $32, %ecx
+-      jg      L(mm_len_32_or_more_backward)
++      ja      L(mm_len_32_or_more_backward)
+ 
+ /* Copy [0..32] and return.  */
+       movdqu  (%eax), %xmm0
+@@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward):
+ 
+ L(mm_len_32_or_more_backward):
+       cmpl    $64, %ecx
+-      jg      L(mm_len_64_or_more_backward)
++      ja      L(mm_len_64_or_more_backward)
+ 
+ /* Copy [0..64] and return.  */
+       movdqu  (%eax), %xmm0
+@@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward):
+ 
+ L(mm_len_64_or_more_backward):
+       cmpl    $128, %ecx
+-      jg      L(mm_len_128_or_more_backward)
++      ja      L(mm_len_128_or_more_backward)
+ 
+ /* Copy [0..128] and return.  */
+       movdqu  (%eax), %xmm0
+@@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward):
+       add     %ecx, %eax
+       cmp     %edx, %eax
+       movl    SRC(%esp), %eax
+-      jle     L(forward)
++      jbe     L(forward)
+       PUSH (%esi)
+       PUSH (%edi)
+       PUSH (%ebx)
+@@ -269,7 +269,7 @@ L(check_forward):
+       add     %edx, %ecx
+       cmp     %eax, %ecx
+       movl    LEN(%esp), %ecx
+-      jle     L(forward)
++      jbe     L(forward)
+ 
+ /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128]
+       separately.  */
diff --git a/gnu/packages/patches/glibc-2.27-supported-locales.patch 
b/gnu/packages/patches/glibc-2.27-supported-locales.patch
new file mode 100644
index 0000000000..2888052bb8
--- /dev/null
+++ b/gnu/packages/patches/glibc-2.27-supported-locales.patch
@@ -0,0 +1,33 @@
+This patch is taken from debian's glibc package (generate-supported.mk).
+It install the localedata/SUPPORTED file of the glibc. This file lists
+all the supported locales of the glibc.
+
+diff --git a/localedata/Makefile.old b/localedata/Makefile
+index 34877c0..a61d9b9 100644
+--- a/localedata/Makefile.old
++++ b/localedata/Makefile
+@@ -91,7 +91,8 @@ endif
+ # Files to install.
+ install-others := $(addprefix $(inst_i18ndir)/, \
+                             $(addsuffix .gz, $(charmaps)) \
+-                            $(locales))
++                            $(locales)) \
++                   $(inst_i18ndir)/SUPPORTED
+ 
+ tests: $(objdir)/iconvdata/gconv-modules
+ 
+@@ -195,6 +196,14 @@ endif
+ 
+ include SUPPORTED
+ 
++$(inst_i18ndir)/SUPPORTED: SUPPORTED $(+force)
++      for locale in $(SUPPORTED-LOCALES); do \
++              [ $$locale = true ] && continue; \
++              echo $$locale | sed 's,/, ,' >> LOCALES; \
++      done
++      $(make-target-directory)
++      $(INSTALL_DATA) LOCALES $@
++
+ INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES))
+ 
+ # Sometimes the whole collection of locale files should be installed.
diff --git a/gnu/packages/patches/glibc-2.28-git-fixes.patch 
b/gnu/packages/patches/glibc-2.28-git-fixes.patch
new file mode 100644
index 0000000000..7e370ef0b1
--- /dev/null
+++ b/gnu/packages/patches/glibc-2.28-git-fixes.patch
@@ -0,0 +1,248 @@
+This file contains fixes from the "release/2.28/master" branch:
+https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.28/master
+
+Currently we have these commits (sans tests and ChangeLog updates):
+7f11842e7483da7aa9fa3031be122021978ef600
+726e1554ce4db5e35af41cb0110c54c5e1232054
+4b25485f03158959cff45379eecc1d73c7dcdd11
+d05b05d1570ba3ae354a2f5a3cfeefb373b09979
+bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0
+2f498f3d140ab5152bd784df2be7af7d9c5e63ed
+
+diff --git a/htl/Versions b/htl/Versions
+index 6a63a1b8a1..c5a616da10 100644
+--- a/htl/Versions
++++ b/htl/Versions
+@@ -150,6 +150,8 @@ libpthread {
+     __cthread_keycreate;
+     __cthread_getspecific;
+     __cthread_setspecific;
++    __pthread_getspecific;
++    __pthread_setspecific;
+     __pthread_getattr_np;
+     __pthread_attr_getstack;
+   }
+
+diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c
+index a0227a67f6..64ddf9551a 100644
+--- a/sysdeps/htl/pt-getspecific.c
++++ b/sysdeps/htl/pt-getspecific.c
+@@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key)
+   return self->thread_specifics[key];
+ }
+ strong_alias (__pthread_getspecific, pthread_getspecific);
++hidden_def (__pthread_getspecific)
+diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c
+index a46a12f157..02aff417ef 100644
+--- a/sysdeps/htl/pt-setspecific.c
++++ b/sysdeps/htl/pt-setspecific.c
+@@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value)
+   return 0;
+ }
+ strong_alias (__pthread_setspecific, pthread_setspecific);
++hidden_def (__pthread_setspecific)
+diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h
+index 132ac1718e..71c2fcd9c6 100644
+--- a/sysdeps/htl/pthreadP.h
++++ b/sysdeps/htl/pthreadP.h
+@@ -68,6 +68,8 @@ struct __pthread_cancelation_handler 
**___pthread_get_cleanup_stack (void) attri
+ 
+ #if IS_IN (libpthread)
+ hidden_proto (__pthread_key_create)
++hidden_proto (__pthread_getspecific)
++hidden_proto (__pthread_setspecific)
+ hidden_proto (_pthread_mutex_init)
+ #endif
+ 
+diff --git a/sysdeps/unix/sysv/linux/getdents64.c 
b/sysdeps/unix/sysv/linux/getdents64.c
+index 3bde0cf4f0..bc140b5a7f 100644
+--- a/sysdeps/unix/sysv/linux/getdents64.c
++++ b/sysdeps/unix/sysv/linux/getdents64.c
+@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents)
+ # include <shlib-compat.h>
+ 
+ # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+-# include <olddirent.h>
++#  include <olddirent.h>
++#  include <unistd.h>
+ 
+-/* kernel definition of as of 3.2.  */
+-struct compat_linux_dirent
++static ssize_t
++handle_overflow (int fd, __off64_t offset, ssize_t count)
+ {
+-  /* Both d_ino and d_off are compat_ulong_t which are defined in all
+-     architectures as 'u32'.  */
+-  uint32_t        d_ino;
+-  uint32_t        d_off;
+-  unsigned short  d_reclen;
+-  char            d_name[1];
+-};
++  /* If this is the first entry in the buffer, we can report the
++     error.  */
++  if (count == 0)
++    {
++      __set_errno (EOVERFLOW);
++      return -1;
++    }
++
++  /* Otherwise, seek to the overflowing entry, so that the next call
++     will report the error, and return the data read so far..  */
++  if (__lseek64 (fd, offset, SEEK_SET) != 0)
++    return -1;
++  return count;
++}
+ 
+ ssize_t
+ __old_getdents64 (int fd, char *buf, size_t nbytes)
+ {
+-  ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
++  /* We do not move the individual directory entries.  This is only
++     possible if the target type (struct __old_dirent64) is smaller
++     than the source type.  */
++  _Static_assert (offsetof (struct __old_dirent64, d_name)
++                <= offsetof (struct dirent64, d_name),
++                "__old_dirent64 is larger than dirent64");
++  _Static_assert (__alignof__ (struct __old_dirent64)
++                <= __alignof__ (struct dirent64),
++                "alignment of __old_dirent64 is larger than dirent64");
+ 
+-  /* The kernel added the d_type value after the name.  Change this now.  */
+-  if (retval != -1)
++  ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
++  if (retval > 0)
+     {
+-      union
+-      {
+-      struct compat_linux_dirent k;
+-      struct dirent u;
+-      } *kbuf = (void *) buf;
+-
+-      while ((char *) kbuf < buf + retval)
++      char *p = buf;
++      char *end = buf + retval;
++      while (p < end)
+       {
+-        char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
+-        memmove (kbuf->u.d_name, kbuf->k.d_name,
+-                 strlen (kbuf->k.d_name) + 1);
+-        kbuf->u.d_type = d_type;
++        struct dirent64 *source = (struct dirent64 *) p;
++
++        /* Copy out the fixed-size data.  */
++        __ino_t ino = source->d_ino;
++        __off64_t offset = source->d_off;
++        unsigned int reclen = source->d_reclen;
++        unsigned char type = source->d_type;
++
++        /* Check for ino_t overflow.  */
++        if (__glibc_unlikely (ino != source->d_ino))
++          return handle_overflow (fd, offset, p - buf);
++
++        /* Convert to the target layout.  Use a separate struct and
++           memcpy to side-step aliasing issues.  */
++        struct __old_dirent64 result;
++        result.d_ino = ino;
++        result.d_off = offset;
++        result.d_reclen = reclen;
++        result.d_type = type;
++
++        /* Write the fixed-sized part of the result to the
++           buffer.  */
++        size_t result_name_offset = offsetof (struct __old_dirent64, d_name);
++        memcpy (p, &result, result_name_offset);
++
++        /* Adjust the position of the name if necessary.  Copy
++           everything until the end of the record, including the
++           terminating NUL byte.  */
++        if (result_name_offset != offsetof (struct dirent64, d_name))
++          memmove (p + result_name_offset, source->d_name,
++                   reclen - offsetof (struct dirent64, d_name));
+ 
+-        kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
++        p += reclen;
+       }
+      }
+   return retval;
+
+diff --git a/misc/error.c b/misc/error.c
+index b4e8b6c938..03378e2f2a 100644
+--- a/misc/error.c
++++ b/misc/error.c
+@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...)
+ 
+   va_start (args, message);
+   error_tail (status, errnum, message, args);
++  va_end (args);
+ 
+ #ifdef _LIBC
+   _IO_funlockfile (stderr);
+@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char 
*file_name,
+ 
+   va_start (args, message);
+   error_tail (status, errnum, message, args);
++  va_end (args);
+ 
+ #ifdef _LIBC
+   _IO_funlockfile (stderr);
+
+diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c
+index 265a02434d..7293b795b6 100644
+--- a/nscd/nscd_conf.c
++++ b/nscd/nscd_conf.c
+@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn 
dbs[lastdb])
+         if (!arg1)
+           error (0, 0, _("Must specify user name for server-user option"));
+         else
+-          server_user = xstrdup (arg1);
++          {
++            free ((char *) server_user);
++            server_user = xstrdup (arg1);
++          }
+       }
+       else if (strcmp (entry, "stat-user") == 0)
+       {
+@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn 
dbs[lastdb])
+           error (0, 0, _("Must specify user name for stat-user option"));
+         else
+           {
++            free ((char *) stat_user);
+             stat_user = xstrdup (arg1);
+ 
+             struct passwd *pw = getpwnam (stat_user);
+
+diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
+index cfd34b66b9..35b0bfc5d2 100644
+--- a/nss/nss_files/files-alias.c
++++ b/nss/nss_files/files-alias.c
+@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct 
aliasent *result,
+                       {
+                         while (! feof_unlocked (listfile))
+                           {
++                            if (room_left < 2)
++                              {
++                                free (old_line);
++                                fclose (listfile);
++                                goto no_more_room;
++                              }
++
+                             first_unused[room_left - 1] = '\xff';
+                             line = fgets_unlocked (first_unused, room_left,
+                                                    listfile);
+@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct 
aliasent *result,
+                             if (first_unused[room_left - 1] != '\xff')
+                               {
+                                 free (old_line);
++                                fclose (listfile);
+                                 goto no_more_room;
+                               }
+ 
+@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct 
aliasent *result,
+                                                      + __alignof__ (char *)))
+                                       {
+                                         free (old_line);
++                                        fclose (listfile);
+                                         goto no_more_room;
+                                       }
+                                     room_left -= ((first_unused - cp)
+
diff --git a/gnu/packages/patches/glibc-2.28-supported-locales.patch 
b/gnu/packages/patches/glibc-2.28-supported-locales.patch
new file mode 100644
index 0000000000..2888052bb8
--- /dev/null
+++ b/gnu/packages/patches/glibc-2.28-supported-locales.patch
@@ -0,0 +1,33 @@
+This patch is taken from debian's glibc package (generate-supported.mk).
+It install the localedata/SUPPORTED file of the glibc. This file lists
+all the supported locales of the glibc.
+
+diff --git a/localedata/Makefile.old b/localedata/Makefile
+index 34877c0..a61d9b9 100644
+--- a/localedata/Makefile.old
++++ b/localedata/Makefile
+@@ -91,7 +91,8 @@ endif
+ # Files to install.
+ install-others := $(addprefix $(inst_i18ndir)/, \
+                             $(addsuffix .gz, $(charmaps)) \
+-                            $(locales))
++                            $(locales)) \
++                   $(inst_i18ndir)/SUPPORTED
+ 
+ tests: $(objdir)/iconvdata/gconv-modules
+ 
+@@ -195,6 +196,14 @@ endif
+ 
+ include SUPPORTED
+ 
++$(inst_i18ndir)/SUPPORTED: SUPPORTED $(+force)
++      for locale in $(SUPPORTED-LOCALES); do \
++              [ $$locale = true ] && continue; \
++              echo $$locale | sed 's,/, ,' >> LOCALES; \
++      done
++      $(make-target-directory)
++      $(INSTALL_DATA) LOCALES $@
++
+ INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES))
+ 
+ # Sometimes the whole collection of locale files should be installed.
diff --git a/gnu/packages/patches/glibc-CVE-2015-5180.patch 
b/gnu/packages/patches/glibc-CVE-2015-5180.patch
new file mode 100644
index 0000000000..92e3740fc1
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2015-5180.patch
@@ -0,0 +1,311 @@
+From b3b37f1a5559a7620e31c8053ed1b44f798f2b6d Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Sat, 31 Dec 2016 20:22:09 +0100
+Subject: [PATCH] CVE-2015-5180: resolv: Fix crash with internal QTYPE [BZ
+ #18784]
+
+Also rename T_UNSPEC because an upcoming public header file
+update will use that name.
+
+(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5)
+---
+ ChangeLog                     |  14 ++++
+ NEWS                          |   6 ++
+ include/arpa/nameser_compat.h |   6 +-
+ resolv/Makefile               |   5 ++
+ resolv/nss_dns/dns-host.c     |   2 +-
+ resolv/res_mkquery.c          |   4 +
+ resolv/res_query.c            |   6 +-
+ resolv/tst-resolv-qtypes.c    | 185 ++++++++++++++++++++++++++++++++++++++++++
+ 8 files changed, 221 insertions(+), 7 deletions(-)
+ create mode 100644 resolv/tst-resolv-qtypes.c
+
+diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
+index 2e735ed..7c0deed 100644
+--- a/include/arpa/nameser_compat.h
++++ b/include/arpa/nameser_compat.h
+@@ -1,8 +1,8 @@
+ #ifndef _ARPA_NAMESER_COMPAT_
+ #include <resolv/arpa/nameser_compat.h>
+ 
+-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
+-   T_A and T_AAAA).  */
+-#define T_UNSPEC 62321
++/* The number is outside the 16-bit RR type range and is used
++   internally by the implementation.  */
++#define T_QUERY_A_AND_AAAA 439963904
+ 
+ #endif
+diff --git a/resolv/Makefile b/resolv/Makefile
+index 8be41d3..a4c86b9 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
+ extra-libs += libanl
+ routines += gai_sigqueue
+ tests += tst-res_hconf_reorder
++
++# This test sends millions of packets and is rather slow.
++xtests += tst-resolv-qtypes
+ endif
+ extra-libs-others = $(extra-libs)
+ libresolv-routines := gethnamaddr res_comp res_debug  \
+@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
+ $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
+       $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
+       $(evaluate-test)
++
++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
+index 5f9e357..d16fa4b 100644
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -323,7 +323,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct 
gaih_addrtuple **pat,
+ 
+   int olderr = errno;
+   enum nss_status status;
+-  int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
++  int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
+                             host_buffer.buf->buf, 2048, &host_buffer.ptr,
+                             &ans2p, &nans2p, &resplen2, &ans2p_malloced);
+   if (n >= 0)
+diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
+index 12f9730..d80b531 100644
+--- a/resolv/res_mkquery.c
++++ b/resolv/res_mkquery.c
+@@ -103,6 +103,10 @@ res_nmkquery(res_state statp,
+       int n;
+       u_char *dnptrs[20], **dpp, **lastdnptr;
+ 
++      if (class < 0 || class > 65535
++          || type < 0 || type > 65535)
++        return -1;
++
+ #ifdef DEBUG
+       if (statp->options & RES_DEBUG)
+               printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+diff --git a/resolv/res_query.c b/resolv/res_query.c
+index 944d1a9..07dc6f6 100644
+--- a/resolv/res_query.c
++++ b/resolv/res_query.c
+@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp,
+       int n, use_malloc = 0;
+       u_int oflags = statp->_flags;
+ 
+-      size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
++      size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
+       u_char *buf = alloca (bufsize);
+       u_char *query1 = buf;
+       int nquery1 = -1;
+@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp,
+               printf(";; res_query(%s, %d, %d)\n", name, class, type);
+ #endif
+ 
+-      if (type == T_UNSPEC)
++      if (type == T_QUERY_A_AND_AAAA)
+         {
+           n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
+                            query1, bufsize);
+@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp,
+       if (__builtin_expect (n <= 0, 0) && !use_malloc) {
+               /* Retry just in case res_nmkquery failed because of too
+                  short buffer.  Shouldn't happen.  */
+-              bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
++              bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
+               buf = malloc (bufsize);
+               if (buf != NULL) {
+                       query1 = buf;
+diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
+new file mode 100644
+index 0000000..b3e60c6
+--- /dev/null
++++ b/resolv/tst-resolv-qtypes.c
+@@ -0,0 +1,185 @@
++/* Exercise low-level query functions with different QTYPEs.
++   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/>.  */
++
++#include <resolv.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/check_nss.h>
++#include <support/resolv_test.h>
++#include <support/support.h>
++#include <support/test-driver.h>
++#include <support/xmemstream.h>
++
++/* If ture, the response function will send the actual response packet
++   over TCP instead of UDP.  */
++static volatile bool force_tcp;
++
++/* Send back a fake resource record matching the QTYPE.  */
++static void
++response (const struct resolv_response_context *ctx,
++          struct resolv_response_builder *b,
++          const char *qname, uint16_t qclass, uint16_t qtype)
++{
++  if (force_tcp && ctx->tcp)
++    {
++      resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
++      resolv_response_add_question (b, qname, qclass, qtype);
++      return;
++    }
++
++  resolv_response_init (b, (struct resolv_response_flags) { });
++  resolv_response_add_question (b, qname, qclass, qtype);
++  resolv_response_section (b, ns_s_an);
++  resolv_response_open_record (b, qname, qclass, qtype, 0);
++  resolv_response_add_data (b, &qtype, sizeof (qtype));
++  resolv_response_close_record (b);
++}
++
++static const const char *domain = "www.example.com";
++
++static int
++wrap_res_query (int type, unsigned char *answer, int answer_length)
++{
++  return res_query (domain, C_IN, type, answer, answer_length);
++}
++
++static int
++wrap_res_search (int type, unsigned char *answer, int answer_length)
++{
++  return res_query (domain, C_IN, type, answer, answer_length);
++}
++
++static int
++wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
++{
++  return res_querydomain ("www", "example.com", C_IN, type,
++                           answer, answer_length);
++}
++
++static int
++wrap_res_send (int type, unsigned char *answer, int answer_length)
++{
++  unsigned char buf[512];
++  int ret = res_mkquery (QUERY, domain, C_IN, type,
++                         (const unsigned char *) "", 0, NULL,
++                         buf, sizeof (buf));
++  if (type < 0 || type >= 65536)
++    {
++      /* res_mkquery fails for out-of-range record types.  */
++      TEST_VERIFY_EXIT (ret == -1);
++      return -1;
++    }
++  TEST_VERIFY_EXIT (ret > 12);  /* DNS header length.  */
++  return res_send (buf, ret, answer, answer_length);
++}
++
++static int
++wrap_res_nquery (int type, unsigned char *answer, int answer_length)
++{
++  return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
++}
++
++static int
++wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
++{
++  return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
++}
++
++static int
++wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
++{
++  return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
++                           answer, answer_length);
++}
++
++static int
++wrap_res_nsend (int type, unsigned char *answer, int answer_length)
++{
++  unsigned char buf[512];
++  int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
++                         (const unsigned char *) "", 0, NULL,
++                         buf, sizeof (buf));
++  if (type < 0 || type >= 65536)
++    {
++      /* res_mkquery fails for out-of-range record types.  */
++      TEST_VERIFY_EXIT (ret == -1);
++      return -1;
++    }
++  TEST_VERIFY_EXIT (ret > 12);  /* DNS header length.  */
++  return res_nsend (&_res, buf, ret, answer, answer_length);
++}
++
++static void
++test_function (const char *fname,
++               int (*func) (int type,
++                            unsigned char *answer, int answer_length))
++{
++  unsigned char buf[512];
++  for (int tcp = 0; tcp < 2; ++tcp)
++    {
++      force_tcp = tcp;
++      for (unsigned int type = 1; type <= 65535; ++type)
++        {
++          if (test_verbose)
++            printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
++                    type, fname, tcp);
++          int ret = func (type, buf, sizeof (buf));
++          if (ret != 47)
++            FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
++                        fname,tcp, type, ret);
++          /* One question, one answer record.  */
++          TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
++          /* Question section.  */
++          static const char qname[] = "\3www\7example\3com";
++          size_t qname_length = sizeof (qname);
++          TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
++          /* RDATA part of answer.  */
++          uint16_t type16 = type;
++          TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
++        }
++    }
++
++  TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
++  TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
++}
++
++static int
++do_test (void)
++{
++  struct resolv_redirect_config config =
++    {
++      .response_callback = response,
++    };
++  struct resolv_test *obj = resolv_test_start (config);
++
++  test_function ("res_query", &wrap_res_query);
++  test_function ("res_search", &wrap_res_search);
++  test_function ("res_querydomain", &wrap_res_querydomain);
++  test_function ("res_send", &wrap_res_send);
++
++  test_function ("res_nquery", &wrap_res_nquery);
++  test_function ("res_nsearch", &wrap_res_nsearch);
++  test_function ("res_nquerydomain", &wrap_res_nquerydomain);
++  test_function ("res_nsend", &wrap_res_nsend);
++
++  resolv_test_end (obj);
++  return 0;
++}
++
++#define TIMEOUT 300
++#include <support/test-driver.c>
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2015-7547.patch 
b/gnu/packages/patches/glibc-CVE-2015-7547.patch
new file mode 100644
index 0000000000..12abeb76d4
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2015-7547.patch
@@ -0,0 +1,590 @@
+From b995d95a5943785be3ab862b2d3276f3b4a22481 Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@systemhalted.org>
+Date: Tue, 16 Feb 2016 21:26:37 -0500
+Subject: [PATCH] CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug
+ 18665).
+
+* 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)
+
+See also:
+https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
+https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html
+
+(cherry picked from commit e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca)
+---
+ ChangeLog                 |  15 +++
+ NEWS                      |  14 +++
+ resolv/nss_dns/dns-host.c | 111 ++++++++++++++++++-
+ resolv/res_query.c        |   3 +
+ resolv/res_send.c         | 264 ++++++++++++++++++++++++++++++++++------------
+ 5 files changed, 338 insertions(+), 69 deletions(-)
+
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
+index 357ac04..a0fe9a8 100644
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -1031,7 +1031,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)
+     {
+@@ -1208,7 +1211,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;
+ }
+ 
+ 
+@@ -1222,11 +1232,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
+@@ -1242,8 +1342,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/res_query.c b/resolv/res_query.c
+index 4a9b3b3..95470a9 100644
+--- a/resolv/res_query.c
++++ b/resolv/res_query.c
+@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
+                 {
+                   free (*answerp2);
+                   *answerp2 = NULL;
++                  *nanswerp2 = 0;
+                   *answerp2_malloced = 0;
+                 }
+       }
+@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
+                         {
+                           free (*answerp2);
+                           *answerp2 = NULL;
++                          *nanswerp2 = 0;
+                           *answerp2_malloced = 0;
+                         }
+ 
+@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
+         {
+           free (*answerp2);
+           *answerp2 = NULL;
++          *nanswerp2 = 0;
+           *answerp2_malloced = 0;
+         }
+       if (saved_herrno != -1)
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 5e53cc2..6511bb1 100644
+--- 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.
+@@ -363,6 +380,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int 
buflen,
+ #ifdef USE_HOOKS
+       if (__glibc_unlikely (statp->qhook || statp->rhook))       {
+               if (anssiz < MAXPACKET && ansp) {
++                      /* Always allocate MAXPACKET, callers expect
++                         this specific size.  */
+                       u_char *buf = malloc (MAXPACKET);
+                       if (buf == NULL)
+                               return (-1);
+@@ -638,6 +657,77 @@ get_nsaddr (res_state statp, int n)
+     return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
+ }
+ 
++/* 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 field 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,
+@@ -647,11 +737,7 @@ send_vc(res_state statp,
+ {
+       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 *nsap = get_nsaddr (statp, ns);
+       int truncating, connreset, n;
+       /* On some architectures compiler might emit a warning indicating
+@@ -743,6 +829,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:
+@@ -779,40 +867,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.  */
+-#if __GNUC_PREREQ (4, 7)
+-                      DIAG_PUSH_NEEDS_COMMENT;
+-                      DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+-#endif
+-#if _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
+-#if __GNUC_PREREQ (4, 7)
+-                      DIAG_POP_NEEDS_COMMENT;
+-#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;
+@@ -820,10 +882,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 (__glibc_likely (anscp != NULL))       {
++      /* Is the answer buffer too small?  */
++      if (*thisanssizp < rlen) {
++              /* If the current buffer is not the 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;
+@@ -835,6 +901,9 @@ send_vc(res_state statp,
+                       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,
+@@ -997,6 +1066,66 @@ 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 field 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,
+@@ -1006,8 +1135,6 @@ send_dg(res_state statp,
+ {
+       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;
+@@ -1040,6 +1167,8 @@ 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;
+@@ -1203,55 +1332,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.  */
+-#if _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 not the 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);
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2016-3075.patch 
b/gnu/packages/patches/glibc-CVE-2016-3075.patch
new file mode 100644
index 0000000000..d16722806e
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-3075.patch
@@ -0,0 +1,43 @@
+From 146b58d11fddbef15b888906e3be4f33900c416f Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 29 Mar 2016 12:57:56 +0200
+Subject: [PATCH] CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ
+ #19879]
+
+The defensive copy is not needed because the name may not alias the
+output buffer.
+
+(cherry picked from commit 317b199b4aff8cfa27f2302ab404d2bb5032b9a4)
+(cherry picked from commit 883dceebc8f11921a9890211a4e202e5be17562f)
+---
+ ChangeLog                    |  7 +++++++
+ NEWS                         | 10 ++++++++--
+ resolv/nss_dns/dns-network.c |  5 +----
+ 3 files changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
+index 2eb2f67..8f301a7 100644
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -118,17 +118,14 @@ _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, name, C_IN, T_PTR, net_buffer.buf->buf,
+                              1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
+   if (anslen < 0)
+     {
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2016-3706.patch 
b/gnu/packages/patches/glibc-CVE-2016-3706.patch
new file mode 100644
index 0000000000..617242df24
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-3706.patch
@@ -0,0 +1,188 @@
+From 1a8a7c12950a0026a3c406a7cb1608f96aa1460e Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 29 Apr 2016 10:35:34 +0200
+Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent
+ conversion [BZ #20010]
+
+When converting a struct hostent response to struct gaih_addrtuple, the
+gethosts macro (which is called from gaih_inet) used alloca, without
+malloc fallback for large responses.  This commit changes this code to
+use calloc unconditionally.
+
+This commit also consolidated a second hostent-to-gaih_addrtuple
+conversion loop (in gaih_inet) to use the new conversion function.
+
+(cherry picked from commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9)
+---
+ ChangeLog                   |  10 ++++
+ sysdeps/posix/getaddrinfo.c | 130 +++++++++++++++++++++++---------------------
+ 2 files changed, 79 insertions(+), 61 deletions(-)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 1ef3f20..fed2d3b 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -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
+-                      {
+-                        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)
++                    /* We found data, convert it.  */
++                    if (!convert_hostent_to_gaih_addrtuple
++                        (req, AF_INET, h, &addrmem))
+                       {
+-                        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
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2016-4429.patch 
b/gnu/packages/patches/glibc-CVE-2016-4429.patch
new file mode 100644
index 0000000000..5eebd10543
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-4429.patch
@@ -0,0 +1,58 @@
+From bdce95930e1d9a7d013d1ba78740243491262879 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 23 May 2016 20:18:34 +0200
+Subject: [PATCH] CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ
+ #20112]
+
+The call is technically in a loop, and under certain circumstances
+(which are quite difficult to reproduce in a test case), alloca
+can be invoked repeatedly during a single call to clntudp_call.
+As a result, the available stack space can be exhausted (even
+though individual alloca sizes are bounded implicitly by what
+can fit into a UDP packet, as a side effect of the earlier
+successful send operation).
+
+(cherry picked from commit bc779a1a5b3035133024b21e2f339fe4219fb11c)
+---
+ ChangeLog         |  7 +++++++
+ NEWS              |  4 ++++
+ sunrpc/clnt_udp.c | 10 +++++++++-
+ 3 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
+index a6cf5f1..4d9acb1 100644
+--- a/sunrpc/clnt_udp.c
++++ b/sunrpc/clnt_udp.c
+@@ -388,9 +388,15 @@ send_again:
+         struct sock_extended_err *e;
+         struct sockaddr_in err_addr;
+         struct iovec iov;
+-        char *cbuf = (char *) alloca (outlen + 256);
++        char *cbuf = malloc (outlen + 256);
+         int ret;
+ 
++        if (cbuf == NULL)
++          {
++            cu->cu_error.re_errno = errno;
++            return (cu->cu_error.re_status = RPC_CANTRECV);
++          }
++
+         iov.iov_base = cbuf + 256;
+         iov.iov_len = outlen;
+         msg.msg_name = (void *) &err_addr;
+@@ -415,10 +421,12 @@ send_again:
+                cmsg = CMSG_NXTHDR (&msg, cmsg))
+             if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
+               {
++                free (cbuf);
+                 e = (struct sock_extended_err *) CMSG_DATA(cmsg);
+                 cu->cu_error.re_errno = e->ee_errno;
+                 return (cu->cu_error.re_status = RPC_CANTRECV);
+               }
++        free (cbuf);
+       }
+ #endif
+       do
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch 
b/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch
new file mode 100644
index 0000000000..71e80968be
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt1.patch
@@ -0,0 +1,36 @@
+From f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 17:09:55 +0200
+Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1
+ programs [BZ #21624]
+
+LD_LIBRARY_PATH can only be used to reorder system search paths, which
+is not useful functionality.
+
+This makes an exploitable unbounded alloca in _dl_init_paths unreachable
+for AT_SECURE=1 programs.
+
+patch from:
+https://sourceware.org/git/?p=glibc.git;a=commit;h=f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d
+---
+ ChangeLog  | 7 +++++++
+ elf/rtld.c | 3 ++-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 2446a87..2269dbe 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -2422,7 +2422,8 @@ process_envvars (enum mode *modep)
+ 
+       case 12:
+         /* The library search path.  */
+-        if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
++        if (!__libc_enable_secure
++            && memcmp (envline, "LIBRARY_PATH", 12) == 0)
+           {
+             library_path = &envline[13];
+             break;
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch 
b/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch
new file mode 100644
index 0000000000..4b859c4bfd
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt2.patch
@@ -0,0 +1,124 @@
+From 6d0ba622891bed9d8394eef1935add53003b12e8 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 22:31:04 +0200
+Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
+
+patch from:
+https://sourceware.org/git/?p=glibc.git;a=patch;h=6d0ba622891bed9d8394eef1935add53003b12e8
+
+---
+ ChangeLog  |  7 ++++++
+ elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
+ 2 files changed, 73 insertions(+), 16 deletions(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 2269dbe..86ae20c 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
+ strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
+ #endif
+ 
++/* Length limits for names and paths, to protect the dynamic linker,
++   particularly when __libc_enable_secure is active.  */
++#ifdef NAME_MAX
++# define SECURE_NAME_LIMIT NAME_MAX
++#else
++# define SECURE_NAME_LIMIT 255
++#endif
++#ifdef PATH_MAX
++# define SECURE_PATH_LIMIT PATH_MAX
++#else
++# define SECURE_PATH_LIMIT 1024
++#endif
++
++/* Check that AT_SECURE=0, or that the passed name does not contain
++   directories and is not overly long.  Reject empty names
++   unconditionally.  */
++static bool
++dso_name_valid_for_suid (const char *p)
++{
++  if (__glibc_unlikely (__libc_enable_secure))
++    {
++      /* Ignore pathnames with directories for AT_SECURE=1
++       programs, and also skip overlong names.  */
++      size_t len = strlen (p);
++      if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
++      return false;
++    }
++  return *p != '\0';
++}
+ 
+ /* List of auditing DSOs.  */
+ static struct audit_list
+@@ -718,6 +747,42 @@ static const char *preloadlist attribute_relro;
+ /* Nonzero if information about versions has to be printed.  */
+ static int version_info attribute_relro;
+ 
++/* The LD_PRELOAD environment variable gives list of libraries
++   separated by white space or colons that are loaded before the
++   executable's dependencies and prepended to the global scope list.
++   (If the binary is running setuid all elements containing a '/' are
++   ignored since it is insecure.)  Return the number of preloads
++   performed.  */
++unsigned int
++handle_ld_preload (const char *preloadlist, struct link_map *main_map)
++{
++  unsigned int npreloads = 0;
++  const char *p = preloadlist;
++  char fname[SECURE_PATH_LIMIT];
++
++  while (*p != '\0')
++    {
++      /* Split preload list at space/colon.  */
++      size_t len = strcspn (p, " :");
++      if (len > 0 && len < sizeof (fname))
++      {
++        memcpy (fname, p, len);
++        fname[len] = '\0';
++      }
++      else
++      fname[0] = '\0';
++
++      /* Skip over the substring and the following delimiter.  */
++      p += len;
++      if (*p != '\0')
++      ++p;
++
++      if (dso_name_valid_for_suid (fname))
++      npreloads += do_preload (fname, main_map, "LD_PRELOAD");
++    }
++  return npreloads;
++}
++
+ static void
+ dl_main (const ElfW(Phdr) *phdr,
+        ElfW(Word) phnum,
+@@ -1464,23 +1529,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit 
interface: %s; ignored.\n",
+ 
+   if (__glibc_unlikely (preloadlist != NULL))
+     {
+-      /* The LD_PRELOAD environment variable gives list of libraries
+-       separated by white space or colons that are loaded before the
+-       executable's dependencies and prepended to the global scope
+-       list.  If the binary is running setuid all elements
+-       containing a '/' are ignored since it is insecure.  */
+-      char *list = strdupa (preloadlist);
+-      char *p;
+-
+       HP_TIMING_NOW (start);
+-
+-      /* Prevent optimizing strsep.  Speed is not important here.  */
+-      while ((p = (strsep) (&list, " :")) != NULL)
+-      if (p[0] != '\0'
+-          && (__builtin_expect (! __libc_enable_secure, 1)
+-              || strchr (p, '/') == NULL))
+-        npreloads += do_preload (p, main_map, "LD_PRELOAD");
+-
++      npreloads += handle_ld_preload (preloadlist, main_map);
+       HP_TIMING_NOW (stop);
+       HP_TIMING_DIFF (diff, start, stop);
+       HP_TIMING_ACCUM_NT (load_time, diff);
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch 
b/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch
new file mode 100644
index 0000000000..3d8f6d2bf8
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2017-1000366-pt3.patch
@@ -0,0 +1,206 @@
+From 81b82fb966ffbd94353f793ad17116c6088dedd9 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 22:32:12 +0200
+Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements
+
+Also only process the last LD_AUDIT entry.
+
+patch from:
+https://sourceware.org/git/?p=glibc.git;a=commit;h=81b82fb966ffbd94353f793ad17116c6088dedd9
+
+---
+ ChangeLog  |  11 +++++++
+ elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
+ 2 files changed, 106 insertions(+), 15 deletions(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 86ae20c..65647fb 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
+   return *p != '\0';
+ }
+ 
+-/* List of auditing DSOs.  */
++/* LD_AUDIT variable contents.  Must be processed before the
++   audit_list below.  */
++const char *audit_list_string;
++
++/* Cyclic list of auditing DSOs.  audit_list->next is the first
++   element.  */
+ static struct audit_list
+ {
+   const char *name;
+   struct audit_list *next;
+ } *audit_list;
+ 
++/* Iterator for audit_list_string followed by audit_list.  */
++struct audit_list_iter
++{
++  /* Tail of audit_list_string still needing processing, or NULL.  */
++  const char *audit_list_tail;
++
++  /* The list element returned in the previous iteration.  NULL before
++     the first element.  */
++  struct audit_list *previous;
++
++  /* Scratch buffer for returning a name which is part of
++     audit_list_string.  */
++  char fname[SECURE_NAME_LIMIT];
++};
++
++/* Initialize an audit list iterator.  */
++static void
++audit_list_iter_init (struct audit_list_iter *iter)
++{
++  iter->audit_list_tail = audit_list_string;
++  iter->previous = NULL;
++}
++
++/* Iterate through both audit_list_string and audit_list.  */
++static const char *
++audit_list_iter_next (struct audit_list_iter *iter)
++{
++  if (iter->audit_list_tail != NULL)
++    {
++      /* First iterate over audit_list_string.  */
++      while (*iter->audit_list_tail != '\0')
++      {
++        /* Split audit list at colon.  */
++        size_t len = strcspn (iter->audit_list_tail, ":");
++        if (len > 0 && len < sizeof (iter->fname))
++          {
++            memcpy (iter->fname, iter->audit_list_tail, len);
++            iter->fname[len] = '\0';
++          }
++        else
++          /* Do not return this name to the caller.  */
++          iter->fname[0] = '\0';
++
++        /* Skip over the substring and the following delimiter.  */
++        iter->audit_list_tail += len;
++        if (*iter->audit_list_tail == ':')
++          ++iter->audit_list_tail;
++
++        /* If the name is valid, return it.  */
++        if (dso_name_valid_for_suid (iter->fname))
++          return iter->fname;
++        /* Otherwise, wrap around and try the next name.  */
++      }
++      /* Fall through to the procesing of audit_list.  */
++    }
++
++  if (iter->previous == NULL)
++    {
++      if (audit_list == NULL)
++      /* No pre-parsed audit list.  */
++      return NULL;
++      /* Start of audit list.  The first list element is at
++       audit_list->next (cyclic list).  */
++      iter->previous = audit_list->next;
++      return iter->previous->name;
++    }
++  if (iter->previous == audit_list)
++    /* Cyclic list wrap-around.  */
++    return NULL;
++  iter->previous = iter->previous->next;
++  return iter->previous->name;
++}
++
+ #ifndef HAVE_INLINED_SYSCALLS
+ /* Set nonzero during loading and initialization of executable and
+    libraries, cleared before the executable's entry point runs.  This
+@@ -1305,11 +1383,13 @@ of this helper program; chances are you did not intend 
to run this program.\n\
+     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+ 
+   /* If we have auditing DSOs to load, do it now.  */
+-  if (__glibc_unlikely (audit_list != NULL))
++  bool need_security_init = true;
++  if (__glibc_unlikely (audit_list != NULL)
++      || __glibc_unlikely (audit_list_string != NULL))
+     {
+-      /* Iterate over all entries in the list.  The order is important.  */
+       struct audit_ifaces *last_audit = NULL;
+-      struct audit_list *al = audit_list->next;
++      struct audit_list_iter al_iter;
++      audit_list_iter_init (&al_iter);
+ 
+       /* Since we start using the auditing DSOs right away we need to
+        initialize the data structures now.  */
+@@ -1320,9 +1400,14 @@ of this helper program; chances are you did not intend 
to run this program.\n\
+        use different values (especially the pointer guard) and will
+        fail later on.  */
+       security_init ();
++      need_security_init = false;
+ 
+-      do
++      while (true)
+       {
++        const char *name = audit_list_iter_next (&al_iter);
++        if (name == NULL)
++          break;
++
+         int tls_idx = GL(dl_tls_max_dtv_idx);
+ 
+         /* Now it is time to determine the layout of the static TLS
+@@ -1331,7 +1416,7 @@ of this helper program; chances are you did not intend 
to run this program.\n\
+            no DF_STATIC_TLS bit is set.  The reason is that we know
+            glibc will use the static model.  */
+         struct dlmopen_args dlmargs;
+-        dlmargs.fname = al->name;
++        dlmargs.fname = name;
+         dlmargs.map = NULL;
+ 
+         const char *objname;
+@@ -1344,7 +1429,7 @@ of this helper program; chances are you did not intend 
to run this program.\n\
+           not_loaded:
+             _dl_error_printf ("\
+ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; 
ignored.\n",
+-                              al->name, err_str);
++                              name, err_str);
+             if (malloced)
+               free ((char *) err_str);
+           }
+@@ -1448,10 +1533,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit 
interface: %s; ignored.\n",
+                 goto not_loaded;
+               }
+           }
+-
+-        al = al->next;
+       }
+-      while (al != audit_list->next);
+ 
+       /* If we have any auditing modules, announce that we already
+        have two objects loaded.  */
+@@ -1715,7 +1797,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit 
interface: %s; ignored.\n",
+   if (tcbp == NULL)
+     tcbp = init_tls ();
+ 
+-  if (__glibc_likely (audit_list == NULL))
++  if (__glibc_likely (need_security_init))
+     /* Initialize security features.  But only if we have not done it
+        earlier.  */
+     security_init ();
+@@ -2346,9 +2428,7 @@ process_dl_audit (char *str)
+   char *p;
+ 
+   while ((p = (strsep) (&str, ":")) != NULL)
+-    if (p[0] != '\0'
+-      && (__builtin_expect (! __libc_enable_secure, 1)
+-          || strchr (p, '/') == NULL))
++    if (dso_name_valid_for_suid (p))
+       {
+       /* This is using the local malloc, not the system malloc.  The
+          memory can never be freed.  */
+@@ -2412,7 +2492,7 @@ process_envvars (enum mode *modep)
+             break;
+           }
+         if (memcmp (envline, "AUDIT", 5) == 0)
+-          process_dl_audit (&envline[6]);
++          audit_list_string = &envline[6];
+         break;
+ 
+       case 7:
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2018-11236.patch 
b/gnu/packages/patches/glibc-CVE-2018-11236.patch
new file mode 100644
index 0000000000..4f8a72943c
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2018-11236.patch
@@ -0,0 +1,149 @@
+https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=5460617d1567657621107d895ee2dd83bc1f88f2
+with ChangeLog removed
+
+From 5460617d1567657621107d895ee2dd83bc1f88f2 Mon Sep 17 00:00:00 2001
+From: Paul Pluzhnikov <ppluzhnikov@google.com>
+Date: Tue, 8 May 2018 18:12:41 -0700
+Subject: [PATCH] Fix BZ 22786: integer addition overflow may cause stack
+ buffer overflow when realpath() input length is close to SSIZE_MAX.
+
+2018-05-09  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+       [BZ #22786]
+       * stdlib/canonicalize.c (__realpath): Fix overflow in path length
+       computation.
+       * stdlib/Makefile (test-bz22786): New test.
+       * stdlib/test-bz22786.c: New test.
+---
+ ChangeLog             |  8 +++++
+ stdlib/Makefile       |  2 +-
+ stdlib/canonicalize.c |  2 +-
+ stdlib/test-bz22786.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 100 insertions(+), 2 deletions(-)
+ create mode 100644 stdlib/test-bz22786.c
+
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index af1643c..1ddb1f9 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -84,7 +84,7 @@ tests                := tst-strtol tst-strtod testmb 
testrand testsort testdiv   \
+                  tst-cxa_atexit tst-on_exit test-atexit-race              \
+                  test-at_quick_exit-race test-cxa_atexit-race             \
+                  test-on_exit-race test-dlclose-exit-race                 \
+-                 tst-makecontext-align
++                 tst-makecontext-align test-bz22786
+ 
+ tests-internal        := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
+                  tst-tls-atexit tst-tls-atexit-nodelete
+diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
+index 4135f3f..390fb43 100644
+--- a/stdlib/canonicalize.c
++++ b/stdlib/canonicalize.c
+@@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved)
+               extra_buf = __alloca (path_max);
+ 
+             len = strlen (end);
+-            if ((long int) (n + len) >= path_max)
++            if (path_max - n <= len)
+               {
+                 __set_errno (ENAMETOOLONG);
+                 goto error;
+diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
+new file mode 100644
+index 0000000..e7837f9
+--- /dev/null
++++ b/stdlib/test-bz22786.c
+@@ -0,0 +1,90 @@
++/* Bug 22786: test for buffer overflow in realpath.
++   Copyright (C) 2018 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/>.  */
++
++/* This file must be run from within a directory called "stdlib".  */
++
++#include <errno.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <support/test-driver.h>
++#include <libc-diag.h>
++
++static int
++do_test (void)
++{
++  const char dir[] = "bz22786";
++  const char lnk[] = "bz22786/symlink";
++
++  rmdir (dir);
++  if (mkdir (dir, 0755) != 0 && errno != EEXIST)
++    {
++      printf ("mkdir %s: %m\n", dir);
++      return EXIT_FAILURE;
++    }
++  if (symlink (".", lnk) != 0 && errno != EEXIST)
++    {
++      printf ("symlink (%s, %s): %m\n", dir, lnk);
++      return EXIT_FAILURE;
++    }
++
++  const size_t path_len = (size_t) INT_MAX + 1;
++
++  DIAG_PUSH_NEEDS_COMMENT;
++#if __GNUC_PREREQ (7, 0)
++  /* GCC 7 warns about too-large allocations; here we need such
++     allocation to succeed for the test to work.  */
++  DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
++#endif
++  char *path = malloc (path_len);
++  DIAG_POP_NEEDS_COMMENT;
++
++  if (path == NULL)
++    {
++      printf ("malloc (%zu): %m\n", path_len);
++      return EXIT_UNSUPPORTED;
++    }
++
++  /* Construct very long path = "bz22786/symlink/aaaa....."  */
++  char *p = mempcpy (path, lnk, sizeof (lnk) - 1);
++  *(p++) = '/';
++  memset (p, 'a', path_len - (path - p) - 2);
++  p[path_len - (path - p) - 1] = '\0';
++
++  /* This call crashes before the fix for bz22786 on 32-bit platforms.  */
++  p = realpath (path, NULL);
++
++  if (p != NULL || errno != ENAMETOOLONG)
++    {
++      printf ("realpath: %s (%m)", p);
++      return EXIT_FAILURE;
++    }
++
++  /* Cleanup.  */
++  unlink (lnk);
++  rmdir (dir);
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test
++#include <support/test-driver.c>
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2018-11237.patch 
b/gnu/packages/patches/glibc-CVE-2018-11237.patch
new file mode 100644
index 0000000000..8a7c604ecd
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2018-11237.patch
@@ -0,0 +1,55 @@
+https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=9aaaab7c6e4176e61c59b0a63c6ba906d875dc0e
+with the ChangeLog removed
+
+From 9aaaab7c6e4176e61c59b0a63c6ba906d875dc0e Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@suse.de>
+Date: Tue, 22 May 2018 10:37:59 +0200
+Subject: [PATCH] Don't write beyond destination in
+ __mempcpy_avx512_no_vzeroupper (bug 23196)
+
+When compiled as mempcpy, the return value is the end of the destination
+buffer, thus it cannot be used to refer to the start of it.
+---
+ ChangeLog                                               | 9 +++++++++
+ string/test-mempcpy.c                                   | 1 +
+ sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S | 5 +++--
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c
+index c08fba8..d98ecdd 100644
+--- a/string/test-mempcpy.c
++++ b/string/test-mempcpy.c
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #define MEMCPY_RESULT(dst, len) (dst) + (len)
++#define MIN_PAGE_SIZE 131072
+ #define TEST_MAIN
+ #define TEST_NAME "mempcpy"
+ #include "test-string.h"
+diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S 
b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
+index 23c0f7a..effc3ac 100644
+--- a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
++++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
+@@ -336,6 +336,7 @@ L(preloop_large):
+       vmovups (%rsi), %zmm4
+       vmovups 0x40(%rsi), %zmm5
+ 
++      mov     %rdi, %r11
+ /* Align destination for access with non-temporal stores in the loop.  */
+       mov     %rdi, %r8
+       and     $-0x80, %rdi
+@@ -366,8 +367,8 @@ L(gobble_256bytes_nt_loop):
+       cmp     $256, %rdx
+       ja      L(gobble_256bytes_nt_loop)
+       sfence
+-      vmovups %zmm4, (%rax)
+-      vmovups %zmm5, 0x40(%rax)
++      vmovups %zmm4, (%r11)
++      vmovups %zmm5, 0x40(%r11)
+       jmp     L(check)
+ 
+ L(preloop_large_bkw):
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-cvs-common-symbols.patch 
b/gnu/packages/patches/glibc-cvs-common-symbols.patch
new file mode 100644
index 0000000000..7764c99fa6
--- /dev/null
+++ b/gnu/packages/patches/glibc-cvs-common-symbols.patch
@@ -0,0 +1,58 @@
+commit 388b4f1a02f3a801965028bbfcd48d905638b797
+Author: H.J. Lu <hjl.tools@gmail.com>
+Date:   Fri Jun 23 14:38:46 2017 -0700
+
+    Avoid .symver on common symbols [BZ #21666]
+    
+    The .symver directive on common symbol just creates a new common symbol,
+    not an alias and the newer assembler with the bug fix for
+    
+    https://sourceware.org/bugzilla/show_bug.cgi?id=21661
+    
+    will issue an error.  Before the fix, we got
+    
+    $ readelf -sW libc.so | grep "loc[12s]"
+      5109: 00000000003a0608     8 OBJECT  LOCAL  DEFAULT   36 loc1
+      5188: 00000000003a0610     8 OBJECT  LOCAL  DEFAULT   36 loc2
+      5455: 00000000003a0618     8 OBJECT  LOCAL  DEFAULT   36 locs
+      6575: 00000000003a05f0     8 OBJECT  GLOBAL DEFAULT   36 locs@GLIBC_2.2.5
+      7156: 00000000003a05f8     8 OBJECT  GLOBAL DEFAULT   36 loc1@GLIBC_2.2.5
+      7312: 00000000003a0600     8 OBJECT  GLOBAL DEFAULT   36 loc2@GLIBC_2.2.5
+    
+    in libc.so.  The versioned loc1, loc2 and locs have the wrong addresses.
+    After the fix, we got
+    
+    $ readelf -sW libc.so | grep "loc[12s]"
+      6570: 000000000039e3b8     8 OBJECT  GLOBAL DEFAULT   34 locs@GLIBC_2.2.5
+      7151: 000000000039e3c8     8 OBJECT  GLOBAL DEFAULT   34 loc1@GLIBC_2.2.5
+      7307: 000000000039e3c0     8 OBJECT  GLOBAL DEFAULT   34 loc2@GLIBC_2.2.5
+    
+            [BZ #21666]
+            * misc/regexp.c (loc1): Add __attribute__ ((nocommon));
+            (loc2): Likewise.
+            (locs): Likewise.
+
+diff --git a/misc/regexp.c b/misc/regexp.c
+index 19d76c0c37..eaea7c3b89 100644
+--- a/misc/regexp.c
++++ b/misc/regexp.c
+@@ -29,14 +29,15 @@
+ 
+ #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23)
+ 
+-/* Define the variables used for the interface.  */
+-char *loc1;
+-char *loc2;
++/* Define the variables used for the interface.  Avoid .symver on common
++   symbol, which just creates a new common symbol, not an alias.  */
++char *loc1 __attribute__ ((nocommon));
++char *loc2 __attribute__ ((nocommon));
+ compat_symbol (libc, loc1, loc1, GLIBC_2_0);
+ compat_symbol (libc, loc2, loc2, GLIBC_2_0);
+ 
+ /* Although we do not support the use we define this variable as well.  */
+-char *locs;
++char *locs __attribute__ ((nocommon));
+ compat_symbol (libc, locs, locs, GLIBC_2_0);
+ 
+ 
diff --git a/gnu/packages/patches/glibc-hurd-magic-pid.patch 
b/gnu/packages/patches/glibc-hurd-magic-pid.patch
new file mode 100644
index 0000000000..a6849f7d35
--- /dev/null
+++ b/gnu/packages/patches/glibc-hurd-magic-pid.patch
@@ -0,0 +1,190 @@
+This patch implements "magic" lookup for "pid/…", as used when looking up
+/proc/self.
+
+The patch comes from the 't/magic-pid' branch
+at <https://git.savannah.gnu.org/cgit/hurd/glibc.git>.  It squashes
+commit 392e52286a302ca6157fbd221295e64ab6b6d8ba (by Justus Winter)
+and commit 392e52286a302ca6157fbd221295e64ab6b6d8ba (a subsequent fix by
+Samuel Thibault).
+
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Subject: [PATCH] hurd: Handle `pid' magical lookup retry
+
+        * hurd/lookup-retry.c: Handle `pid' magical lookup
+        retry.
+
+diff --git a/hurd/lookup-retry.c b/hurd/lookup-retry.c
+index aee2ba8f93..6ed8de1653 100644
+--- a/hurd/lookup-retry.c
++++ b/hurd/lookup-retry.c
+@@ -25,6 +25,7 @@
+ #include <string.h>
+ #include <_itoa.h>
+ #include <eloop-threshold.h>
++#include <unistd.h>
+ 
+ /* Translate the error from dir_lookup into the error the user sees.  */
+ static inline error_t
+@@ -59,6 +60,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+   error_t err;
+   char *file_name;
+   int nloops;
++  file_t lastdir = MACH_PORT_NULL;
+ 
+   error_t lookup_op (file_t startdir)
+     {
+@@ -107,14 +109,15 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+       {
+       case FS_RETRY_REAUTH:
+         if (err = reauthenticate (*result))
+-          return err;
++          goto out;
+         /* Fall through.  */
+ 
+       case FS_RETRY_NORMAL:
+         if (nloops++ >= __eloop_threshold ())
+           {
+             __mach_port_deallocate (__mach_task_self (), *result);
+-            return ELOOP;
++            err = ELOOP;
++            goto out;
+           }
+ 
+         /* An empty RETRYNAME indicates we have the final port.  */
+@@ -174,7 +177,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+ 
+             if (err)
+               __mach_port_deallocate (__mach_task_self (), *result);
+-            return err;
++            goto out;
+           }
+ 
+         startdir = *result;
+@@ -189,7 +192,10 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+             if (*result != MACH_PORT_NULL)
+               __mach_port_deallocate (__mach_task_self (), *result);
+             if (nloops++ >= __eloop_threshold ())
+-              return ELOOP;
++              {
++                err = ELOOP;
++                goto out;
++              }
+             file_name = &retryname[1];
+             break;
+ 
+@@ -208,7 +214,8 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+                     (*end != '/' && *end != '\0'))
+                   {
+                     errno = save;
+-                    return ENOENT;
++                    err = ENOENT;
++                    goto out;
+                   }
+                 if (! get_dtable_port)
+                   err = EGRATUITOUS;
+@@ -226,9 +233,12 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+                   }
+                 errno = save;
+                 if (err)
+-                  return err;
++                  goto out;
+                 if (*end == '\0')
+-                  return 0;
++                  {
++                    err = 0;
++                    goto out;
++                  }
+                 else
+                   {
+                     /* Do a normal retry on the remaining components.  */
+@@ -255,9 +265,12 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+                 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
+                                        (integer_t *) &hostinfo,
+                                        &hostinfocnt))
+-                  return err;
++                  goto out;
+                 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
+-                  return EGRATUITOUS;
++                  {
++                    err = EGRATUITOUS;
++                    goto out;
++                  }
+                 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
+                 *--p = '/';
+                 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
+@@ -293,10 +306,11 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+                     }
+ 
+                 case '\0':
+-                  return opentty (result);
++                  err = opentty (result);
++                  goto out;
+                 case '/':
+                   if (err = opentty (&startdir))
+-                    return err;
++                    goto out;
+                   strcpy (retryname, &retryname[4]);
+                   break;
+                 default:
+@@ -306,14 +320,48 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+               goto bad_magic;
+             break;
+ 
++          case 'p':
++            if (retryname[1] == 'i' && retryname[2] == 'd' &&
++                (retryname[3] == '/' || retryname[3] == 0))
++              {
++                char *p, buf[1024];  /* XXX */
++                size_t len;
++                p = _itoa (__getpid (), &buf[sizeof buf], 10, 0);
++                len = &buf[sizeof buf] - p;
++                memcpy (buf, p, len);
++                strcpy (buf + len, &retryname[3]);
++                strcpy (retryname, buf);
++
++                /* Do a normal retry on the remaining components.  */
++                __mach_port_mod_refs (__mach_task_self (), lastdir,
++                                      MACH_PORT_RIGHT_SEND, 1);
++                startdir = lastdir;
++                file_name = retryname;
++              }
++            else
++              goto bad_magic;
++            break;
++
+           default:
+           bad_magic:
+-            return EGRATUITOUS;
++            err = EGRATUITOUS;
++            goto out;
+           }
+         break;
+ 
+       default:
+-        return EGRATUITOUS;
++        err = EGRATUITOUS;
++        goto out;
++      }
++
++      if (MACH_PORT_VALID (*result) && *result != lastdir)
++      {
++        if (MACH_PORT_VALID (lastdir))
++          __mach_port_deallocate (__mach_task_self (), lastdir);
++
++        lastdir = *result;
++        __mach_port_mod_refs (__mach_task_self (), lastdir,
++                              MACH_PORT_RIGHT_SEND, 1);
+       }
+ 
+       if (startdir != MACH_PORT_NULL)
+@@ -326,6 +374,10 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
+       err = (*use_init_port) (dirport, &lookup_op);
+     } while (! err);
+ 
++out:
++  if (MACH_PORT_VALID (lastdir))
++    __mach_port_deallocate (__mach_task_self (), lastdir);
++
+   return err;
+ }
+ weak_alias (__hurd_file_name_lookup_retry, hurd_file_name_lookup_retry)
diff --git a/gnu/packages/patches/glibc-o-largefile.patch 
b/gnu/packages/patches/glibc-o-largefile.patch
new file mode 100644
index 0000000000..2b0ae8c8bb
--- /dev/null
+++ b/gnu/packages/patches/glibc-o-largefile.patch
@@ -0,0 +1,25 @@
+This fixes <https://sourceware.org/bugzilla/show_bug.cgi?id=18781>
+whereby, on 32-bit platforms, libc 2.22 would fail to pass O_LARGEFILE
+to 'openat'.  This was caught by 'tests/sparse03.at' in the tar
+test suite.
+
+commit eb32b0d40308166c4d8f6330cc2958cb1e545075
+Author: Andreas Schwab <schwab@suse.de>
+Date:   Mon Aug 10 14:12:47 2015 +0200
+
+    Readd O_LARGEFILE flag for openat64 (bug 18781)
+
+--- a/sysdeps/unix/sysv/linux/openat.c
++++ b/sysdeps/unix/sysv/linux/openat.c
+@@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...)
+       va_end (arg);
+     }
+ 
++  /* We have to add the O_LARGEFILE flag for openat64.  */
++#ifdef MORE_OFLAGS
++  oflag |= MORE_OFLAGS;
++#endif
++
+   return SYSCALL_CANCEL (openat, fd, file, oflag, mode);
+ }
+ libc_hidden_def (__OPENAT)
diff --git a/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch 
b/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch
new file mode 100644
index 0000000000..3d6c7749d4
--- /dev/null
+++ b/gnu/packages/patches/glibc-vectorized-strcspn-guards.patch
@@ -0,0 +1,23 @@
+Copied from Debian.
+
+2017-06-14  Florian Weimer  <fweimer@redhat.com>
+
+       * sysdeps/i386/i686/multiarch/strcspn-c.c: Add IS_IN (libc) guard.
+       * sysdeps/i386/i686/multiarch/varshift.c: Likewise.
+
+--- a/sysdeps/i386/i686/multiarch/strcspn-c.c
++++ b/sysdeps/i386/i686/multiarch/strcspn-c.c
+@@ -1,2 +1,4 @@
+-#define __strcspn_sse2 __strcspn_ia32
+-#include <sysdeps/x86_64/multiarch/strcspn-c.c>
++#if IS_IN (libc)
++# define __strcspn_sse2 __strcspn_ia32
++# include <sysdeps/x86_64/multiarch/strcspn-c.c>
++#endif
+--- a/sysdeps/i386/i686/multiarch/varshift.c
++++ b/sysdeps/i386/i686/multiarch/varshift.c
+@@ -1 +1,3 @@
+-#include <sysdeps/x86_64/multiarch/varshift.c>
++#if IS_IN (libc)
++# include <sysdeps/x86_64/multiarch/varshift.c>
++#endif

base-commit: c6f81ff7a6a527b5a14189a2c359b981ddba43bc
prerequisite-patch-id: 77c51f63cfaba6cafe4e7125f50077d6dc5ca24a
prerequisite-patch-id: 776778c03bce9b7ad3ab94a120f42b764c00fcae
prerequisite-patch-id: 4910d08bdc27384d76030b6ac491ad2c2ed0957f
prerequisite-patch-id: 2de8762a6381a93682d0fe4c893962b9803362b0
prerequisite-patch-id: b9b6f21a2db3f7a5ef82bb11ed23f69749cc6b3d
prerequisite-patch-id: fd4074fb4cf068ccac3122c19138f098a610542a
prerequisite-patch-id: 2b8e69760af1f7bfb66c1edb44471653b6b229d1
prerequisite-patch-id: 51cecbabc04c69d4338addaece536c42a075660f
prerequisite-patch-id: 2c67bfd85b343a65440e6c63451e5417129dea6f
prerequisite-patch-id: 7c7e8e7affe4a115423836e82a0930db2b25ae59
prerequisite-patch-id: 53f792328e96bc30e638d953317e730535d89d42
-- 
2.38.1






reply via email to

[Prev in Thread] Current Thread [Next in Thread]