CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
glibc: sync with upstream 2.32 branch
authorVictor Martinez <pitillo@ono.com>
Mon, 16 Aug 2021 16:51:55 +0000 (18:51 +0200)
committerVictor Martinez <pitillo@ono.com>
Mon, 16 Aug 2021 16:51:55 +0000 (18:51 +0200)
glibc/.signature
glibc/Pkgfile
glibc/glibc-2.32-4.patch [moved from glibc/glibc-2.32-3.patch with 83% similarity]

index 1b9494184704d718a34afa3933bc7c01773f30e3..7336798d02a7dc9a400a5e3af1a30b98650a7b41 100644 (file)
@@ -1,10 +1,10 @@
 untrusted comment: verify with /etc/ports/core-arm64.pub
 untrusted comment: verify with /etc/ports/core-arm64.pub
-RWSKslkvIwb+2TiAM+qlQMm5LIeG/8o5YyrOhDNJcN0mcAiDyHTaWHrq/Euq2B/lkKXoz7DkLcz064Xmebfmc8BIm5I5CGfCZg4=
-SHA256 (Pkgfile) = 4e4d4bde65cc20f9332fcbfba88564b5173fceb1bea444e9147473c7c623ebd7
+RWSKslkvIwb+2dHGq53TY3V8hJm7rj/rOd8XfxKXr2rgQjoV7+VJnJX3lGOpYBQ/G0NTdzREj6vs7rmKjhwRV5J8gjkZJ/rdyAw=
+SHA256 (Pkgfile) = 366156379536c0ba86b0fb76c9a8b5e3243ad5ff21171e8741ef4e905de14614
 SHA256 (.footprint) = ab59b6f81ccffce49e3183ef01f479f7ddc4ddd5802dceb20d16b20849ae388d
 SHA256 (glibc-2.32.tar.xz) = 1627ea54f5a1a8467032563393e0901077626dc66f37f10ee6363bb722222836
 SHA256 (linux-4.19.24.tar.xz) = 3bb1885fabd874b469a8ea19571c5a4ad5b6faa3cca1662137c57b40fcbf8e04
 SHA256 (.footprint) = ab59b6f81ccffce49e3183ef01f479f7ddc4ddd5802dceb20d16b20849ae388d
 SHA256 (glibc-2.32.tar.xz) = 1627ea54f5a1a8467032563393e0901077626dc66f37f10ee6363bb722222836
 SHA256 (linux-4.19.24.tar.xz) = 3bb1885fabd874b469a8ea19571c5a4ad5b6faa3cca1662137c57b40fcbf8e04
-SHA256 (glibc-2.32-3.patch) = 6d84a6054984e89c4b139dfa1a29561ee2f146bafa479f1c465700220a6aee73
+SHA256 (glibc-2.32-4.patch) = 3c93822f91229e21fb718390fd41a0dd279032e80c878d2657d268e77f851202
 SHA256 (hosts) = 5c02b256c105f1d4a12fb738d71c1bab9eb126533074d7a0c8a14b92670c9431
 SHA256 (resolv.conf) = 72ccb58768a72a771ec37142bc361a18478a07ec9de6e925a20760794389bf51
 SHA256 (nsswitch.conf) = 859b8984e5e90aff3cce8f9779996ae4033b280d2122840e9411e2f44a1c2e61
 SHA256 (hosts) = 5c02b256c105f1d4a12fb738d71c1bab9eb126533074d7a0c8a14b92670c9431
 SHA256 (resolv.conf) = 72ccb58768a72a771ec37142bc361a18478a07ec9de6e925a20760794389bf51
 SHA256 (nsswitch.conf) = 859b8984e5e90aff3cce8f9779996ae4033b280d2122840e9411e2f44a1c2e61
index 8aba423a1f23c3fdf8e5ebad8ca0eb9a05e4872a..49a00bdb1b73f4c4594f517e1fd1e8580d1f3159 100644 (file)
@@ -6,10 +6,10 @@
 
 name=glibc
 version=2.32
 
 name=glibc
 version=2.32
-release=3
+release=4
 source=(http://ftp.gnu.org/gnu/glibc/glibc-$version.tar.xz \
         http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.24.tar.xz \
 source=(http://ftp.gnu.org/gnu/glibc/glibc-$version.tar.xz \
         http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.24.tar.xz \
-        glibc-$version-3.patch \
+        glibc-$version-4.patch \
         hosts resolv.conf nsswitch.conf host.conf ld.so.conf)
 
 build() {
         hosts resolv.conf nsswitch.conf host.conf ld.so.conf)
 
 build() {
@@ -20,7 +20,7 @@ build() {
   make ARCH=arm64 INSTALL_HDR_PATH=$PKG/usr headers_install
   chown root:root $PKG/usr
 
   make ARCH=arm64 INSTALL_HDR_PATH=$PKG/usr headers_install
   chown root:root $PKG/usr
 
-  patch -p1 -d $SRC/$name-${version:0:4} -i $SRC/$name-$version-3.patch
+  patch -p1 -d $SRC/$name-${version:0:4} -i $SRC/$name-$version-4.patch
 
   mkdir $SRC/build
   cd $SRC/build
 
   mkdir $SRC/build
   cd $SRC/build
similarity index 83%
rename from glibc/glibc-2.32-3.patch
rename to glibc/glibc-2.32-4.patch
index 8195ec34535ce6cfbfa4e04b4d41716205ce011a..ea46dfbdb512985c8c0c46fa2a3a4683fadb52f0 100644 (file)
@@ -1,5 +1,5 @@
 diff --git a/NEWS b/NEWS
 diff --git a/NEWS b/NEWS
-index 485b8ddffa..f278041512 100644
+index 485b8ddffa..2afe250ccf 100644
 --- a/NEWS
 +++ b/NEWS
 @@ -5,6 +5,25 @@ See the end for copying conditions.
 --- a/NEWS
 +++ b/NEWS
 @@ -5,6 +5,25 @@ See the end for copying conditions.
@@ -28,13 +28,17 @@ index 485b8ddffa..f278041512 100644
  Version 2.32
  
  Major new features:
  Version 2.32
  
  Major new features:
-@@ -185,6 +204,10 @@ Security related changes:
+@@ -185,6 +204,14 @@ Security related changes:
    Dytrych of the Cisco Security Assessment and Penetration Team (See
    TALOS-2020-1019).
  
 +  CVE-2020-27618: An infinite loop has been fixed in the iconv program when
 +  invoked with input containing redundant shift sequences in the IBM1364,
 +  IBM1371, IBM1388, IBM1390, or IBM1399 character sets.
    Dytrych of the Cisco Security Assessment and Penetration Team (See
    TALOS-2020-1019).
  
 +  CVE-2020-27618: An infinite loop has been fixed in the iconv program when
 +  invoked with input containing redundant shift sequences in the IBM1364,
 +  IBM1371, IBM1388, IBM1390, or IBM1399 character sets.
++
++  CVE-2021-33574: The mq_notify function has a potential use-after-free
++  issue when using a notification type of SIGEV_THREAD and a thread
++  attribute with a non-default affinity mask.
 +
  The following bugs are resolved with this release:
  
 +
  The following bugs are resolved with this release:
  
@@ -194,7 +198,7 @@ index 4ab7e182b7..0000000000
 -
 -#include <string.h>
 diff --git a/elf/Makefile b/elf/Makefile
 -
 -#include <string.h>
 diff --git a/elf/Makefile b/elf/Makefile
-index 0b78721848..355e70037b 100644
+index 0b78721848..3ba7f4ecfc 100644
 --- a/elf/Makefile
 +++ b/elf/Makefile
 @@ -1381,6 +1381,8 @@ CFLAGS-ifuncmain7pie.c += $(pie-ccflag)
 --- a/elf/Makefile
 +++ b/elf/Makefile
 @@ -1381,6 +1381,8 @@ CFLAGS-ifuncmain7pie.c += $(pie-ccflag)
@@ -206,6 +210,15 @@ index 0b78721848..355e70037b 100644
  $(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so
  $(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o
  $(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so
  $(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so
  $(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o
  $(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so
+@@ -1630,8 +1632,6 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
+ tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
+                    LD_HWCAP_MASK=0x1
+-tst-env-setuid-tunables-ENV = \
+-      GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
+ $(objpfx)tst-debug1: $(libdl)
+ $(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so
 diff --git a/elf/dl-load.c b/elf/dl-load.c
 index e39980fb19..71867e7c1a 100644
 --- a/elf/dl-load.c
 diff --git a/elf/dl-load.c b/elf/dl-load.c
 index e39980fb19..71867e7c1a 100644
 --- a/elf/dl-load.c
@@ -278,6 +291,97 @@ index e39980fb19..71867e7c1a 100644
    /* We are done mapping in the file.  We no longer need the descriptor.  */
    if (__glibc_unlikely (__close_nocancel (fd) != 0))
      {
    /* We are done mapping in the file.  We no longer need the descriptor.  */
    if (__glibc_unlikely (__close_nocancel (fd) != 0))
      {
+diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
+index 26e6e26612..15b29bcb90 100644
+--- a/elf/dl-tunables.c
++++ b/elf/dl-tunables.c
+@@ -177,6 +177,7 @@ parse_tunables (char *tunestr, char *valstring)
+     return;
+   char *p = tunestr;
++  size_t off = 0;
+   while (true)
+     {
+@@ -190,7 +191,11 @@ parse_tunables (char *tunestr, char *valstring)
+       /* If we reach the end of the string before getting a valid name-value
+        pair, bail out.  */
+       if (p[len] == '\0')
+-      return;
++      {
++        if (__libc_enable_secure)
++          tunestr[off] = '\0';
++        return;
++      }
+       /* We did not find a valid name-value pair before encountering the
+        colon.  */
+@@ -216,35 +221,28 @@ parse_tunables (char *tunestr, char *valstring)
+         if (tunable_is_name (cur->name, name))
+           {
+-            /* If we are in a secure context (AT_SECURE) then ignore the tunable
+-               unless it is explicitly marked as secure.  Tunable values take
+-               precedence over their envvar aliases.  */
++            /* If we are in a secure context (AT_SECURE) then ignore the
++               tunable unless it is explicitly marked as secure.  Tunable
++               values take precedence over their envvar aliases.  We write
++               the tunables that are not SXID_ERASE back to TUNESTR, thus
++               dropping all SXID_ERASE tunables and any invalid or
++               unrecognized tunables.  */
+             if (__libc_enable_secure)
+               {
+-                if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
++                if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
+                   {
+-                    if (p[len] == '\0')
+-                      {
+-                        /* Last tunable in the valstring.  Null-terminate and
+-                           return.  */
+-                        *name = '\0';
+-                        return;
+-                      }
+-                    else
+-                      {
+-                        /* Remove the current tunable from the string.  We do
+-                           this by overwriting the string starting from NAME
+-                           (which is where the current tunable begins) with
+-                           the remainder of the string.  We then have P point
+-                           to NAME so that we continue in the correct
+-                           position in the valstring.  */
+-                        char *q = &p[len + 1];
+-                        p = name;
+-                        while (*q != '\0')
+-                          *name++ = *q++;
+-                        name[0] = '\0';
+-                        len = 0;
+-                      }
++                    if (off > 0)
++                      tunestr[off++] = ':';
++
++                    const char *n = cur->name;
++
++                    while (*n != '\0')
++                      tunestr[off++] = *n++;
++
++                    tunestr[off++] = '=';
++
++                    for (size_t j = 0; j < len; j++)
++                      tunestr[off++] = value[j];
+                   }
+                 if (cur->security_level != TUNABLE_SECLEVEL_NONE)
+@@ -257,9 +255,7 @@ parse_tunables (char *tunestr, char *valstring)
+           }
+       }
+-      if (p[len] == '\0')
+-      return;
+-      else
++      if (p[len] != '\0')
+       p += len + 1;
+     }
+ }
 diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c
 index 04faeb86ef..4a01906836 100644
 --- a/elf/ifuncmain6pie.c
 diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c
 index 04faeb86ef..4a01906836 100644
 --- a/elf/ifuncmain6pie.c
@@ -369,6 +473,391 @@ index 5b882163fa..14a42ed00a 100644
        break;
        }
  
        break;
        }
  
+diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
+index 971d5892b1..ca0c8c245c 100644
+--- a/elf/tst-env-setuid-tunables.c
++++ b/elf/tst-env-setuid-tunables.c
+@@ -25,35 +25,76 @@
+ #include "config.h"
+ #undef _LIBC
+-#define test_parent test_parent_tunables
+-#define test_child test_child_tunables
+-
+-static int test_child_tunables (void);
+-static int test_parent_tunables (void);
+-
+-#include "tst-env-setuid.c"
+-
+-#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096"
+-#define PARENT_VALSTRING_VALUE \
+-  "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096"
++#include <errno.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <unistd.h>
++#include <intprops.h>
++#include <array_length.h>
++
++#include <support/check.h>
++#include <support/support.h>
++#include <support/test-driver.h>
++#include <support/capture_subprocess.h>
++
++const char *teststrings[] =
++{
++  "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.check=2:glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096:glibc.malloc.check=2",
++  "glibc.malloc.perturb=0x800",
++  "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
++  "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
++  "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
++  "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
++  ":glibc.malloc.garbage=2:glibc.malloc.check=1",
++  "glibc.malloc.check=1:glibc.malloc.check=2",
++  "not_valid.malloc.check=2",
++  "glibc.not_valid.check=2",
++};
++
++const char *resultstrings[] =
++{
++  "glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.perturb=0x800",
++  "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.mmap_threshold=4096",
++  "glibc.malloc.mmap_threshold=4096",
++  "",
++  "",
++  "",
++  "",
++  "",
++  "",
++};
+ static int
+-test_child_tunables (void)
++test_child (int off)
+ {
+   const char *val = getenv ("GLIBC_TUNABLES");
+ #if HAVE_TUNABLES
+-  if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0)
++  if (val != NULL && strcmp (val, resultstrings[off]) == 0)
+     return 0;
+   if (val != NULL)
+-    printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
++    printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
+   return 1;
+ #else
+   if (val != NULL)
+     {
+-      printf ("GLIBC_TUNABLES not cleared\n");
++      printf ("[%d] GLIBC_TUNABLES not cleared\n", off);
+       return 1;
+     }
+   return 0;
+@@ -61,15 +102,48 @@ test_child_tunables (void)
+ }
+ static int
+-test_parent_tunables (void)
++do_test (int argc, char **argv)
+ {
+-  const char *val = getenv ("GLIBC_TUNABLES");
++  /* Setgid child process.  */
++  if (argc == 2)
++    {
++      if (getgid () == getegid ())
++      /* This can happen if the file system is mounted nosuid.  */
++      FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
++                        (intmax_t) getgid ());
+-  if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0)
+-    return 0;
++      int ret = test_child (atoi (argv[1]));
+-  if (val != NULL)
+-    printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
++      if (ret != 0)
++      exit (1);
+-  return 1;
++      exit (EXIT_SUCCESS);
++    }
++  else
++    {
++      int ret = 0;
++
++      /* Spawn tests.  */
++      for (int i = 0; i < array_length (teststrings); i++)
++      {
++        char buf[INT_BUFSIZE_BOUND (int)];
++
++        printf ("Spawned test for %s (%d)\n", teststrings[i], i);
++        snprintf (buf, sizeof (buf), "%d\n", i);
++        if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
++          exit (1);
++
++        int status = support_capture_subprogram_self_sgid (buf);
++
++        /* Bail out early if unsupported.  */
++        if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
++          return EXIT_UNSUPPORTED;
++
++        ret |= status;
++      }
++      return ret;
++    }
+ }
++
++#define TEST_FUNCTION_ARGV do_test
++#include <support/test-driver.c>
+diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c
+index 41dc79e83a..2dbccdb69e 100644
+--- a/elf/tst-env-setuid.c
++++ b/elf/tst-env-setuid.c
+@@ -29,173 +29,12 @@
+ #include <sys/wait.h>
+ #include <unistd.h>
++#include <support/check.h>
+ #include <support/support.h>
+ #include <support/test-driver.h>
++#include <support/capture_subprocess.h>
+ static char SETGID_CHILD[] = "setgid-child";
+-#define CHILD_STATUS 42
+-
+-/* Return a GID which is not our current GID, but is present in the
+-   supplementary group list.  */
+-static gid_t
+-choose_gid (void)
+-{
+-  const int count = 64;
+-  gid_t groups[count];
+-  int ret = getgroups (count, groups);
+-  if (ret < 0)
+-    {
+-      printf ("getgroups: %m\n");
+-      exit (1);
+-    }
+-  gid_t current = getgid ();
+-  for (int i = 0; i < ret; ++i)
+-    {
+-      if (groups[i] != current)
+-      return groups[i];
+-    }
+-  return 0;
+-}
+-
+-/* Spawn and execute a program and verify that it returns the CHILD_STATUS.  */
+-static pid_t
+-do_execve (char **args)
+-{
+-  pid_t kid = vfork ();
+-
+-  if (kid < 0)
+-    {
+-      printf ("vfork: %m\n");
+-      return -1;
+-    }
+-
+-  if (kid == 0)
+-    {
+-      /* Child process.  */
+-      execve (args[0], args, environ);
+-      _exit (-errno);
+-    }
+-
+-  if (kid < 0)
+-    return 1;
+-
+-  int status;
+-
+-  if (waitpid (kid, &status, 0) < 0)
+-    {
+-      printf ("waitpid: %m\n");
+-      return 1;
+-    }
+-
+-  if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
+-    return EXIT_UNSUPPORTED;
+-
+-  if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS)
+-    {
+-      printf ("Unexpected exit status %d from child process\n",
+-            WEXITSTATUS (status));
+-      return 1;
+-    }
+-  return 0;
+-}
+-
+-/* Copies the executable into a restricted directory, so that we can
+-   safely make it SGID with the TARGET group ID.  Then runs the
+-   executable.  */
+-static int
+-run_executable_sgid (gid_t target)
+-{
+-  char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd",
+-                           test_dir, (intmax_t) getpid ());
+-  char *execname = xasprintf ("%s/bin", dirname);
+-  int infd = -1;
+-  int outfd = -1;
+-  int ret = 0;
+-  if (mkdir (dirname, 0700) < 0)
+-    {
+-      printf ("mkdir: %m\n");
+-      goto err;
+-    }
+-  infd = open ("/proc/self/exe", O_RDONLY);
+-  if (infd < 0)
+-    {
+-      printf ("open (/proc/self/exe): %m\n");
+-      goto err;
+-    }
+-  outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
+-  if (outfd < 0)
+-    {
+-      printf ("open (%s): %m\n", execname);
+-      goto err;
+-    }
+-  char buf[4096];
+-  for (;;)
+-    {
+-      ssize_t rdcount = read (infd, buf, sizeof (buf));
+-      if (rdcount < 0)
+-      {
+-        printf ("read: %m\n");
+-        goto err;
+-      }
+-      if (rdcount == 0)
+-      break;
+-      char *p = buf;
+-      char *end = buf + rdcount;
+-      while (p != end)
+-      {
+-        ssize_t wrcount = write (outfd, buf, end - p);
+-        if (wrcount == 0)
+-          errno = ENOSPC;
+-        if (wrcount <= 0)
+-          {
+-            printf ("write: %m\n");
+-            goto err;
+-          }
+-        p += wrcount;
+-      }
+-    }
+-  if (fchown (outfd, getuid (), target) < 0)
+-    {
+-      printf ("fchown (%s): %m\n", execname);
+-      goto err;
+-    }
+-  if (fchmod (outfd, 02750) < 0)
+-    {
+-      printf ("fchmod (%s): %m\n", execname);
+-      goto err;
+-    }
+-  if (close (outfd) < 0)
+-    {
+-      printf ("close (outfd): %m\n");
+-      goto err;
+-    }
+-  if (close (infd) < 0)
+-    {
+-      printf ("close (infd): %m\n");
+-      goto err;
+-    }
+-
+-  char *args[] = {execname, SETGID_CHILD, NULL};
+-
+-  ret = do_execve (args);
+-
+-err:
+-  if (outfd >= 0)
+-    close (outfd);
+-  if (infd >= 0)
+-    close (infd);
+-  if (execname)
+-    {
+-      unlink (execname);
+-      free (execname);
+-    }
+-  if (dirname)
+-    {
+-      rmdir (dirname);
+-      free (dirname);
+-    }
+-  return ret;
+-}
+ #ifndef test_child
+ static int
+@@ -256,40 +95,32 @@ do_test (int argc, char **argv)
+   if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
+     {
+       if (getgid () == getegid ())
+-      {
+-        /* This can happen if the file system is mounted nosuid.  */
+-        fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
+-                 (intmax_t) getgid ());
+-        exit (EXIT_UNSUPPORTED);
+-      }
++      /* This can happen if the file system is mounted nosuid.  */
++      FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
++                        (intmax_t) getgid ());
+       int ret = test_child ();
+       if (ret != 0)
+       exit (1);
+-      exit (CHILD_STATUS);
++      exit (EXIT_SUCCESS);
+     }
+   else
+     {
+       if (test_parent () != 0)
+       exit (1);
+-      /* Try running a setgid program.  */
+-      gid_t target = choose_gid ();
+-      if (target == 0)
+-      {
+-        fprintf (stderr,
+-                 "Could not find a suitable GID for user %jd, skipping test\n",
+-                 (intmax_t) getuid ());
+-        exit (0);
+-      }
++      int status = support_capture_subprogram_self_sgid (SETGID_CHILD);
+-      return run_executable_sgid (target);
+-    }
++      if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
++      return EXIT_UNSUPPORTED;
++
++      if (!WIFEXITED (status))
++      FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
+-  /* Something went wrong and our argv was corrupted.  */
+-  _exit (1);
++      return 0;
++    }
+ }
+ #define TEST_FUNCTION_ARGV do_test
 diff --git a/iconv/Versions b/iconv/Versions
 index 8a5f4cf780..d51af52fa3 100644
 --- a/iconv/Versions
 diff --git a/iconv/Versions b/iconv/Versions
 index 8a5f4cf780..d51af52fa3 100644
 --- a/iconv/Versions
@@ -1111,6 +1600,31 @@ index 88c69d1e9c..381aa721ef 100644
                      }
                    else if (status == NSS_STATUS_RETURN
                             || status == NSS_STATUS_NOTFOUND
                      }
                    else if (status == NSS_STATUS_RETURN
                             || status == NSS_STATUS_NOTFOUND
+diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
+index ed1b22308e..cb3f989cba 100644
+--- a/posix/wordexp-test.c
++++ b/posix/wordexp-test.c
+@@ -183,6 +183,7 @@ struct test_case_struct
+     { 0, NULL, "$var", 0, 0, { NULL, }, IFS },
+     { 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS },
+     { 0, NULL, "", 0, 0, { NULL, }, IFS },
++    { 0, NULL, "${1234567890123456789012}", 0, 0, { NULL, }, IFS },
+     /* Flags not already covered (testit() has special handling for these) */
+     { 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS },
+diff --git a/posix/wordexp.c b/posix/wordexp.c
+index e082d94895..56289503a1 100644
+--- a/posix/wordexp.c
++++ b/posix/wordexp.c
+@@ -1399,7 +1399,7 @@ envsubst:
+   /* Is it a numeric parameter? */
+   else if (isdigit (env[0]))
+     {
+-      int n = atoi (env);
++      unsigned long n = strtoul (env, NULL, 10);
+       if (n >= __libc_argc)
+       /* Substitute NULL. */
 diff --git a/resolv/Makefile b/resolv/Makefile
 index b61c0c3e0c..dbd8f8bf4f 100644
 --- a/resolv/Makefile
 diff --git a/resolv/Makefile b/resolv/Makefile
 index b61c0c3e0c..dbd8f8bf4f 100644
 --- a/resolv/Makefile
@@ -2389,6 +2903,236 @@ index 95b46dcbeb..3a323547f9 100644
                  ((char *)charbuf.scratch.data)[fc] = 1;
              }
            else
                  ((char *)charbuf.scratch.data)[fc] = 1;
              }
            else
+diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c
+index 3cfe9a05c3..d4b1139c5e 100644
+--- a/stdlib/tst-secure-getenv.c
++++ b/stdlib/tst-secure-getenv.c
+@@ -30,167 +30,12 @@
+ #include <sys/wait.h>
+ #include <unistd.h>
++#include <support/check.h>
+ #include <support/support.h>
++#include <support/capture_subprocess.h>
+ #include <support/test-driver.h>
+ static char MAGIC_ARGUMENT[] = "run-actual-test";
+-#define MAGIC_STATUS 19
+-
+-/* Return a GID which is not our current GID, but is present in the
+-   supplementary group list.  */
+-static gid_t
+-choose_gid (void)
+-{
+-  int count = getgroups (0, NULL);
+-  if (count < 0)
+-    {
+-      printf ("getgroups: %m\n");
+-      exit (1);
+-    }
+-  gid_t *groups;
+-  groups = xcalloc (count, sizeof (*groups));
+-  int ret = getgroups (count, groups);
+-  if (ret < 0)
+-    {
+-      printf ("getgroups: %m\n");
+-      exit (1);
+-    }
+-  gid_t current = getgid ();
+-  gid_t not_current = 0;
+-  for (int i = 0; i < ret; ++i)
+-    {
+-      if (groups[i] != current)
+-        {
+-          not_current = groups[i];
+-          break;
+-        }
+-    }
+-  free (groups);
+-  return not_current;
+-}
+-
+-
+-/* Copies the executable into a restricted directory, so that we can
+-   safely make it SGID with the TARGET group ID.  Then runs the
+-   executable.  */
+-static int
+-run_executable_sgid (gid_t target)
+-{
+-  char *dirname = xasprintf ("%s/secure-getenv.%jd",
+-                           test_dir, (intmax_t) getpid ());
+-  char *execname = xasprintf ("%s/bin", dirname);
+-  int infd = -1;
+-  int outfd = -1;
+-  int ret = -1;
+-  if (mkdir (dirname, 0700) < 0)
+-    {
+-      printf ("mkdir: %m\n");
+-      goto err;
+-    }
+-  infd = open ("/proc/self/exe", O_RDONLY);
+-  if (infd < 0)
+-    {
+-      printf ("open (/proc/self/exe): %m\n");
+-      goto err;
+-    }
+-  outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
+-  if (outfd < 0)
+-    {
+-      printf ("open (%s): %m\n", execname);
+-      goto err;
+-    }
+-  char buf[4096];
+-  for (;;)
+-    {
+-      ssize_t rdcount = read (infd, buf, sizeof (buf));
+-      if (rdcount < 0)
+-      {
+-        printf ("read: %m\n");
+-        goto err;
+-      }
+-      if (rdcount == 0)
+-      break;
+-      char *p = buf;
+-      char *end = buf + rdcount;
+-      while (p != end)
+-      {
+-        ssize_t wrcount = write (outfd, buf, end - p);
+-        if (wrcount == 0)
+-          errno = ENOSPC;
+-        if (wrcount <= 0)
+-          {
+-            printf ("write: %m\n");
+-            goto err;
+-          }
+-        p += wrcount;
+-      }
+-    }
+-  if (fchown (outfd, getuid (), target) < 0)
+-    {
+-      printf ("fchown (%s): %m\n", execname);
+-      goto err;
+-    }
+-  if (fchmod (outfd, 02750) < 0)
+-    {
+-      printf ("fchmod (%s): %m\n", execname);
+-      goto err;
+-    }
+-  if (close (outfd) < 0)
+-    {
+-      printf ("close (outfd): %m\n");
+-      goto err;
+-    }
+-  if (close (infd) < 0)
+-    {
+-      printf ("close (infd): %m\n");
+-      goto err;
+-    }
+-
+-  int kid = fork ();
+-  if (kid < 0)
+-    {
+-      printf ("fork: %m\n");
+-      goto err;
+-    }
+-  if (kid == 0)
+-    {
+-      /* Child process.  */
+-      char *args[] = { execname, MAGIC_ARGUMENT, NULL };
+-      execve (execname, args, environ);
+-      printf ("execve (%s): %m\n", execname);
+-      _exit (1);
+-    }
+-  int status;
+-  if (waitpid (kid, &status, 0) < 0)
+-    {
+-      printf ("waitpid: %m\n");
+-      goto err;
+-    }
+-  if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS)
+-    {
+-      printf ("Unexpected exit status %d from child process\n",
+-            status);
+-      goto err;
+-    }
+-  ret = 0;
+-
+-err:
+-  if (outfd >= 0)
+-    close (outfd);
+-  if (infd >= 0)
+-    close (infd);
+-  if (execname)
+-    {
+-      unlink (execname);
+-      free (execname);
+-    }
+-  if (dirname)
+-    {
+-      rmdir (dirname);
+-      free (dirname);
+-    }
+-  return ret;
+-}
+ static int
+ do_test (void)
+@@ -212,15 +57,15 @@ do_test (void)
+       exit (1);
+     }
+-  gid_t target = choose_gid ();
+-  if (target == 0)
+-    {
+-      fprintf (stderr,
+-             "Could not find a suitable GID for user %jd, skipping test\n",
+-             (intmax_t) getuid ());
+-      exit (0);
+-    }
+-  return run_executable_sgid (target);
++  int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT);
++
++  if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
++    return EXIT_UNSUPPORTED;
++
++  if (!WIFEXITED (status))
++    FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
++
++  return 0;
+ }
+ static void
+@@ -229,23 +74,15 @@ alternative_main (int argc, char **argv)
+   if (argc == 2 && strcmp (argv[1], MAGIC_ARGUMENT) == 0)
+     {
+       if (getgid () == getegid ())
+-      {
+-        /* This can happen if the file system is mounted nosuid.  */
+-        fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
+-                (intmax_t) getgid ());
+-        exit (MAGIC_STATUS);
+-      }
++      /* This can happen if the file system is mounted nosuid.  */
++      FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
++                 (intmax_t) getgid ());
+       if (getenv ("PATH") == NULL)
+-      {
+-        printf ("PATH variable not present\n");
+-        exit (3);
+-      }
++      FAIL_EXIT (3, "PATH variable not present\n");
+       if (secure_getenv ("PATH") != NULL)
+-      {
+-        printf ("PATH variable not filtered out\n");
+-        exit (4);
+-      }
+-      exit (MAGIC_STATUS);
++      FAIL_EXIT (4, "PATH variable not filtered out\n");
++
++      exit (EXIT_SUCCESS);
+     }
+ }
 diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
 index 309d0f39b2..c8d3051af8 100644
 --- a/string/bits/string_fortified.h
 diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
 index 309d0f39b2..c8d3051af8 100644
 --- a/string/bits/string_fortified.h
@@ -2435,6 +3179,23 @@ index 93faafddf9..4154863511 100644
    resolv_test \
    set_fortify_handler \
    support-xfstat \
    resolv_test \
    set_fortify_handler \
    support-xfstat \
+diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
+index 9808750f80..421f657678 100644
+--- a/support/capture_subprocess.h
++++ b/support/capture_subprocess.h
+@@ -41,6 +41,12 @@ struct support_capture_subprocess support_capture_subprocess
+ struct support_capture_subprocess support_capture_subprogram
+   (const char *file, char *const argv[]);
++/* Copy the running program into a setgid binary and run it with CHILD_ID
++   argument.  If execution is successful, return the exit status of the child
++   program, otherwise return a non-zero failure exit code.  */
++int support_capture_subprogram_self_sgid
++  (char *child_id);
++
+ /* Deallocate the subprocess data captured by
+    support_capture_subprocess.  */
+ void support_capture_subprocess_free (struct support_capture_subprocess *);
 diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c
 new file mode 100644
 index 0000000000..f9c5c3462a
 diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c
 new file mode 100644
 index 0000000000..f9c5c3462a
@@ -2731,6 +3492,240 @@ index 67819469a0..31a5c1c3e7 100644
  __END_DECLS
  
  #endif /* SUPPORT_RESOLV_TEST_H */
  __END_DECLS
  
  #endif /* SUPPORT_RESOLV_TEST_H */
+diff --git a/support/subprocess.h b/support/subprocess.h
+index 8b442fd5c0..34ffd02e8e 100644
+--- a/support/subprocess.h
++++ b/support/subprocess.h
+@@ -38,6 +38,11 @@ struct support_subprocess support_subprocess
+ struct support_subprocess support_subprogram
+   (const char *file, char *const argv[]);
++/* Invoke program FILE with ARGV arguments by using posix_spawn and wait for it
++   to complete.  Return program exit status.  */
++int support_subprogram_wait
++  (const char *file, char *const argv[]);
++
+ /* Wait for the subprocess indicated by PROC::PID.  Return the status
+    indicate by waitpid call.  */
+ int support_process_wait (struct support_subprocess *proc);
+diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
+index eeed676e3d..28a37df67f 100644
+--- a/support/support_capture_subprocess.c
++++ b/support/support_capture_subprocess.c
+@@ -20,11 +20,14 @@
+ #include <support/capture_subprocess.h>
+ #include <errno.h>
++#include <fcntl.h>
+ #include <stdlib.h>
+ #include <support/check.h>
+ #include <support/xunistd.h>
+ #include <support/xsocket.h>
+ #include <support/xspawn.h>
++#include <support/support.h>
++#include <support/test-driver.h>
+ static void
+ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
+@@ -36,7 +39,7 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
+       if (ret < 0)
+         {
+           support_record_failure ();
+-          printf ("error: reading from subprocess %s: %m", what);
++          printf ("error: reading from subprocess %s: %m\n", what);
+           pfd->events = 0;
+           pfd->revents = 0;
+         }
+@@ -102,6 +105,129 @@ support_capture_subprogram (const char *file, char *const argv[])
+   return result;
+ }
++/* Copies the executable into a restricted directory, so that we can
++   safely make it SGID with the TARGET group ID.  Then runs the
++   executable.  */
++static int
++copy_and_spawn_sgid (char *child_id, gid_t gid)
++{
++  char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd",
++                           test_dir, (intmax_t) getpid ());
++  char *execname = xasprintf ("%s/bin", dirname);
++  int infd = -1;
++  int outfd = -1;
++  int ret = 1, status = 1;
++
++  TEST_VERIFY (mkdir (dirname, 0700) == 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++
++  infd = open ("/proc/self/exe", O_RDONLY);
++  if (infd < 0)
++    FAIL_UNSUPPORTED ("unsupported: Cannot read binary from procfs\n");
++
++  outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
++  TEST_VERIFY (outfd >= 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++
++  char buf[4096];
++  for (;;)
++    {
++      ssize_t rdcount = read (infd, buf, sizeof (buf));
++      TEST_VERIFY (rdcount >= 0);
++      if (support_record_failure_is_failed ())
++      goto err;
++      if (rdcount == 0)
++      break;
++      char *p = buf;
++      char *end = buf + rdcount;
++      while (p != end)
++      {
++        ssize_t wrcount = write (outfd, buf, end - p);
++        if (wrcount == 0)
++          errno = ENOSPC;
++        TEST_VERIFY (wrcount > 0);
++        if (support_record_failure_is_failed ())
++          goto err;
++        p += wrcount;
++      }
++    }
++  TEST_VERIFY (fchown (outfd, getuid (), gid) == 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++  TEST_VERIFY (fchmod (outfd, 02750) == 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++  TEST_VERIFY (close (outfd) == 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++  TEST_VERIFY (close (infd) == 0);
++  if (support_record_failure_is_failed ())
++    goto err;
++
++  /* We have the binary, now spawn the subprocess.  Avoid using
++     support_subprogram because we only want the program exit status, not the
++     contents.  */
++  ret = 0;
++
++  char * const args[] = {execname, child_id, NULL};
++
++  status = support_subprogram_wait (args[0], args);
++
++err:
++  if (outfd >= 0)
++    close (outfd);
++  if (infd >= 0)
++    close (infd);
++  if (execname != NULL)
++    {
++      unlink (execname);
++      free (execname);
++    }
++  if (dirname != NULL)
++    {
++      rmdir (dirname);
++      free (dirname);
++    }
++
++  if (ret != 0)
++    FAIL_EXIT1("Failed to make sgid executable for test\n");
++
++  return status;
++}
++
++int
++support_capture_subprogram_self_sgid (char *child_id)
++{
++  gid_t target = 0;
++  const int count = 64;
++  gid_t groups[count];
++
++  /* Get a GID which is not our current GID, but is present in the
++     supplementary group list.  */
++  int ret = getgroups (count, groups);
++  if (ret < 0)
++    FAIL_UNSUPPORTED("Could not get group list for user %jd\n",
++                   (intmax_t) getuid ());
++
++  gid_t current = getgid ();
++  for (int i = 0; i < ret; ++i)
++    {
++      if (groups[i] != current)
++      {
++        target = groups[i];
++        break;
++      }
++    }
++
++  if (target == 0)
++    FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n",
++                   (intmax_t) getuid ());
++
++  return copy_and_spawn_sgid (child_id, target);
++}
++
+ void
+ support_capture_subprocess_free (struct support_capture_subprocess *p)
+ {
+diff --git a/support/support_subprocess.c b/support/support_subprocess.c
+index 36e3a77af2..4a25828111 100644
+--- a/support/support_subprocess.c
++++ b/support/support_subprocess.c
+@@ -27,7 +27,7 @@
+ #include <support/subprocess.h>
+ static struct support_subprocess
+-support_suprocess_init (void)
++support_subprocess_init (void)
+ {
+   struct support_subprocess result;
+@@ -48,7 +48,7 @@ support_suprocess_init (void)
+ struct support_subprocess
+ support_subprocess (void (*callback) (void *), void *closure)
+ {
+-  struct support_subprocess result = support_suprocess_init ();
++  struct support_subprocess result = support_subprocess_init ();
+   result.pid = xfork ();
+   if (result.pid == 0)
+@@ -71,7 +71,7 @@ support_subprocess (void (*callback) (void *), void *closure)
+ struct support_subprocess
+ support_subprogram (const char *file, char *const argv[])
+ {
+-  struct support_subprocess result = support_suprocess_init ();
++  struct support_subprocess result = support_subprocess_init ();
+   posix_spawn_file_actions_t fa;
+   /* posix_spawn_file_actions_init does not fail.  */
+@@ -84,7 +84,7 @@ support_subprogram (const char *file, char *const argv[])
+   xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]);
+   xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]);
+-  result.pid = xposix_spawn (file, &fa, NULL, argv, NULL);
++  result.pid = xposix_spawn (file, &fa, NULL, argv, environ);
+   xclose (result.stdout_pipe[1]);
+   xclose (result.stderr_pipe[1]);
+@@ -92,6 +92,19 @@ support_subprogram (const char *file, char *const argv[])
+   return result;
+ }
++int
++support_subprogram_wait (const char *file, char *const argv[])
++{
++  posix_spawn_file_actions_t fa;
++
++  posix_spawn_file_actions_init (&fa);
++  struct support_subprocess res = support_subprocess_init ();
++
++  res.pid = xposix_spawn (file, &fa, NULL, argv, environ);
++
++  return support_process_wait (&res);
++}
++
+ int
+ support_process_wait (struct support_subprocess *proc)
+ {
 diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c
 index 196e462520..cf7624aaa2 100644
 --- a/sysdeps/aarch64/dl-bti.c
 diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c
 index 196e462520..cf7624aaa2 100644
 --- a/sysdeps/aarch64/dl-bti.c
@@ -4017,6 +5012,85 @@ index 8a53a1088f..362a2b713c 100644
      return true;
  #endif
    return false;
      return true;
  #endif
    return false;
+diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure
+index fa46e9e351..e7f576338d 100644
+--- a/sysdeps/s390/configure
++++ b/sysdeps/s390/configure
+@@ -123,7 +123,9 @@ void testinsn (char *buf)
+     __asm__ (".machine \"arch13\" \n\t"
+            ".machinemode \"zarch_nohighgprs\" \n\t"
+            "lghi %%r0,16 \n\t"
+-           "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
++           "mvcrl 0(%0),32(%0) \n\t"
++           "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
++           : : "a" (buf) : "memory", "r0");
+ }
+ EOF
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
+@@ -271,7 +273,9 @@ else
+ void testinsn (char *buf)
+ {
+     __asm__ ("lghi %%r0,16 \n\t"
+-           "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
++           "mvcrl 0(%0),32(%0) \n\t"
++           "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
++           : : "a" (buf) : "memory", "r0");
+ }
+ EOF
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
+diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac
+index 3ed5a8ef87..5c3479e8cf 100644
+--- a/sysdeps/s390/configure.ac
++++ b/sysdeps/s390/configure.ac
+@@ -88,7 +88,9 @@ void testinsn (char *buf)
+     __asm__ (".machine \"arch13\" \n\t"
+            ".machinemode \"zarch_nohighgprs\" \n\t"
+            "lghi %%r0,16 \n\t"
+-           "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
++           "mvcrl 0(%0),32(%0) \n\t"
++           "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
++           : : "a" (buf) : "memory", "r0");
+ }
+ EOF
+ dnl test, if assembler supports S390 arch13 instructions
+@@ -195,7 +197,9 @@ cat > conftest.c <<\EOF
+ void testinsn (char *buf)
+ {
+     __asm__ ("lghi %%r0,16 \n\t"
+-           "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
++           "mvcrl 0(%0),32(%0) \n\t"
++           "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
++           : : "a" (buf) : "memory", "r0");
+ }
+ EOF
+ dnl test, if assembler supports S390 arch13 zarch instructions as default
+diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c
+index 5fc85e129f..ee59b5de14 100644
+--- a/sysdeps/s390/memmove.c
++++ b/sysdeps/s390/memmove.c
+@@ -43,7 +43,7 @@ extern __typeof (__redirect_memmove) MEMMOVE_ARCH13 attribute_hidden;
+ s390_libc_ifunc_expr (__redirect_memmove, memmove,
+                     ({
+                       s390_libc_ifunc_expr_stfle_init ();
+-                      (HAVE_MEMMOVE_ARCH13
++                      (HAVE_MEMMOVE_ARCH13 && (hwcap & HWCAP_S390_VXRS_EXT2)
+                        && S390_IS_ARCH13_MIE3 (stfle_bits))
+                         ? MEMMOVE_ARCH13
+                         : (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX))
+diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
+index e6195c6e26..17c0cc3952 100644
+--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
+@@ -171,7 +171,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+     IFUNC_IMPL (i, name, memmove,
+ # if HAVE_MEMMOVE_ARCH13
+               IFUNC_IMPL_ADD (array, i, memmove,
+-                              S390_IS_ARCH13_MIE3 (stfle_bits),
++                              ((dl_hwcap & HWCAP_S390_VXRS_EXT2)
++                               && S390_IS_ARCH13_MIE3 (stfle_bits)),
+                               MEMMOVE_ARCH13)
+ # endif
+ # if HAVE_MEMMOVE_Z13
 diff --git a/sysdeps/sh/be/sh4/fpu/Implies b/sysdeps/sh/be/sh4/fpu/Implies
 new file mode 100644
 index 0000000000..71b28ee1a4
 diff --git a/sysdeps/sh/be/sh4/fpu/Implies b/sysdeps/sh/be/sh4/fpu/Implies
 new file mode 100644
 index 0000000000..71b28ee1a4
@@ -4059,6 +5133,55 @@ index fc688450ee..00a4d0c8e7 100644
  
  #define IS_EMAG(midr) (MIDR_IMPLEMENTOR(midr) == 'P'                        \
                         && MIDR_PARTNUM(midr) == 0x000)
  
  #define IS_EMAG(midr) (MIDR_IMPLEMENTOR(midr) == 'P'                        \
                         && MIDR_PARTNUM(midr) == 0x000)
+diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c
+index 61bbb03b64..b5a903c3a2 100644
+--- a/sysdeps/unix/sysv/linux/mq_notify.c
++++ b/sysdeps/unix/sysv/linux/mq_notify.c
+@@ -133,8 +133,11 @@ helper_thread (void *arg)
+           (void) __pthread_barrier_wait (&notify_barrier);
+       }
+       else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
+-      /* The only state we keep is the copy of the thread attributes.  */
+-      free (data.attr);
++      {
++        /* The only state we keep is the copy of the thread attributes.  */
++        pthread_attr_destroy (data.attr);
++        free (data.attr);
++      }
+     }
+   return NULL;
+ }
+@@ -255,8 +258,14 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification)
+       if (data.attr == NULL)
+       return -1;
+-      memcpy (data.attr, notification->sigev_notify_attributes,
+-            sizeof (pthread_attr_t));
++      int ret = __pthread_attr_copy (data.attr,
++                                   notification->sigev_notify_attributes);
++      if (ret != 0)
++      {
++        free (data.attr);
++        __set_errno (ret);
++        return -1;
++      }
+     }
+   /* Construct the new request.  */
+@@ -269,8 +278,11 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification)
+   int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
+   /* If it failed, free the allocated memory.  */
+-  if (__glibc_unlikely (retval != 0))
+-    free (data.attr);
++  if (retval != 0 && data.attr != NULL)
++    {
++      pthread_attr_destroy (data.attr);
++      free (data.attr);
++    }
+   return retval;
+ }
 diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
 index 0776472d5e..a1f24ab242 100644
 --- a/sysdeps/unix/sysv/linux/msgctl.c
 diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
 index 0776472d5e..a1f24ab242 100644
 --- a/sysdeps/unix/sysv/linux/msgctl.c
@@ -4912,6 +6035,88 @@ index 0000000000..42c795d2a8
 +++ b/sysdeps/x86/tst-setjmp-cet.c
 @@ -0,0 +1 @@
 +#include <setjmp/tst-setjmp.c>
 +++ b/sysdeps/x86/tst-setjmp-cet.c
 @@ -0,0 +1 @@
 +#include <setjmp/tst-setjmp.c>
+diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure
+old mode 100644
+new mode 100755
+index 84f82c2406..fc1840e23f
+--- a/sysdeps/x86_64/configure
++++ b/sysdeps/x86_64/configure
+@@ -107,39 +107,6 @@ if test x"$build_mathvec" = xnotset; then
+   build_mathvec=yes
+ fi
+-if test "$static_pie" = yes; then
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5
+-$as_echo_n "checking for linker static PIE support... " >&6; }
+-if ${libc_cv_ld_static_pie+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  cat > conftest.s <<\EOF
+-      .text
+-      .global _start
+-      .weak foo
+-_start:
+-      leaq    foo(%rip), %rax
+-EOF
+-  libc_cv_pie_option="-Wl,-pie"
+-  if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5'
+-  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+-  (eval $ac_try) 2>&5
+-  ac_status=$?
+-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }; }; then
+-    libc_cv_ld_static_pie=yes
+-  else
+-    libc_cv_ld_static_pie=no
+-  fi
+-rm -f conftest*
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5
+-$as_echo "$libc_cv_ld_static_pie" >&6; }
+-  if test "$libc_cv_ld_static_pie" != yes; then
+-    as_fn_error $? "linker support for static PIE needed" "$LINENO" 5
+-  fi
+-fi
+-
+ $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
+diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac
+index cdaba0c075..611a7d9ba3 100644
+--- a/sysdeps/x86_64/configure.ac
++++ b/sysdeps/x86_64/configure.ac
+@@ -53,31 +53,6 @@ if test x"$build_mathvec" = xnotset; then
+   build_mathvec=yes
+ fi
+-dnl Check if linker supports static PIE with the fix for
+-dnl
+-dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782
+-dnl
+-if test "$static_pie" = yes; then
+-  AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl
+-cat > conftest.s <<\EOF
+-      .text
+-      .global _start
+-      .weak foo
+-_start:
+-      leaq    foo(%rip), %rax
+-EOF
+-  libc_cv_pie_option="-Wl,-pie"
+-  if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then
+-    libc_cv_ld_static_pie=yes
+-  else
+-    libc_cv_ld_static_pie=no
+-  fi
+-rm -f conftest*])
+-  if test "$libc_cv_ld_static_pie" != yes; then
+-    AC_MSG_ERROR([linker support for static PIE needed])
+-  fi
+-fi
+-
+ dnl It is always possible to access static and hidden symbols in an
+ dnl position independent way.
+ AC_DEFINE(PI_STATIC_AND_HIDDEN)
 diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
 index ca73d8fef9..363a749cb2 100644
 --- a/sysdeps/x86_64/dl-machine.h
 diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
 index ca73d8fef9..363a749cb2 100644
 --- a/sysdeps/x86_64/dl-machine.h