[glibc] 01/02: debian/patches/git-updates.diff: update from upstream stable branch.
This is an automated email from the git hooks/post-receive script.
aurel32 pushed a commit to branch glibc-2.26
in repository glibc.
commit d52a330c4cea79690233af54f8f65929abbc3ae5
Author: Aurelien Jarno <aurelien@aurel32.net>
Date: Sun Dec 31 19:11:21 2017 +0100
debian/patches/git-updates.diff: update from upstream stable branch.
---
debian/changelog | 1 +
debian/patches/git-updates.diff | 3281 +++++++++++++++++++++++++++++++++------
2 files changed, 2848 insertions(+), 434 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 3158f20..1c30857 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,7 @@ glibc (2.26-0experimental3) UNRELEASED; urgency=medium
* debian/sysdeps/hppa.mk: set TIMEOUTFACTOR to 100 on HPPA.
* debian/testsuite-xfail-debian.mk: remove tst-create-detached from XFAIL
on HPPA.
+ * debian/patches/git-updates.diff: update from upstream stable branch.
-- Aurelien Jarno <aurel32@debian.org> Sun, 17 Dec 2017 20:13:55 +0100
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff
index e112efc..753fa61 100644
--- a/debian/patches/git-updates.diff
+++ b/debian/patches/git-updates.diff
@@ -1,10 +1,70 @@
-GIT update of git://sourceware.org/git/glibc.git/release/2.26/master from glibc-2.26
+GIT update of https://sourceware.org/git/glibc.git/release/2.26/master from glibc-2.26
diff --git a/ChangeLog b/ChangeLog
-index 8dbfc7eaff..55a17414ab 100644
+index 8dbfc7eaff..414e931aa5 100644
--- a/ChangeLog
+++ b/ChangeLog
-@@ -1,3 +1,1057 @@
+@@ -1,3 +1,1117 @@
++2017-12-30 Aurelien Jarno <aurelien@aurel32.net>
++ Dmitry V. Levin <ldv@altlinux.org>
++
++ [BZ #22625]
++ * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic
++ string token expansion. Check for NULL pointer or empty string possibly
++ returned by expand_dynamic_string_token.
++ (decompose_rpath): Check for empty path after dynamic string
++ token expansion.
++
++2017-12-18 Dmitry V. Levin <ldv@altlinux.org>
++
++ [BZ #22627]
++ * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory
++ code and invocation.
++
++2017-11-18 Florian Weimer <fweimer@redhat.com>
++
++ * sysdeps/unix/sysv/linux/tst-ttyname.c
++ (become_root_in_mount_ns): Remove.
++ (do_in_chroot_1): Call support_enter_mount_namespace.
++ (do_in_chroot_2): Likewise.
++ (do_test): Call support_become_root early.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ [BZ #22145]
++ * sysdeps/unix/sysv/linux/tst-ttyname.c: New file.
++ * sysdeps/unix/sysv/linux/Makefile: Add tst-ttyname to tests.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ [BZ #22145]
++ * sysdeps/unix/sysv/linux/ttyname.c (ttyname):
++ Defer is_pty check until end of the function.
++ * sysdeps/unix/sysv/linux/ttyname_r.c (__ttyname_r): Likewise.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ [BZ #22145]
++ * sysdeps/unix/sysv/linux/ttyname.h (is_mytty): New function.
++ * sysdeps/unix/sysv/linux/ttyname.c (getttyname): Call is_mytty.
++ (ttyname): Likewise.
++ * sysdeps/unix/sysv/linux/ttyname_r.c (getttyname_r): Likewise.
++ (__ttyname_r): Likewise.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Change return type from
++ int to bool.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Update doc reference.
++
++2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
++
++ * manual/terminal.texi (Is It a Terminal):
++ Mention ENODEV for ttyname and ttyname_r.
++
+2017-12-14 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22607]
@@ -1086,10 +1146,10 @@ index 9bb707c168..828a445f24 100644
# Don't try to use -lc when making libc.so itself.
# Also omits crti.o and crtn.o, which we do not want
diff --git a/NEWS b/NEWS
-index 8295f20c0a..2c49212cb5 100644
+index 8295f20c0a..f04b3ed4e8 100644
--- a/NEWS
+++ b/NEWS
-@@ -5,6 +5,92 @@ See the end for copying conditions.
+@@ -5,6 +5,98 @@ See the end for copying conditions.
Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
@@ -1143,6 +1203,10 @@ index 8295f20c0a..2c49212cb5 100644
+ CVE-2017-1000366 has been applied, but it is mentioned here only because
+ of the CVE assignment.) Reported by Qualys.
+
++ CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN
++ for AT_SECURE or SUID binaries could be used to load libraries from the
++ current directory.
++
+The following bugs are resolved with this release:
+
+ [16750] ldd: Never run file directly.
@@ -1168,6 +1232,7 @@ index 8295f20c0a..2c49212cb5 100644
+ [22095] resolv: Fix memory leak with OOM during resolv.conf parsing
+ [22096] resolv: __resolv_conf_attach must not free passed conf object
+ [22111] malloc: per thread cache is not returned when thread exits
++ [22145] ttyname gives up too early in the face of namespaces
+ [22146] Let fpclassify use the builtin when optimizing for size in C++ mode
+ [22225] math: nearbyint arithmetic moved before feholdexcept
+ [22235] Add C++ versions of iscanonical for ldbl-96 and ldbl-128ibm
@@ -1178,6 +1243,7 @@ index 8295f20c0a..2c49212cb5 100644
+ [22322] libc: [mips64] wrong bits/long-double.h installed
+ [22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671)
+ [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426)
++ [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice
+
Version 2.26
@@ -1414,7 +1480,7 @@ index 0280fba8a7..8bbbf2a121 100644
else
libcrypt-routines += md5 sha256 sha512
diff --git a/elf/dl-load.c b/elf/dl-load.c
-index c1b6d4ba0f..621403c05f 100644
+index c1b6d4ba0f..7397c1882c 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -37,6 +37,7 @@
@@ -1447,7 +1513,79 @@ index c1b6d4ba0f..621403c05f 100644
static bool
is_trusted_path (const char *path, size_t len)
-@@ -688,9 +689,8 @@ _dl_init_paths (const char *llp)
+@@ -433,31 +434,40 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
+ {
+ char *cp;
+ size_t nelems = 0;
+- char *to_free;
+
+ while ((cp = __strsep (&rpath, sep)) != NULL)
+ {
+ struct r_search_path_elem *dirp;
++ char *to_free = NULL;
++ size_t len = 0;
+
+- to_free = cp = expand_dynamic_string_token (l, cp, 1);
++ /* `strsep' can pass an empty string. */
++ if (*cp != '\0')
++ {
++ to_free = cp = expand_dynamic_string_token (l, cp, 1);
+
+- size_t len = strlen (cp);
++ /* expand_dynamic_string_token can return NULL in case of empty
++ path or memory allocation failure. */
++ if (cp == NULL)
++ continue;
+
+- /* `strsep' can pass an empty string. This has to be
+- interpreted as `use the current directory'. */
+- if (len == 0)
+- {
+- static const char curwd[] = "./";
+- cp = (char *) curwd;
+- }
++ /* Compute the length after dynamic string token expansion and
++ ignore empty paths. */
++ len = strlen (cp);
++ if (len == 0)
++ {
++ free (to_free);
++ continue;
++ }
+
+- /* Remove trailing slashes (except for "/"). */
+- while (len > 1 && cp[len - 1] == '/')
+- --len;
++ /* Remove trailing slashes (except for "/"). */
++ while (len > 1 && cp[len - 1] == '/')
++ --len;
+
+- /* Now add one if there is none so far. */
+- if (len > 0 && cp[len - 1] != '/')
+- cp[len++] = '/';
++ /* Now add one if there is none so far. */
++ if (len > 0 && cp[len - 1] != '/')
++ cp[len++] = '/';
++ }
+
+ /* Make sure we don't use untrusted directories if we run SUID. */
+ if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
+@@ -621,6 +631,14 @@ decompose_rpath (struct r_search_path_struct *sps,
+ necessary. */
+ free (copy);
+
++ /* There is no path after expansion. */
++ if (result[0] == NULL)
++ {
++ free (result);
++ sps->dirs = (struct r_search_path_elem **) -1;
++ return false;
++ }
++
+ sps->dirs = result;
+ /* The caller will change this value if we haven't used a real malloc. */
+ sps->malloced = 1;
+@@ -688,9 +706,8 @@ _dl_init_paths (const char *llp)
+ ncapstr * sizeof (enum r_dir_status))
/ sizeof (struct r_search_path_elem));
@@ -1459,16 +1597,32 @@ index c1b6d4ba0f..621403c05f 100644
if (rtld_search_dirs.dirs[0] == NULL)
{
errstring = N_("cannot create cache for search path");
-@@ -776,8 +776,6 @@ _dl_init_paths (const char *llp)
+@@ -776,37 +793,14 @@ _dl_init_paths (const char *llp)
if (llp != NULL && *llp != '\0')
{
- size_t nllp;
- const char *cp = llp;
- char *llp_tmp;
-
- #ifdef SHARED
-@@ -800,13 +798,10 @@ _dl_init_paths (const char *llp)
+- char *llp_tmp;
+-
+-#ifdef SHARED
+- /* Expand DSTs. */
+- size_t cnt = DL_DST_COUNT (llp, 1);
+- if (__glibc_likely (cnt == 0))
+- llp_tmp = strdupa (llp);
+- else
+- {
+- /* Determine the length of the substituted string. */
+- size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
+-
+- /* Allocate the necessary memory. */
+- llp_tmp = (char *) alloca (total + 1);
+- llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
+- }
+-#else
+- llp_tmp = strdupa (llp);
+-#endif
++ char *llp_tmp = strdupa (llp);
/* Decompose the LD_LIBRARY_PATH contents. First determine how many
elements it has. */
@@ -10985,11 +11139,237 @@ index e28b0c5058..4320336c9a 100644
#endif
}
+diff --git a/support/Makefile b/support/Makefile
+index 2ace3fa8cc..8458840cd8 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -32,15 +32,18 @@ libsupport-routines = \
+ check_netent \
+ delayed_exit \
+ ignore_stderr \
++ next_to_fault \
+ oom_error \
+ resolv_test \
+ set_fortify_handler \
++ support-xfstat \
+ support-xstat \
+ support_become_root \
+ support_can_chroot \
+ support_capture_subprocess \
+ support_capture_subprocess_check \
+ support_chroot \
++ support_enter_mount_namespace \
+ support_enter_network_namespace \
+ support_format_address_family \
+ support_format_addrinfo \
+@@ -52,6 +55,7 @@ libsupport-routines = \
+ support_record_failure \
+ support_run_diff \
+ support_shared_allocate \
++ support_test_compare_failure \
+ support_write_file_string \
+ support_test_main \
+ support_test_verify_impl \
+@@ -65,12 +69,15 @@ libsupport-routines = \
+ xchroot \
+ xclose \
+ xconnect \
++ xdlfcn \
+ xdup2 \
+ xfclose \
+ xfopen \
+ xfork \
++ xftruncate \
+ xgetsockname \
+ xlisten \
++ xlseek \
+ xmalloc \
+ xmemstream \
+ xmkdir \
+@@ -83,8 +90,8 @@ libsupport-routines = \
+ xpthread_attr_destroy \
+ xpthread_attr_init \
+ xpthread_attr_setdetachstate \
+- xpthread_attr_setstacksize \
+ xpthread_attr_setguardsize \
++ xpthread_attr_setstacksize \
+ xpthread_barrier_destroy \
+ xpthread_barrier_init \
+ xpthread_barrier_wait \
+@@ -108,19 +115,26 @@ libsupport-routines = \
+ xpthread_once \
+ xpthread_rwlock_init \
+ xpthread_rwlock_rdlock \
+- xpthread_rwlock_wrlock \
+ xpthread_rwlock_unlock \
++ xpthread_rwlock_wrlock \
+ xpthread_rwlockattr_init \
+ xpthread_rwlockattr_setkind_np \
+ xpthread_sigmask \
+ xpthread_spin_lock \
+ xpthread_spin_unlock \
++ xraise \
++ xreadlink \
+ xrealloc \
+ xrecvfrom \
+ xsendto \
+ xsetsockopt \
++ xsigaction \
++ xsignal \
+ xsocket \
+ xstrdup \
++ xstrndup \
++ xsysconf \
++ xunlink \
+ xwaitpid \
+ xwrite \
+
+@@ -137,6 +151,8 @@ tests = \
+ tst-support_capture_subprocess \
+ tst-support_format_dns_packet \
+ tst-support_record_failure \
++ tst-test_compare \
++ tst-xreadlink \
+
+ ifeq ($(run-built-tests),yes)
+ tests-special = \
+diff --git a/support/check.h b/support/check.h
+index bdcd12952a..55a6f09f42 100644
+--- a/support/check.h
++++ b/support/check.h
+@@ -86,6 +86,67 @@ void support_test_verify_exit_impl (int status, const char *file, int line,
+ does not support reporting failures from a DSO. */
+ void support_record_failure (void);
+
++/* Compare the two integers LEFT and RIGHT and report failure if they
++ are different. */
++#define TEST_COMPARE(left, right) \
++ ({ \
++ /* + applies the integer promotions, for bitfield support. */ \
++ typedef __typeof__ (+ (left)) __left_type; \
++ typedef __typeof__ (+ (right)) __right_type; \
++ __left_type __left_value = (left); \
++ __right_type __right_value = (right); \
++ /* Prevent use with floating-point and boolean types. */ \
++ _Static_assert ((__left_type) 1.0 == (__left_type) 1.5, \
++ "left value has floating-point type"); \
++ _Static_assert ((__right_type) 1.0 == (__right_type) 1.5, \
++ "right value has floating-point type"); \
++ /* Prevent accidental use with larger-than-long long types. */ \
++ _Static_assert (sizeof (__left_value) <= sizeof (long long), \
++ "left value fits into long long"); \
++ _Static_assert (sizeof (__right_value) <= sizeof (long long), \
++ "right value fits into long long"); \
++ /* Make sure that integer conversions does not alter the sign. */ \
++ enum \
++ { \
++ __left_is_unsigned = (__left_type) -1 > 0, \
++ __right_is_unsigned = (__right_type) -1 > 0, \
++ __unsigned_left_converts_to_wider = (__left_is_unsigned \
++ && (sizeof (__left_value) \
++ < sizeof (__right_value))), \
++ __unsigned_right_converts_to_wider = (__right_is_unsigned \
++ && (sizeof (__right_value) \
++ < sizeof (__left_value))) \
++ }; \
++ _Static_assert (__left_is_unsigned == __right_is_unsigned \
++ || __unsigned_left_converts_to_wider \
++ || __unsigned_right_converts_to_wider, \
++ "integer conversions may alter sign of operands"); \
++ /* Compare the value. */ \
++ if (__left_value != __right_value) \
++ /* Pass the sign for printing the correct value. */ \
++ support_test_compare_failure \
++ (__FILE__, __LINE__, \
++ #left, __left_value, __left_value < 0, sizeof (__left_type), \
++ #right, __right_value, __right_value < 0, sizeof (__right_type)); \
++ })
++
++/* Internal implementation of TEST_COMPARE. LEFT_NEGATIVE and
++ RIGHT_NEGATIVE are used to store the sign separately, so that both
++ unsigned long long and long long arguments fit into LEFT_VALUE and
++ RIGHT_VALUE, and the function can still print the original value.
++ LEFT_SIZE and RIGHT_SIZE specify the size of the argument in bytes,
++ for hexadecimal formatting. */
++void support_test_compare_failure (const char *file, int line,
++ const char *left_expr,
++ long long left_value,
++ int left_negative,
++ int left_size,
++ const char *right_expr,
++ long long right_value,
++ int right_negative,
++ int right_size);
++
++
+ /* Internal function called by the test driver. */
+ int support_report_failure (int status)
+ __attribute__ ((weak, warn_unused_result));
+diff --git a/support/check_addrinfo.c b/support/check_addrinfo.c
+index 55895ace3c..c47f105ce6 100644
+--- a/support/check_addrinfo.c
++++ b/support/check_addrinfo.c
+@@ -20,6 +20,7 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <support/check.h>
+ #include <support/format_nss.h>
+ #include <support/run_diff.h>
+diff --git a/support/check_dns_packet.c b/support/check_dns_packet.c
+index d2a31bed7b..6d14bd90c0 100644
+--- a/support/check_dns_packet.c
++++ b/support/check_dns_packet.c
+@@ -20,6 +20,7 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <support/check.h>
+ #include <support/format_nss.h>
+ #include <support/run_diff.h>
+diff --git a/support/check_hostent.c b/support/check_hostent.c
+index 890d672d50..47fb8bc332 100644
+--- a/support/check_hostent.c
++++ b/support/check_hostent.c
+@@ -20,6 +20,7 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <support/check.h>
+ #include <support/format_nss.h>
+ #include <support/run_diff.h>
+diff --git a/support/check_netent.c b/support/check_netent.c
+index daa3083fd1..80b69309b4 100644
+--- a/support/check_netent.c
++++ b/support/check_netent.c
+@@ -20,6 +20,7 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <support/check.h>
+ #include <support/format_nss.h>
+ #include <support/run_diff.h>
diff --git a/support/namespace.h b/support/namespace.h
-index 859c2fda3f..9eddb1a0e9 100644
+index 859c2fda3f..b5e2d1474a 100644
--- a/support/namespace.h
+++ b/support/namespace.h
-@@ -66,7 +66,9 @@ struct support_chroot_configuration
+@@ -51,6 +51,11 @@ bool support_can_chroot (void);
+ has sufficient privileges. */
+ bool support_enter_network_namespace (void);
+
++/* Enter a mount namespace and mark / as private (not shared). If
++ this function returns true, mount operations in this process will
++ not affect the host system afterwards. */
++bool support_enter_mount_namespace (void);
++
+ /* Return true if support_enter_network_namespace managed to enter a
+ UTS namespace. */
+ bool support_in_uts_namespace (void);
+@@ -66,7 +71,9 @@ struct support_chroot_configuration
{
/* File contents. The files are not created if the field is
NULL. */
@@ -11000,7 +11380,7 @@ index 859c2fda3f..9eddb1a0e9 100644
};
/* The result of the creation of a chroot. */
-@@ -78,8 +80,11 @@ struct support_chroot
+@@ -78,8 +85,11 @@ struct support_chroot
/* Path to the chroot directory. */
char *path_chroot;
@@ -11014,11 +11394,272 @@ index 859c2fda3f..9eddb1a0e9 100644
};
/* Create a chroot environment. The returned data should be freed
+diff --git a/support/next_to_fault.c b/support/next_to_fault.c
+new file mode 100644
+index 0000000000..7c6b077898
+--- /dev/null
++++ b/support/next_to_fault.c
+@@ -0,0 +1,52 @@
++/* Memory allocation next to an unmapped page.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/next_to_fault.h>
++#include <support/xunistd.h>
++#include <sys/mman.h>
++#include <sys/param.h>
++
++struct support_next_to_fault
++support_next_to_fault_allocate (size_t size)
++{
++ long page_size = sysconf (_SC_PAGE_SIZE);
++ TEST_VERIFY_EXIT (page_size > 0);
++ struct support_next_to_fault result;
++ result.region_size = roundup (size, page_size) + page_size;
++ if (size + page_size <= size || result.region_size <= size)
++ FAIL_EXIT1 ("support_next_to_fault_allocate (%zu): overflow", size);
++ result.region_start
++ = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, -1);
++ /* Unmap the page after the allocation. */
++ xmprotect (result.region_start + (result.region_size - page_size),
++ page_size, PROT_NONE);
++ /* Align the allocation within the region so that it ends just
++ before the PROT_NONE page. */
++ result.buffer = result.region_start + result.region_size - page_size - size;
++ result.length = size;
++ return result;
++}
++
++void
++support_next_to_fault_free (struct support_next_to_fault *ntf)
++{
++ xmunmap (ntf->region_start, ntf->region_size);
++ *ntf = (struct support_next_to_fault) { NULL, };
++}
+diff --git a/support/next_to_fault.h b/support/next_to_fault.h
+new file mode 100644
+index 0000000000..dd71c28ac0
+--- /dev/null
++++ b/support/next_to_fault.h
+@@ -0,0 +1,48 @@
++/* Memory allocation next to an unmapped page.
++ 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/>. */
++
++#ifndef SUPPORT_NEXT_TO_FAULT_H
++#define SUPPORT_NEXT_TO_FAULT_H
++
++#include <sys/cdefs.h>
++#include <sys/types.h>
++
++__BEGIN_DECLS
++
++/* The memory region created by next_to_fault_allocate. */
++struct support_next_to_fault
++{
++ /* The user data. */
++ char *buffer;
++ size_t length;
++
++ /* The entire allocated region. */
++ void *region_start;
++ size_t region_size;
++};
++
++/* Allocate a buffer of SIZE bytes just before a page which is mapped
++ with PROT_NONE (so that overrunning the buffer will cause a
++ fault). */
++struct support_next_to_fault support_next_to_fault_allocate (size_t size);
++
++/* Deallocate the memory region allocated by
++ next_to_fault_allocate. */
++void support_next_to_fault_free (struct support_next_to_fault *);
++
++#endif /* SUPPORT_NEXT_TO_FAULT_H */
+diff --git a/support/support-xfstat.c b/support/support-xfstat.c
+new file mode 100644
+index 0000000000..4c8ee9142b
+--- /dev/null
++++ b/support/support-xfstat.c
+@@ -0,0 +1,28 @@
++/* fstat64 with error checking.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xunistd.h>
++#include <sys/stat.h>
++
++void
++xfstat (int fd, struct stat64 *result)
++{
++ if (fstat64 (fd, result) != 0)
++ FAIL_EXIT1 ("fstat64 (%d): %m", fd);
++}
+diff --git a/support/support.h b/support/support.h
+index 4b5f04c2cc..bbba803ba1 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -68,6 +68,7 @@ void *xrealloc (void *p, size_t n);
+ char *xasprintf (const char *format, ...)
+ __attribute__ ((format (printf, 1, 2), malloc));
+ char *xstrdup (const char *);
++char *xstrndup (const char *, size_t);
+
+ __END_DECLS
+
+diff --git a/support/support_become_root.c b/support/support_become_root.c
+index 3fa0bd4ac0..933138f99f 100644
+--- a/support/support_become_root.c
++++ b/support/support_become_root.c
+@@ -18,18 +18,80 @@
+
+ #include <support/namespace.h>
+
++#include <errno.h>
++#include <fcntl.h>
+ #include <sched.h>
+ #include <stdio.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/xunistd.h>
+ #include <unistd.h>
+
++#ifdef CLONE_NEWUSER
++/* The necessary steps to allow file creation in user namespaces. */
++static void
++setup_uid_gid_mapping (uid_t original_uid, gid_t original_gid)
++{
++ int fd = open64 ("/proc/self/uid_map", O_WRONLY);
++ if (fd < 0)
++ {
++ printf ("warning: could not open /proc/self/uid_map: %m\n"
++ "warning: file creation may not be possible\n");
++ return;
++ }
++
++ /* We map our original UID to the same UID in the container so we
++ own our own files normally. Without that, file creation could
++ fail with EOVERFLOW (sic!). */
++ char buf[100];
++ int ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n",
++ (unsigned long long) original_uid,
++ (unsigned long long) original_uid);
++ TEST_VERIFY_EXIT (ret < sizeof (buf));
++ xwrite (fd, buf, ret);
++ xclose (fd);
++
++ /* Linux 3.19 introduced the setgroups file. We need write "deny" to this
++ file otherwise writing to gid_map will fail with EPERM. */
++ fd = open64 ("/proc/self/setgroups", O_WRONLY, 0);
++ if (fd < 0)
++ {
++ if (errno != ENOENT)
++ FAIL_EXIT1 ("open64 (\"/proc/self/setgroups\", 0x%x, 0%o): %m",
++ O_WRONLY, 0);
++ /* This kernel doesn't expose the setgroups file so simply move on. */
++ }
++ else
++ {
++ xwrite (fd, "deny\n", strlen ("deny\n"));
++ xclose (fd);
++ }
++
++ /* Now map our own GID, like we did for the user ID. */
++ fd = xopen ("/proc/self/gid_map", O_WRONLY, 0);
++ ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n",
++ (unsigned long long) original_gid,
++ (unsigned long long) original_gid);
++ TEST_VERIFY_EXIT (ret < sizeof (buf));
++ xwrite (fd, buf, ret);
++ xclose (fd);
++}
++#endif /* CLONE_NEWUSER */
++
+ bool
+ support_become_root (void)
+ {
+ #ifdef CLONE_NEWUSER
++ uid_t original_uid = getuid ();
++ gid_t original_gid = getgid ();
++
+ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0)
+- /* Even if we do not have UID zero, we have extended privileges at
+- this point. */
+- return true;
++ {
++ setup_uid_gid_mapping (original_uid, original_gid);
++ /* Even if we do not have UID zero, we have extended privileges at
++ this point. */
++ return true;
++ }
+ #endif
+ if (setuid (0) != 0)
+ {
+diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c
+index 0dfd2deb54..a462753f76 100644
+--- a/support/support_can_chroot.c
++++ b/support/support_can_chroot.c
+@@ -21,9 +21,9 @@
+ #include <support/check.h>
+ #include <support/namespace.h>
+ #include <support/support.h>
++#include <support/xunistd.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+-#include <xunistd.h>
+
+ static void
+ callback (void *closure)
diff --git a/support/support_chroot.c b/support/support_chroot.c
-index c0807b313a..f3ef551b05 100644
+index c0807b313a..693813f694 100644
--- a/support/support_chroot.c
+++ b/support/support_chroot.c
-@@ -24,6 +24,23 @@
+@@ -24,30 +24,38 @@
#include <support/test-driver.h>
#include <support/xunistd.h>
@@ -11042,7 +11683,16 @@ index c0807b313a..f3ef551b05 100644
struct support_chroot *
support_chroot_create (struct support_chroot_configuration conf)
{
-@@ -39,15 +56,10 @@ support_chroot_create (struct support_chroot_configuration conf)
+ struct support_chroot *chroot = xmalloc (sizeof (*chroot));
+-
+- chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
+- if (mkdtemp (chroot->path_chroot) == NULL)
+- FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot);
+- add_temp_file (chroot->path_chroot);
++ chroot->path_chroot = support_create_temp_directory ("tst-resolv-res_init-");
+
+ /* Create the /etc directory in the chroot environment. */
+ char *path_etc = xasprintf ("%s/etc", chroot->path_chroot);
xmkdir (path_etc, 0777);
add_temp_file (path_etc);
@@ -11062,7 +11712,7 @@ index c0807b313a..f3ef551b05 100644
free (path_etc);
-@@ -67,5 +79,7 @@ support_chroot_free (struct support_chroot *chroot)
+@@ -67,5 +75,7 @@ support_chroot_free (struct support_chroot *chroot)
{
free (chroot->path_chroot);
free (chroot->path_resolv_conf);
@@ -11070,70 +11720,14 @@ index c0807b313a..f3ef551b05 100644
+ free (chroot->path_host_conf);
free (chroot);
}
-diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
-index 78d52c717d..9aa1e79a80 100644
---- a/sysdeps/aarch64/multiarch/Makefile
-+++ b/sysdeps/aarch64/multiarch/Makefile
-@@ -1,3 +1,4 @@
- ifeq ($(subdir),string)
--sysdep_routines += memcpy_generic memcpy_thunderx
-+sysdep_routines += memcpy_generic memcpy_thunderx memcpy_falkor \
-+ memmove_falkor
- endif
-diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
-index 32056bcec3..2cb74d5b43 100644
---- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
-+++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
-@@ -25,7 +25,7 @@
- #include <stdio.h>
-
- /* Maximum number of IFUNC implementations. */
--#define MAX_IFUNC 2
-+#define MAX_IFUNC 3
-
- size_t
- __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
-@@ -40,9 +40,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
- /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */
- IFUNC_IMPL (i, name, memcpy,
- IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
-+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor)
- IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic))
- IFUNC_IMPL (i, name, memmove,
- IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx)
-+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor)
- IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic))
-
- return i;
-diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
-index 9f73efbba7..b395df1c63 100644
---- a/sysdeps/aarch64/multiarch/memcpy.c
-+++ b/sysdeps/aarch64/multiarch/memcpy.c
-@@ -30,9 +30,14 @@ extern __typeof (__redirect_memcpy) __libc_memcpy;
-
- extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
- extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden;
-+extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
-
- libc_ifunc (__libc_memcpy,
-- IS_THUNDERX (midr) ? __memcpy_thunderx : __memcpy_generic);
-+ (IS_THUNDERX (midr)
-+ ? __memcpy_thunderx
-+ : (IS_FALKOR (midr)
-+ ? __memcpy_falkor
-+ : __memcpy_generic)));
-
- # undef memcpy
- strong_alias (__libc_memcpy, memcpy);
-diff --git a/sysdeps/aarch64/multiarch/memcpy_falkor.S b/sysdeps/aarch64/multiarch/memcpy_falkor.S
+diff --git a/support/support_enter_mount_namespace.c b/support/support_enter_mount_namespace.c
new file mode 100644
-index 0000000000..dea4f225ee
+index 0000000000..6140692075
--- /dev/null
-+++ b/sysdeps/aarch64/multiarch/memcpy_falkor.S
-@@ -0,0 +1,184 @@
-+/* Optimized memcpy for Qualcomm Falkor processor.
++++ b/support/support_enter_mount_namespace.c
+@@ -0,0 +1,45 @@
++/* Enter a mount namespace.
+ 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
@@ -11147,202 +11741,228 @@ index 0000000000..dea4f225ee
+ 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
++ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
-+#include <sysdep.h>
-+
-+/* Assumptions:
++#include <support/namespace.h>
+
-+ ARMv8-a, AArch64, falkor, unaligned accesses. */
++#include <sched.h>
++#include <stdio.h>
++#include <sys/mount.h>
+
-+#define dstin x0
-+#define src x1
-+#define count x2
-+#define dst x3
-+#define srcend x4
-+#define dstend x5
-+#define A_l x6
-+#define A_lw w6
-+#define A_h x7
-+#define A_hw w7
-+#define tmp1 x14
-+
-+/* Copies are split into 3 main cases:
-+
-+ 1. Small copies of up to 32 bytes
-+ 2. Medium copies of 33..128 bytes which are fully unrolled
-+ 3. Large copies of more than 128 bytes.
-+
-+ Large copies align the sourceto a quad word and use an unrolled loop
-+ processing 64 bytes per iteration.
-+
-+ FALKOR-SPECIFIC DESIGN:
-+
-+ The smallest copies (32 bytes or less) focus on optimal pipeline usage,
-+ which is why the redundant copies of 0-3 bytes have been replaced with
-+ conditionals, since the former would unnecessarily break across multiple
-+ issue groups. The medium copy group has been enlarged to 128 bytes since
-+ bumping up the small copies up to 32 bytes allows us to do that without
-+ cost and also allows us to reduce the size of the prep code before loop64.
-+
-+ All copies are done only via two registers r6 and r7. This is to ensure
-+ that all loads hit a single hardware prefetcher which can get correctly
-+ trained to prefetch a single stream.
-+
-+ The non-temporal stores help optimize cache utilization. */
-+
-+#if IS_IN (libc)
-+ENTRY_ALIGN (__memcpy_falkor, 6)
-+
-+ cmp count, 32
-+ add srcend, src, count
-+ add dstend, dstin, count
-+ b.ls L(copy32)
-+ ldp A_l, A_h, [src]
-+ cmp count, 128
-+ stp A_l, A_h, [dstin]
-+ b.hi L(copy_long)
++bool
++support_enter_mount_namespace (void)
++{
++#ifdef CLONE_NEWNS
++ if (unshare (CLONE_NEWNS) == 0)
++ {
++ /* On some systems, / is marked as MS_SHARED, which means that
++ mounts within the namespace leak to the rest of the system,
++ which is not what we want. */
++ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
++ {
++ printf ("warning: making the mount namespace private failed: %m\n");
++ return false;
++ }
++ return true;
++ }
++ else
++ printf ("warning: unshare (CLONE_NEWNS) failed: %m\n");
++#endif /* CLONE_NEWNS */
++ return false;
++}
+diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c
+index eedb030591..daf335f775 100644
+--- a/support/support_format_addrinfo.c
++++ b/support/support_format_addrinfo.c
+@@ -21,6 +21,7 @@
+ #include <arpa/inet.h>
+ #include <errno.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <support/support.h>
+ #include <support/xmemstream.h>
+
+diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c
+index 2992c57971..e5ef1aa4b3 100644
+--- a/support/support_format_dns_packet.c
++++ b/support/support_format_dns_packet.c
+@@ -20,6 +20,7 @@
+
+ #include <arpa/inet.h>
+ #include <resolv.h>
++#include <stdbool.h>
+ #include <support/check.h>
+ #include <support/support.h>
+ #include <support/xmemstream.h>
+diff --git a/support/support_format_hostent.c b/support/support_format_hostent.c
+index 5b5f26082e..0aac17972b 100644
+--- a/support/support_format_hostent.c
++++ b/support/support_format_hostent.c
+@@ -19,7 +19,9 @@
+ #include <support/format_nss.h>
+
+ #include <arpa/inet.h>
++#include <errno.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <support/support.h>
+ #include <support/xmemstream.h>
+
+@@ -41,10 +43,15 @@ support_format_hostent (struct hostent *h)
+ {
+ if (h == NULL)
+ {
+- char *value = support_format_herrno (h_errno);
+- char *result = xasprintf ("error: %s\n", value);
+- free (value);
+- return result;
++ if (h_errno == NETDB_INTERNAL)
++ return xasprintf ("error: NETDB_INTERNAL (errno %d, %m)\n", errno);
++ else
++ {
++ char *value = support_format_herrno (h_errno);
++ char *result = xasprintf ("error: %s\n", value);
++ free (value);
++ return result;
++ }
+ }
+
+ struct xmemstream mem;
+diff --git a/support/support_format_netent.c b/support/support_format_netent.c
+index 020f5720d9..be8f1720a2 100644
+--- a/support/support_format_netent.c
++++ b/support/support_format_netent.c
+@@ -20,6 +20,7 @@
+
+ #include <arpa/inet.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <support/support.h>
+ #include <support/xmemstream.h>
+
+diff --git a/support/support_test_compare_failure.c b/support/support_test_compare_failure.c
+new file mode 100644
+index 0000000000..894145b56d
+--- /dev/null
++++ b/support/support_test_compare_failure.c
+@@ -0,0 +1,55 @@
++/* Reporting a numeric comparison failure.
++ Copyright (C) 2017 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
+
-+ /* Medium copies: 33..128 bytes. */
-+ sub tmp1, count, 1
-+ ldp A_l, A_h, [src, 16]
-+ stp A_l, A_h, [dstin, 16]
-+ tbz tmp1, 6, 1f
-+ ldp A_l, A_h, [src, 32]
-+ stp A_l, A_h, [dstin, 32]
-+ ldp A_l, A_h, [src, 48]
-+ stp A_l, A_h, [dstin, 48]
-+ ldp A_l, A_h, [srcend, -64]
-+ stp A_l, A_h, [dstend, -64]
-+ ldp A_l, A_h, [srcend, -48]
-+ stp A_l, A_h, [dstend, -48]
-+1:
-+ ldp A_l, A_h, [srcend, -32]
-+ stp A_l, A_h, [dstend, -32]
-+ ldp A_l, A_h, [srcend, -16]
-+ stp A_l, A_h, [dstend, -16]
-+ ret
++ 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.
+
-+ .p2align 4
-+ /* Small copies: 0..32 bytes. */
-+L(copy32):
-+ /* 16-32 */
-+ cmp count, 16
-+ b.lo 1f
-+ ldp A_l, A_h, [src]
-+ stp A_l, A_h, [dstin]
-+ ldp A_l, A_h, [srcend, -16]
-+ stp A_l, A_h, [dstend, -16]
-+ ret
-+ .p2align 4
-+1:
-+ /* 8-15 */
-+ tbz count, 3, 1f
-+ ldr A_l, [src]
-+ str A_l, [dstin]
-+ ldr A_l, [srcend, -8]
-+ str A_l, [dstend, -8]
-+ ret
-+ .p2align 4
-+1:
-+ /* 4-7 */
-+ tbz count, 2, 1f
-+ ldr A_lw, [src]
-+ str A_lw, [dstin]
-+ ldr A_lw, [srcend, -4]
-+ str A_lw, [dstend, -4]
-+ ret
-+ .p2align 4
-+1:
-+ /* 2-3 */
-+ tbz count, 1, 1f
-+ ldrh A_lw, [src]
-+ strh A_lw, [dstin]
-+ ldrh A_lw, [srcend, -2]
-+ strh A_lw, [dstend, -2]
-+ ret
-+ .p2align 4
-+1:
-+ /* 0-1 */
-+ tbz count, 0, 1f
-+ ldrb A_lw, [src]
-+ strb A_lw, [dstin]
-+1:
-+ ret
++ 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.
+
-+ /* Align SRC to 16 bytes and copy; that way at least one of the
-+ accesses is aligned throughout the copy sequence.
++ 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/>. */
+
-+ The count is off by 0 to 15 bytes, but this is OK because we trim
-+ off the last 64 bytes to copy off from the end. Due to this the
-+ loop never runs out of bounds. */
-+ .p2align 6
-+L(copy_long):
-+ sub count, count, 64 + 16
-+ and tmp1, src, 15
-+ bic src, src, 15
-+ sub dst, dstin, tmp1
-+ add count, count, tmp1
++#include <stdio.h>
++#include <support/check.h>
+
-+L(loop64):
-+ ldp A_l, A_h, [src, 16]!
-+ stnp A_l, A_h, [dst, 16]
-+ ldp A_l, A_h, [src, 16]!
-+ subs count, count, 64
-+ stnp A_l, A_h, [dst, 32]
-+ ldp A_l, A_h, [src, 16]!
-+ stnp A_l, A_h, [dst, 48]
-+ ldp A_l, A_h, [src, 16]!
-+ stnp A_l, A_h, [dst, 64]
-+ add dst, dst, 64
-+ b.hi L(loop64)
++static void
++report (const char *which, const char *expr, long long value, int negative,
++ int size)
++{
++ printf (" %s: ", which);
++ if (negative)
++ printf ("%lld", value);
++ else
++ printf ("%llu", (unsigned long long) value);
++ unsigned long long mask
++ = (~0ULL) >> (8 * (sizeof (unsigned long long) - size));
++ printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr);
++}
+
-+ /* Write the last full set of 64 bytes. The remainder is at most 64
-+ bytes, so it is safe to always copy 64 bytes from the end even if
-+ there is just 1 byte left. */
-+L(last64):
-+ ldp A_l, A_h, [srcend, -64]
-+ stnp A_l, A_h, [dstend, -64]
-+ ldp A_l, A_h, [srcend, -48]
-+ stnp A_l, A_h, [dstend, -48]
-+ ldp A_l, A_h, [srcend, -32]
-+ stnp A_l, A_h, [dstend, -32]
-+ ldp A_l, A_h, [srcend, -16]
-+ stnp A_l, A_h, [dstend, -16]
-+ ret
++void
++support_test_compare_failure (const char *file, int line,
++ const char *left_expr,
++ long long left_value,
++ int left_negative,
++ int left_size,
++ const char *right_expr,
++ long long right_value,
++ int right_negative,
++ int right_size)
++{
++ support_record_failure ();
++ if (left_size != right_size)
++ printf ("%s:%d: numeric comparison failure (widths %d and %d)\n",
++ file, line, left_size * 8, right_size * 8);
++ else
++ printf ("%s:%d: numeric comparison failure\n", file, line);
++ report (" left", left_expr, left_value, left_negative, left_size);
++ report ("right", right_expr, right_value, right_negative, right_size);
++}
+diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c
+index 48e89597f3..48736530bf 100644
+--- a/support/support_write_file_string.c
++++ b/support/support_write_file_string.c
+@@ -19,7 +19,7 @@
+ #include <fcntl.h>
+ #include <string.h>
+ #include <support/check.h>
+-#include <xunistd.h>
++#include <support/xunistd.h>
+
+ void
+ support_write_file_string (const char *path, const char *contents)
+diff --git a/support/temp_file.c b/support/temp_file.c
+index fdb2477ab9..547263a3e4 100644
+--- a/support/temp_file.c
++++ b/support/temp_file.c
+@@ -86,6 +86,19 @@ create_temp_file (const char *base, char **filename)
+ return fd;
+ }
+
++char *
++support_create_temp_directory (const char *base)
++{
++ char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
++ if (mkdtemp (path) == NULL)
++ {
++ printf ("error: mkdtemp (\"%s\"): %m", path);
++ exit (1);
++ }
++ add_temp_file (path);
++ return path;
++}
+
-+END (__memcpy_falkor)
-+libc_hidden_builtin_def (__memcpy_falkor)
-+#endif
-diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
-index 34c6b29bd5..016f03ee50 100644
---- a/sysdeps/aarch64/multiarch/memmove.c
-+++ b/sysdeps/aarch64/multiarch/memmove.c
-@@ -30,9 +30,14 @@ extern __typeof (__redirect_memmove) __libc_memmove;
+ /* Helper functions called by the test skeleton follow. */
- extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden;
- extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden;
-+extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden;
+ void
+diff --git a/support/temp_file.h b/support/temp_file.h
+index 6fed8df1ea..3b8563e115 100644
+--- a/support/temp_file.h
++++ b/support/temp_file.h
+@@ -32,6 +32,11 @@ void add_temp_file (const char *name);
+ *FILENAME. */
+ int create_temp_file (const char *base, char **filename);
- libc_ifunc (__libc_memmove,
-- IS_THUNDERX (midr) ? __memmove_thunderx : __memmove_generic);
-+ (IS_THUNDERX (midr)
-+ ? __memmove_thunderx
-+ : (IS_FALKOR (midr)
-+ ? __memmove_falkor
-+ : __memmove_generic)));
++/* Create a temporary directory and schedule it for deletion. BASE is
++ used as a prefix for the unique directory name, which the function
++ returns. The caller should free this string. */
++char *support_create_temp_directory (const char *base);
++
+ __END_DECLS
- # undef memmove
- strong_alias (__libc_memmove, memmove);
-diff --git a/sysdeps/aarch64/multiarch/memmove_falkor.S b/sysdeps/aarch64/multiarch/memmove_falkor.S
+ #endif /* SUPPORT_TEMP_FILE_H */
+diff --git a/support/tst-test_compare.c b/support/tst-test_compare.c
new file mode 100644
-index 0000000000..3a4e6a2a8e
+index 0000000000..de138d4f8a
--- /dev/null
-+++ b/sysdeps/aarch64/multiarch/memmove_falkor.S
-@@ -0,0 +1,232 @@
-+/* Copyright (C) 2017 Free Software Foundation, Inc.
-+
++++ b/support/tst-test_compare.c
+@@ -0,0 +1,98 @@
++/* Basic test for the TEST_COMPARE macro.
++ 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
@@ -11356,21 +11976,944 @@ index 0000000000..3a4e6a2a8e
+ 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
++ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
-+#include <sysdep.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/capture_subprocess.h>
+
-+/* Assumptions: ARMv8-a, AArch64, falkor, unaligned accesses. */
++static void
++subprocess (void *closure)
++{
++ char ch = 1;
++ /* These tests should fail. */
++ TEST_COMPARE (ch, -1); /* Line 28. */
++ TEST_COMPARE (2LL, -2LL); /* Line 29. */
++ TEST_COMPARE (3LL, (short) -3); /* Line 30. */
++}
+
-+#define dstin x0
-+#define src x1
-+#define count x2
-+#define dstlen x3
-+#define dst x3
-+#define srcend x4
-+#define dstend x5
-+#define A_l x6
++struct bitfield
++{
++ int i2 : 2;
++ int i3 : 3;
++ unsigned int u2 : 2;
++ unsigned int u3 : 3;
++ int i31 : 31;
++ unsigned int u31 : 31 ;
++ long long int i63 : 63;
++ unsigned long long int u63 : 63;
++};
++
++static int
++do_test (void)
++{
++ /* This should succeed. */
++ TEST_COMPARE (1, 1);
++ TEST_COMPARE (2LL, 2U);
++ {
++ char i8 = 3;
++ unsigned short u16 = 3;
++ TEST_COMPARE (i8, u16);
++ }
++
++ struct bitfield bitfield = { 0 };
++ TEST_COMPARE (bitfield.i2, bitfield.i3);
++ TEST_COMPARE (bitfield.u2, bitfield.u3);
++ TEST_COMPARE (bitfield.u2, bitfield.i3);
++ TEST_COMPARE (bitfield.u3, bitfield.i3);
++ TEST_COMPARE (bitfield.i2, bitfield.u3);
++ TEST_COMPARE (bitfield.i3, bitfield.u2);
++ TEST_COMPARE (bitfield.i63, bitfield.i63);
++ TEST_COMPARE (bitfield.u63, bitfield.u63);
++ TEST_COMPARE (bitfield.i31, bitfield.i63);
++ TEST_COMPARE (bitfield.i63, bitfield.i31);
++
++ struct support_capture_subprocess proc = support_capture_subprocess
++ (&subprocess, NULL);
++
++ /* Discard the reported error. */
++ support_record_failure_reset ();
++
++ puts ("info: *** subprocess output starts ***");
++ fputs (proc.out.buffer, stdout);
++ puts ("info: *** subprocess output ends ***");
++
++ TEST_VERIFY
++ (strcmp (proc.out.buffer,
++ "tst-test_compare.c:28: numeric comparison failure\n"
++ " left: 1 (0x1); from: ch\n"
++ " right: -1 (0xffffffff); from: -1\n"
++ "tst-test_compare.c:29: numeric comparison failure\n"
++ " left: 2 (0x2); from: 2LL\n"
++ " right: -2 (0xfffffffffffffffe); from: -2LL\n"
++ "tst-test_compare.c:30: numeric comparison failure"
++ " (widths 64 and 32)\n"
++ " left: 3 (0x3); from: 3LL\n"
++ " right: -3 (0xfffffffd); from: (short) -3\n") == 0);
++
++ /* Check that there is no output on standard error. */
++ support_capture_subprocess_check (&proc, "TEST_COMPARE", 0, sc_allow_stdout);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/support/tst-xreadlink.c b/support/tst-xreadlink.c
+new file mode 100644
+index 0000000000..a4a22812c1
+--- /dev/null
++++ b/support/tst-xreadlink.c
+@@ -0,0 +1,72 @@
++/* Test the xreadlink function.
++ 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/>. */
++
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/xunistd.h>
++
++static int
++do_test (void)
++{
++ char *dir = support_create_temp_directory ("tst-xreadlink-");
++ char *symlink_name = xasprintf ("%s/symlink", dir);
++ add_temp_file (symlink_name);
++
++ /* The limit 10000 is arbitrary and simply there to prevent an
++ attempt to exhaust all available disk space. */
++ for (int size = 1; size < 10000; ++size)
++ {
++ char *contents = xmalloc (size + 1);
++ for (int i = 0; i < size; ++i)
++ contents[i] = 'a' + (rand () % 26);
++ contents[size] = '\0';
++ if (symlink (contents, symlink_name) != 0)
++ {
++ if (errno == ENAMETOOLONG)
++ {
++ printf ("info: ENAMETOOLONG failure at %d bytes\n", size);
++ free (contents);
++ break;
++ }
++ FAIL_EXIT1 ("symlink (%d bytes): %m", size);
++ }
++
++ char *readlink_result = xreadlink (symlink_name);
++ TEST_VERIFY (strcmp (readlink_result, contents) == 0);
++ free (readlink_result);
++ xunlink (symlink_name);
++ free (contents);
++ }
++
++ /* Create an empty file to suppress the temporary file deletion
++ warning. */
++ xclose (xopen (symlink_name, O_WRONLY | O_CREAT, 0));
++
++ free (symlink_name);
++ free (dir);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/support/xdlfcn.c b/support/xdlfcn.c
+new file mode 100644
+index 0000000000..05966c41ef
+--- /dev/null
++++ b/support/xdlfcn.c
+@@ -0,0 +1,59 @@
++/* Support functionality for using dlopen/dlclose/dlsym.
++ 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/>. */
++
++#include <stddef.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++void *
++xdlopen (const char *filename, int flags)
++{
++ void *dso = dlopen (filename, flags);
++
++ if (dso == NULL)
++ FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ());
++
++ /* Clear any errors. */
++ dlerror ();
++
++ return dso;
++}
++
++void *
++xdlsym (void *handle, const char *symbol)
++{
++ void *sym = dlsym (handle, symbol);
++
++ if (sym == NULL)
++ FAIL_EXIT1 ("error: dlsym: %s\n", dlerror ());
++
++ /* Clear any errors. */
++ dlerror ();
++
++ return sym;
++}
++
++void
++xdlclose (void *handle)
++{
++ if (dlclose (handle) != 0)
++ FAIL_EXIT1 ("error: dlclose: %s\n", dlerror ());
++
++ /* Clear any errors. */
++ dlerror ();
++}
+diff --git a/support/xdlfcn.h b/support/xdlfcn.h
+new file mode 100644
+index 0000000000..9bdcb38d3e
+--- /dev/null
++++ b/support/xdlfcn.h
+@@ -0,0 +1,34 @@
++/* Support functionality for using dlopen/dlclose/dlsym.
++ 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/>. */
++
++#ifndef SUPPORT_DLOPEN_H
++#define SUPPORT_DLOPEN_H
++
++#include <dlfcn.h>
++
++__BEGIN_DECLS
++
++/* Each of these terminates process on failure with relevant error message. */
++void *xdlopen (const char *filename, int flags);
++void *xdlsym (void *handle, const char *symbol);
++void xdlclose (void *handle);
++
++
++__END_DECLS
++
++#endif /* SUPPORT_DLOPEN_H */
+diff --git a/support/xftruncate.c b/support/xftruncate.c
+new file mode 100644
+index 0000000000..9c4e9e3050
+--- /dev/null
++++ b/support/xftruncate.c
+@@ -0,0 +1,27 @@
++/* ftruncate with error checking.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xunistd.h>
++
++void
++xftruncate (int fd, long long length)
++{
++ if (ftruncate64 (fd, length) != 0)
++ FAIL_EXIT1 ("ftruncate64 (%d, %lld): %m", fd, length);
++}
+diff --git a/support/xlseek.c b/support/xlseek.c
+new file mode 100644
+index 0000000000..0a75a9f2e6
+--- /dev/null
++++ b/support/xlseek.c
+@@ -0,0 +1,29 @@
++/* lseek with error checking.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xunistd.h>
++
++long long
++xlseek (int fd, long long offset, int whence)
++{
++ long long result = lseek64 (fd, offset, whence);
++ if (result < 0)
++ FAIL_EXIT1 ("lseek64 (%d, %lld, %d): %m", fd, offset, whence);
++ return result;
++}
+diff --git a/support/xraise.c b/support/xraise.c
+new file mode 100644
+index 0000000000..9126c6c3ea
+--- /dev/null
++++ b/support/xraise.c
+@@ -0,0 +1,27 @@
++/* Error-checking wrapper for raise.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xsignal.h>
++
++void
++xraise (int sig)
++{
++ if (raise (sig) != 0)
++ FAIL_EXIT1 ("raise (%d): %m" , sig);
++}
+diff --git a/support/xreadlink.c b/support/xreadlink.c
+new file mode 100644
+index 0000000000..aec58a2aa6
+--- /dev/null
++++ b/support/xreadlink.c
+@@ -0,0 +1,44 @@
++/* Error-checking, allocating wrapper for readlink.
++ 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/>. */
++
++#include <scratch_buffer.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <xunistd.h>
++
++char *
++xreadlink (const char *path)
++{
++ struct scratch_buffer buf;
++ scratch_buffer_init (&buf);
++
++ while (true)
++ {
++ ssize_t count = readlink (path, buf.data, buf.length);
++ if (count < 0)
++ FAIL_EXIT1 ("readlink (\"%s\"): %m", path);
++ if (count < buf.length)
++ {
++ char *result = xstrndup (buf.data, count);
++ scratch_buffer_free (&buf);
++ return result;
++ }
++ if (!scratch_buffer_grow (&buf))
++ FAIL_EXIT1 ("scratch_buffer_grow in xreadlink");
++ }
++}
+diff --git a/support/xsigaction.c b/support/xsigaction.c
+new file mode 100644
+index 0000000000..b74c69afae
+--- /dev/null
++++ b/support/xsigaction.c
+@@ -0,0 +1,27 @@
++/* Error-checking wrapper for sigaction.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xsignal.h>
++
++void
++xsigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
++{
++ if (sigaction (sig, newact, oldact))
++ FAIL_EXIT1 ("sigaction (%d): %m" , sig);
++}
+diff --git a/support/xsignal.c b/support/xsignal.c
+new file mode 100644
+index 0000000000..22a1dd74a7
+--- /dev/null
++++ b/support/xsignal.c
+@@ -0,0 +1,29 @@
++/* Error-checking wrapper for signal.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xsignal.h>
++
++sighandler_t
++xsignal (int sig, sighandler_t handler)
++{
++ sighandler_t result = signal (sig, handler);
++ if (result == SIG_ERR)
++ FAIL_EXIT1 ("signal (%d, %p): %m", sig, handler);
++ return result;
++}
+diff --git a/support/xsignal.h b/support/xsignal.h
+index 3dc0d9d5ce..3087ed0082 100644
+--- a/support/xsignal.h
++++ b/support/xsignal.h
+@@ -24,6 +24,14 @@
+
+ __BEGIN_DECLS
+
++/* The following functions call the corresponding libc functions and
++ terminate the process on error. */
++
++void xraise (int sig);
++sighandler_t xsignal (int sig, sighandler_t handler);
++void xsigaction (int sig, const struct sigaction *newact,
++ struct sigaction *oldact);
++
+ /* The following functions call the corresponding libpthread functions
+ and terminate the process on error. */
+
+diff --git a/support/xstrndup.c b/support/xstrndup.c
+new file mode 100644
+index 0000000000..d59a283d25
+--- /dev/null
++++ b/support/xstrndup.c
+@@ -0,0 +1,30 @@
++/* strndup with error checking.
++ Copyright (C) 2016-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/>. */
++
++#include <support/support.h>
++
++#include <string.h>
++
++char *
++xstrndup (const char *s, size_t length)
++{
++ char *p = strndup (s, length);
++ if (p == NULL)
++ oom_error ("strndup", length);
++ return p;
++}
+diff --git a/support/xsysconf.c b/support/xsysconf.c
+new file mode 100644
+index 0000000000..15ab1e26c4
+--- /dev/null
++++ b/support/xsysconf.c
+@@ -0,0 +1,36 @@
++/* Error-checking wrapper for sysconf.
++ 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/>. */
++
++#include <errno.h>
++#include <support/check.h>
++#include <support/xunistd.h>
++
++long
++xsysconf (int name)
++{
++ /* Detect errors by a changed errno value, in case -1 is a valid
++ value. Make sure that the caller does not see the zero value for
++ errno. */
++ int old_errno = errno;
++ errno = 0;
++ long result = sysconf (name);
++ if (errno != 0)
++ FAIL_EXIT1 ("sysconf (%d): %m", name);
++ errno = old_errno;
++ return result;
++}
+diff --git a/support/xunistd.h b/support/xunistd.h
+index c947bfd8fb..29da063c15 100644
+--- a/support/xunistd.h
++++ b/support/xunistd.h
+@@ -36,8 +36,17 @@ void xpipe (int[2]);
+ void xdup2 (int, int);
+ int xopen (const char *path, int flags, mode_t);
+ void xstat (const char *path, struct stat64 *);
++void xfstat (int fd, struct stat64 *);
+ void xmkdir (const char *path, mode_t);
+ void xchroot (const char *path);
++void xunlink (const char *path);
++long xsysconf (int name);
++long long xlseek (int fd, long long offset, int whence);
++void xftruncate (int fd, long long length);
++
++/* Read the link at PATH. The caller should free the returned string
++ with free. */
++char *xreadlink (const char *path);
+
+ /* Close the file descriptor. Ignore EINTR errors, but terminate the
+ process on other errors. */
+diff --git a/support/xunlink.c b/support/xunlink.c
+new file mode 100644
+index 0000000000..f94ee118cf
+--- /dev/null
++++ b/support/xunlink.c
+@@ -0,0 +1,27 @@
++/* Error-checking wrapper for unlink.
++ 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/>. */
++
++#include <support/check.h>
++#include <support/xunistd.h>
++
++void
++xunlink (const char *path)
++{
++ if (unlink (path) != 0)
++ FAIL_EXIT1 ("unlink (\"%s\"): %m", path);
++}
+diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
+index 78d52c717d..9aa1e79a80 100644
+--- a/sysdeps/aarch64/multiarch/Makefile
++++ b/sysdeps/aarch64/multiarch/Makefile
+@@ -1,3 +1,4 @@
+ ifeq ($(subdir),string)
+-sysdep_routines += memcpy_generic memcpy_thunderx
++sysdep_routines += memcpy_generic memcpy_thunderx memcpy_falkor \
++ memmove_falkor
+ endif
+diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
+index 32056bcec3..2cb74d5b43 100644
+--- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
++++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
+@@ -25,7 +25,7 @@
+ #include <stdio.h>
+
+ /* Maximum number of IFUNC implementations. */
+-#define MAX_IFUNC 2
++#define MAX_IFUNC 3
+
+ size_t
+ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+@@ -40,9 +40,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+ /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */
+ IFUNC_IMPL (i, name, memcpy,
+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
++ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor)
+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic))
+ IFUNC_IMPL (i, name, memmove,
+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx)
++ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor)
+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic))
+
+ return i;
+diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
+index 9f73efbba7..b395df1c63 100644
+--- a/sysdeps/aarch64/multiarch/memcpy.c
++++ b/sysdeps/aarch64/multiarch/memcpy.c
+@@ -30,9 +30,14 @@ extern __typeof (__redirect_memcpy) __libc_memcpy;
+
+ extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
+ extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden;
++extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
+
+ libc_ifunc (__libc_memcpy,
+- IS_THUNDERX (midr) ? __memcpy_thunderx : __memcpy_generic);
++ (IS_THUNDERX (midr)
++ ? __memcpy_thunderx
++ : (IS_FALKOR (midr)
++ ? __memcpy_falkor
++ : __memcpy_generic)));
+
+ # undef memcpy
+ strong_alias (__libc_memcpy, memcpy);
+diff --git a/sysdeps/aarch64/multiarch/memcpy_falkor.S b/sysdeps/aarch64/multiarch/memcpy_falkor.S
+new file mode 100644
+index 0000000000..dea4f225ee
+--- /dev/null
++++ b/sysdeps/aarch64/multiarch/memcpy_falkor.S
+@@ -0,0 +1,184 @@
++/* Optimized memcpy for Qualcomm Falkor processor.
++ 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/>. */
++
++#include <sysdep.h>
++
++/* Assumptions:
++
++ ARMv8-a, AArch64, falkor, unaligned accesses. */
++
++#define dstin x0
++#define src x1
++#define count x2
++#define dst x3
++#define srcend x4
++#define dstend x5
++#define A_l x6
++#define A_lw w6
++#define A_h x7
++#define A_hw w7
++#define tmp1 x14
++
++/* Copies are split into 3 main cases:
++
++ 1. Small copies of up to 32 bytes
++ 2. Medium copies of 33..128 bytes which are fully unrolled
++ 3. Large copies of more than 128 bytes.
++
++ Large copies align the sourceto a quad word and use an unrolled loop
++ processing 64 bytes per iteration.
++
++ FALKOR-SPECIFIC DESIGN:
++
++ The smallest copies (32 bytes or less) focus on optimal pipeline usage,
++ which is why the redundant copies of 0-3 bytes have been replaced with
++ conditionals, since the former would unnecessarily break across multiple
++ issue groups. The medium copy group has been enlarged to 128 bytes since
++ bumping up the small copies up to 32 bytes allows us to do that without
++ cost and also allows us to reduce the size of the prep code before loop64.
++
++ All copies are done only via two registers r6 and r7. This is to ensure
++ that all loads hit a single hardware prefetcher which can get correctly
++ trained to prefetch a single stream.
++
++ The non-temporal stores help optimize cache utilization. */
++
++#if IS_IN (libc)
++ENTRY_ALIGN (__memcpy_falkor, 6)
++
++ cmp count, 32
++ add srcend, src, count
++ add dstend, dstin, count
++ b.ls L(copy32)
++ ldp A_l, A_h, [src]
++ cmp count, 128
++ stp A_l, A_h, [dstin]
++ b.hi L(copy_long)
++
++ /* Medium copies: 33..128 bytes. */
++ sub tmp1, count, 1
++ ldp A_l, A_h, [src, 16]
++ stp A_l, A_h, [dstin, 16]
++ tbz tmp1, 6, 1f
++ ldp A_l, A_h, [src, 32]
++ stp A_l, A_h, [dstin, 32]
++ ldp A_l, A_h, [src, 48]
++ stp A_l, A_h, [dstin, 48]
++ ldp A_l, A_h, [srcend, -64]
++ stp A_l, A_h, [dstend, -64]
++ ldp A_l, A_h, [srcend, -48]
++ stp A_l, A_h, [dstend, -48]
++1:
++ ldp A_l, A_h, [srcend, -32]
++ stp A_l, A_h, [dstend, -32]
++ ldp A_l, A_h, [srcend, -16]
++ stp A_l, A_h, [dstend, -16]
++ ret
++
++ .p2align 4
++ /* Small copies: 0..32 bytes. */
++L(copy32):
++ /* 16-32 */
++ cmp count, 16
++ b.lo 1f
++ ldp A_l, A_h, [src]
++ stp A_l, A_h, [dstin]
++ ldp A_l, A_h, [srcend, -16]
++ stp A_l, A_h, [dstend, -16]
++ ret
++ .p2align 4
++1:
++ /* 8-15 */
++ tbz count, 3, 1f
++ ldr A_l, [src]
++ str A_l, [dstin]
++ ldr A_l, [srcend, -8]
++ str A_l, [dstend, -8]
++ ret
++ .p2align 4
++1:
++ /* 4-7 */
++ tbz count, 2, 1f
++ ldr A_lw, [src]
++ str A_lw, [dstin]
++ ldr A_lw, [srcend, -4]
++ str A_lw, [dstend, -4]
++ ret
++ .p2align 4
++1:
++ /* 2-3 */
++ tbz count, 1, 1f
++ ldrh A_lw, [src]
++ strh A_lw, [dstin]
++ ldrh A_lw, [srcend, -2]
++ strh A_lw, [dstend, -2]
++ ret
++ .p2align 4
++1:
++ /* 0-1 */
++ tbz count, 0, 1f
++ ldrb A_lw, [src]
++ strb A_lw, [dstin]
++1:
++ ret
++
++ /* Align SRC to 16 bytes and copy; that way at least one of the
++ accesses is aligned throughout the copy sequence.
++
++ The count is off by 0 to 15 bytes, but this is OK because we trim
++ off the last 64 bytes to copy off from the end. Due to this the
++ loop never runs out of bounds. */
++ .p2align 6
++L(copy_long):
++ sub count, count, 64 + 16
++ and tmp1, src, 15
++ bic src, src, 15
++ sub dst, dstin, tmp1
++ add count, count, tmp1
++
++L(loop64):
++ ldp A_l, A_h, [src, 16]!
++ stnp A_l, A_h, [dst, 16]
++ ldp A_l, A_h, [src, 16]!
++ subs count, count, 64
++ stnp A_l, A_h, [dst, 32]
++ ldp A_l, A_h, [src, 16]!
++ stnp A_l, A_h, [dst, 48]
++ ldp A_l, A_h, [src, 16]!
++ stnp A_l, A_h, [dst, 64]
++ add dst, dst, 64
++ b.hi L(loop64)
++
++ /* Write the last full set of 64 bytes. The remainder is at most 64
++ bytes, so it is safe to always copy 64 bytes from the end even if
++ there is just 1 byte left. */
++L(last64):
++ ldp A_l, A_h, [srcend, -64]
++ stnp A_l, A_h, [dstend, -64]
++ ldp A_l, A_h, [srcend, -48]
++ stnp A_l, A_h, [dstend, -48]
++ ldp A_l, A_h, [srcend, -32]
++ stnp A_l, A_h, [dstend, -32]
++ ldp A_l, A_h, [srcend, -16]
++ stnp A_l, A_h, [dstend, -16]
++ ret
++
++END (__memcpy_falkor)
++libc_hidden_builtin_def (__memcpy_falkor)
++#endif
+diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
+index 34c6b29bd5..016f03ee50 100644
+--- a/sysdeps/aarch64/multiarch/memmove.c
++++ b/sysdeps/aarch64/multiarch/memmove.c
+@@ -30,9 +30,14 @@ extern __typeof (__redirect_memmove) __libc_memmove;
+
+ extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden;
+ extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden;
++extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden;
+
+ libc_ifunc (__libc_memmove,
+- IS_THUNDERX (midr) ? __memmove_thunderx : __memmove_generic);
++ (IS_THUNDERX (midr)
++ ? __memmove_thunderx
++ : (IS_FALKOR (midr)
++ ? __memmove_falkor
++ : __memmove_generic)));
+
+ # undef memmove
+ strong_alias (__libc_memmove, memmove);
+diff --git a/sysdeps/aarch64/multiarch/memmove_falkor.S b/sysdeps/aarch64/multiarch/memmove_falkor.S
+new file mode 100644
+index 0000000000..3a4e6a2a8e
+--- /dev/null
++++ b/sysdeps/aarch64/multiarch/memmove_falkor.S
+@@ -0,0 +1,232 @@
++/* 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/>. */
++
++#include <sysdep.h>
++
++/* Assumptions: ARMv8-a, AArch64, falkor, unaligned accesses. */
++
++#define dstin x0
++#define src x1
++#define count x2
++#define dstlen x3
++#define dst x3
++#define srcend x4
++#define dstend x5
++#define A_l x6
+#define A_lw w6
+#define A_h x7
+#define A_hw w7
@@ -19811,19 +21354,20 @@ index 0000000000..bdda1f197e
+# define __PTHREAD_MUTEX_LIST_OFFSET 20
+#endif
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
-index 9d6a2de870..dbe6a36c57 100644
+index 9d6a2de870..b1fe960d00 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
-@@ -50,7 +50,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
+@@ -50,7 +50,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
bits/siginfo-arch.h bits/siginfo-consts-arch.h
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
- tst-quota tst-sync_file_range test-errno-linux
-+ tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max
++ tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
++ test-errno-linux
# Generate the list of SYS_* macros for the system calls (__NR_* macros).
-@@ -120,7 +120,11 @@ ifndef no_deps
+@@ -120,7 +121,11 @@ ifndef no_deps
-include $(objpfx)bits/syscall.d
endif
generated += bits/syscall.h bits/syscall.d
@@ -19836,7 +21380,7 @@ index 9d6a2de870..dbe6a36c57 100644
ifeq ($(subdir),time)
sysdep_headers += sys/timex.h bits/timex.h
-@@ -162,7 +166,7 @@ endif
+@@ -162,7 +167,7 @@ endif
ifeq ($(subdir),posix)
sysdep_headers += bits/initspin.h
@@ -20707,17 +22251,147 @@ index 094e05124b..0000000000
-#endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h
new file mode 100644
-index 0000000000..094e05124b
+index 0000000000..094e05124b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h
+@@ -0,0 +1,26 @@
++/* Properties of long double type. SPARC version.
++ Copyright (C) 2016-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 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 <bits/wordsize.h>
++
++#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32
++# define __LONG_DOUBLE_MATH_OPTIONAL 1
++# ifndef __LONG_DOUBLE_128__
++# define __NO_LONG_DOUBLE_MATH 1
++# endif
++#endif
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
+deleted file mode 100644
+index 82a9a296a7..0000000000
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
++++ /dev/null
+@@ -1 +0,0 @@
+-#include <sysdeps/unix/sysv/linux/i386/glob64.c>
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h
+new file mode 100644
+index 0000000000..094e05124b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h
+@@ -0,0 +1,26 @@
++/* Properties of long double type. SPARC version.
++ Copyright (C) 2016-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 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 <bits/wordsize.h>
++
++#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32
++# define __LONG_DOUBLE_MATH_OPTIONAL 1
++# ifndef __LONG_DOUBLE_128__
++# define __NO_LONG_DOUBLE_MATH 1
++# endif
++#endif
+diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
+index c56f894a82..7d23df84d2 100644
+--- a/sysdeps/unix/sysv/linux/spawni.c
++++ b/sysdeps/unix/sysv/linux/spawni.c
+@@ -17,7 +17,6 @@
+ <http://www.gnu.org/licenses/>. */
+
+ #include <spawn.h>
+-#include <assert.h>
+ #include <fcntl.h>
+ #include <paths.h>
+ #include <string.h>
+@@ -268,7 +267,6 @@ __spawni_child (void *arguments)
+ __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK)
+ ? &attr->__ss : &args->oldmask, 0);
+
+- args->err = 0;
+ args->exec (args->file, args->argv, args->envp);
+
+ /* This is compatibility function required to enable posix_spawn run
+@@ -339,7 +337,7 @@ __spawnix (pid_t * pid, const char *file,
+
+ /* Child must set args.err to something non-negative - we rely on
+ the parent and child sharing VM. */
+- args.err = -1;
++ args.err = 0;
+ args.file = file;
+ args.exec = exec;
+ args.fa = file_actions;
+@@ -362,12 +360,26 @@ __spawnix (pid_t * pid, const char *file,
+ new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
+ CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
+
++ /* It needs to collect the case where the auxiliary process was created
++ but failed to execute the file (due either any preparation step or
++ for execve itself). */
+ if (new_pid > 0)
+ {
++ /* Also, it handles the unlikely case where the auxiliary process was
++ terminated before calling execve as if it was successfully. The
++ args.err is set to 0 as default and changed to a positive value
++ only in case of failure, so in case of premature termination
++ due a signal args.err will remain zeroed and it will be up to
++ caller to actually collect it. */
+ ec = args.err;
+- assert (ec >= 0);
+- if (ec != 0)
+- __waitpid (new_pid, NULL, 0);
++ if (ec > 0)
++ /* There still an unlikely case where the child is cancelled after
++ setting args.err, due to a positive error value. Also there is
++ possible pid reuse race (where the kernel allocated the same pid
++ to an unrelated process). Unfortunately due synchronization
++ issues where the kernel might not have the process collected
++ the waitpid below can not use WNOHANG. */
++ __waitpid (new_pid, NULL, 0);
+ }
+ else
+ ec = -new_pid;
+diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c
+new file mode 100644
+index 0000000000..1240b846e6
--- /dev/null
-+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h
-@@ -0,0 +1,26 @@
-+/* Properties of long double type. SPARC version.
-+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
++++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c
+@@ -0,0 +1,27 @@
++/* Check IOV_MAX definition: Helper function to capture UAPI header value.
++ 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 published by the Free Software Foundation; either
++ 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,
@@ -20729,191 +22403,930 @@ index 0000000000..094e05124b
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
-+#include <bits/wordsize.h>
++/* Use a separate function to avoid header compatibility issues. */
+
-+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32
-+# define __LONG_DOUBLE_MATH_OPTIONAL 1
-+# ifndef __LONG_DOUBLE_128__
-+# define __NO_LONG_DOUBLE_MATH 1
-+# endif
-+#endif
-diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
-deleted file mode 100644
-index 82a9a296a7..0000000000
---- a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
-+++ /dev/null
-@@ -1 +0,0 @@
--#include <sysdeps/unix/sysv/linux/i386/glob64.c>
-diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h
++#include <linux/uio.h>
++
++long
++uio_maxiov_value (void)
++{
++ return UIO_MAXIOV;
++}
+diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c
new file mode 100644
-index 0000000000..094e05124b
+index 0000000000..dfdf3da484
--- /dev/null
-+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h
-@@ -0,0 +1,26 @@
-+/* Properties of long double type. SPARC version.
-+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
++++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c
+@@ -0,0 +1,40 @@
++/* Check IOV_MAX definition for consistency (bug 22321).
++ 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 published by the Free Software Foundation; either
++ 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.
++ 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/>. */
++
++/* Defined in tst-sysconf-iov_max-uapi.c. */
++long uio_maxiov_value (void);
++
++
++#include <limits.h>
++#include <support/check.h>
++#include <sys/uio.h>
++#include <unistd.h>
++
++static int
++do_test (void)
++{
++ TEST_VERIFY (_XOPEN_IOV_MAX == 16); /* Value required by POSIX. */
++ TEST_VERIFY (uio_maxiov_value () >= _XOPEN_IOV_MAX);
++ TEST_VERIFY (IOV_MAX == uio_maxiov_value ());
++ TEST_VERIFY (UIO_MAXIOV == uio_maxiov_value ());
++ TEST_VERIFY (sysconf (_SC_UIO_MAXIOV) == uio_maxiov_value ());
++ TEST_VERIFY (sysconf (_SC_IOV_MAX) == uio_maxiov_value ());
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/tst-ttyname.c b/sysdeps/unix/sysv/linux/tst-ttyname.c
+new file mode 100644
+index 0000000000..0fdf1a8ccb
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-ttyname.c
+@@ -0,0 +1,570 @@
++/* 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; see the file COPYING.LIB. If
++ not, see <http://www.gnu.org/licenses/>. */
++
++#include <dirent.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <sched.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/mount.h>
++#include <sys/prctl.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <unistd.h>
++
++#include <support/check.h>
++#include <support/namespace.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/test-driver.h>
++#include <support/xunistd.h>
++
++/* generic utilities */
++
++#define VERIFY(expr) \
++ do { \
++ if (!(expr)) \
++ { \
++ printf ("error: %s:%d: %s: %m\n", \
++ __FILE__, __LINE__, #expr); \
++ exit (1); \
++ } \
++ } while (0)
++
++static void
++touch (const char *path, mode_t mode)
++{
++ xclose (xopen (path, O_WRONLY|O_CREAT|O_NOCTTY, mode));
++}
++
++static size_t
++trim_prefix (char *str, size_t str_len, const char *prefix)
++{
++ size_t prefix_len = strlen (prefix);
++ if (str_len > prefix_len && memcmp (str, prefix, prefix_len) == 0)
++ {
++ memmove (str, str + prefix_len, str_len - prefix_len);
++ return str_len - prefix_len;
++ }
++ return str_len;
++}
++
++/* returns a pointer to static storage */
++static char *
++proc_fd_readlink (const char *linkname)
++{
++ static char target[PATH_MAX+1];
++ ssize_t target_len = readlink (linkname, target, PATH_MAX);
++ VERIFY (target_len > 0);
++ target_len = trim_prefix (target, target_len, "(unreachable)");
++ target[target_len] = '\0';
++ return target;
++}
++
++/* plain ttyname runner */
++
++struct result
++{
++ const char *name;
++ int err;
++};
++
++/* strings in result structure are in static storage */
++static struct result
++run_ttyname (int fd)
++{
++ struct result ret;
++ errno = 0;
++ ret.name = ttyname (fd);
++ ret.err = errno;
++ return ret;
++}
++
++static bool
++eq_ttyname (struct result actual, struct result expected)
++{
++ char *actual_name, *expected_name;
++
++ if ((actual.err == expected.err) &&
++ (!actual.name == !expected.name) &&
++ (actual.name ? strcmp (actual.name, expected.name) == 0 : true))
++ {
++ if (expected.name)
++ expected_name = xasprintf ("\"%s\"", expected.name);
++ else
++ expected_name = xstrdup ("NULL");
++
++ printf ("info: ttyname: PASS {name=%s, errno=%d}\n",
++ expected_name, expected.err);
++
++ free (expected_name);
++ return true;
++ }
++
++ if (actual.name)
++ actual_name = xasprintf ("\"%s\"", actual.name);
++ else
++ actual_name = xstrdup ("NULL");
++
++ if (expected.name)
++ expected_name = xasprintf ("\"%s\"", expected.name);
++ else
++ expected_name = xstrdup ("NULL");
++
++ printf ("error: ttyname: actual {name=%s, errno=%d} != expected {name=%s, errno=%d}\n",
++ actual_name, actual.err,
++ expected_name, expected.err);
++
++ free (actual_name);
++ free (expected_name);
++ return false;
++}
++
++/* ttyname_r runner */
++
++struct result_r
++{
++ const char *name;
++ int ret;
++ int err;
++};
++
++/* strings in result structure are in static storage */
++static struct result_r
++run_ttyname_r (int fd)
++{
++ static char buf[TTY_NAME_MAX];
++
++ struct result_r ret;
++ errno = 0;
++ ret.ret = ttyname_r (fd, buf, TTY_NAME_MAX);
++ ret.err = errno;
++ if (ret.ret == 0)
++ ret.name = buf;
++ else
++ ret.name = NULL;
++ return ret;
++}
++
++static bool
++eq_ttyname_r (struct result_r actual, struct result_r expected)
++{
++ char *actual_name, *expected_name;
++
++ if ((actual.err == expected.err) &&
++ (actual.ret == expected.ret) &&
++ (!actual.name == !expected.name) &&
++ (actual.name ? strcmp (actual.name, expected.name) == 0 : true))
++ {
++ if (expected.name)
++ expected_name = xasprintf ("\"%s\"", expected.name);
++ else
++ expected_name = xstrdup ("NULL");
++
++ printf ("info: ttyname_r: PASS {name=%s, ret=%d, errno=%d}\n",
++ expected_name, expected.ret, expected.err);
++
++ free (expected_name);
++ return true;
++ }
++
++ if (actual.name)
++ actual_name = xasprintf ("\"%s\"", actual.name);
++ else
++ actual_name = xstrdup ("NULL");
++
++ if (expected.name)
++ expected_name = xasprintf ("\"%s\"", expected.name);
++ else
++ expected_name = xstrdup ("NULL");
++
++ printf ("error: ttyname_r: actual {name=%s, ret=%d, errno=%d} != expected {name=%s, ret=%d, errno=%d}\n",
++ actual_name, actual.ret, actual.err,
++ expected_name, expected.ret, expected.err);
++
++ free (actual_name);
++ free (expected_name);
++ return false;
++}
++
++/* combined runner */
++
++static bool
++doit (int fd, const char *testname, struct result_r expected_r)
++{
++ struct result expected = {.name=expected_r.name, .err=expected_r.ret};
++ bool ret = true;
++
++ printf ("info: testcase: %s\n", testname);
++
++ if (!eq_ttyname (run_ttyname (fd), expected))
++ ret = false;
++ if (!eq_ttyname_r (run_ttyname_r (fd), expected_r))
++ ret = false;
++
++ if (!ret)
++ support_record_failure ();
++
++ return ret;
++}
++
++/* chroot setup */
++
++static char *chrootdir;
++
++static void
++prepare (int argc, char **argv)
++{
++ chrootdir = xasprintf ("%s/tst-ttyname-XXXXXX", test_dir);
++ if (mkdtemp (chrootdir) == NULL)
++ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chrootdir);
++ add_temp_file (chrootdir);
++}
++#define PREPARE prepare
++
++/* These chroot setup functions put the TTY at at "/console" (where it
++ won't be found by ttyname), and create "/dev/console" as an
++ ordinary file. This way, it's easier to write test-cases that
++ expect ttyname to fail; test-cases that expect it to succeed need
++ to explicitly remount it at "/dev/console". */
++
++static int
++do_in_chroot_1 (int (*cb)(const char *, int))
++{
++ printf ("info: entering chroot 1\n");
++
++ /* Open the PTS that we'll be testing on. */
++ int master;
++ char *slavename;
++ VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0);
++ VERIFY ((slavename = ptsname (master)));
++ VERIFY (unlockpt (master) == 0);
++ if (strncmp (slavename, "/dev/pts/", 9) != 0)
++ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s",
++ slavename);
++ int slave = xopen (slavename, O_RDWR, 0);
++ if (!doit (slave, "basic smoketest",
++ (struct result_r){.name=slavename, .ret=0, .err=0}))
++ return 1;
++
++ pid_t pid = xfork ();
++ if (pid == 0)
++ {
++ xclose (master);
+
-+ 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/>. */
++ if (!support_enter_mount_namespace ())
++ FAIL_UNSUPPORTED ("could not enter new mount namespace");
+
-+#include <bits/wordsize.h>
++ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0);
++ VERIFY (chdir (chrootdir) == 0);
+
-+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32
-+# define __LONG_DOUBLE_MATH_OPTIONAL 1
-+# ifndef __LONG_DOUBLE_128__
-+# define __NO_LONG_DOUBLE_MATH 1
-+# endif
-+#endif
-diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
-index c56f894a82..7d23df84d2 100644
---- a/sysdeps/unix/sysv/linux/spawni.c
-+++ b/sysdeps/unix/sysv/linux/spawni.c
-@@ -17,7 +17,6 @@
- <http://www.gnu.org/licenses/>. */
-
- #include <spawn.h>
--#include <assert.h>
- #include <fcntl.h>
- #include <paths.h>
- #include <string.h>
-@@ -268,7 +267,6 @@ __spawni_child (void *arguments)
- __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK)
- ? &attr->__ss : &args->oldmask, 0);
-
-- args->err = 0;
- args->exec (args->file, args->argv, args->envp);
-
- /* This is compatibility function required to enable posix_spawn run
-@@ -339,7 +337,7 @@ __spawnix (pid_t * pid, const char *file,
-
- /* Child must set args.err to something non-negative - we rely on
- the parent and child sharing VM. */
-- args.err = -1;
-+ args.err = 0;
- args.file = file;
- args.exec = exec;
- args.fa = file_actions;
-@@ -362,12 +360,26 @@ __spawnix (pid_t * pid, const char *file,
- new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
- CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
-
-+ /* It needs to collect the case where the auxiliary process was created
-+ but failed to execute the file (due either any preparation step or
-+ for execve itself). */
- if (new_pid > 0)
- {
-+ /* Also, it handles the unlikely case where the auxiliary process was
-+ terminated before calling execve as if it was successfully. The
-+ args.err is set to 0 as default and changed to a positive value
-+ only in case of failure, so in case of premature termination
-+ due a signal args.err will remain zeroed and it will be up to
-+ caller to actually collect it. */
- ec = args.err;
-- assert (ec >= 0);
-- if (ec != 0)
-- __waitpid (new_pid, NULL, 0);
-+ if (ec > 0)
-+ /* There still an unlikely case where the child is cancelled after
-+ setting args.err, due to a positive error value. Also there is
-+ possible pid reuse race (where the kernel allocated the same pid
-+ to an unrelated process). Unfortunately due synchronization
-+ issues where the kernel might not have the process collected
-+ the waitpid below can not use WNOHANG. */
-+ __waitpid (new_pid, NULL, 0);
- }
- else
- ec = -new_pid;
-diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c
-new file mode 100644
-index 0000000000..1240b846e6
---- /dev/null
-+++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c
-@@ -0,0 +1,27 @@
-+/* Check IOV_MAX definition: Helper function to capture UAPI header value.
-+ Copyright (C) 2017 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
++ xmkdir ("proc", 0755);
++ xmkdir ("dev", 0755);
++ xmkdir ("dev/pts", 0755);
+
-+ 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.
++ VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0);
++ VERIFY (mount ("devpts", "dev/pts", "devpts",
++ MS_NOSUID|MS_NOEXEC,
++ "newinstance,ptmxmode=0666,mode=620") == 0);
++ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0);
+
-+ 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.
++ touch ("console", 0);
++ touch ("dev/console", 0);
++ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
+
-+ 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/>. */
++ xchroot (".");
+
-+/* Use a separate function to avoid header compatibility issues. */
++ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
++ char *target = proc_fd_readlink (linkname);
++ VERIFY (strcmp (target, slavename) == 0);
++ free (linkname);
+
-+#include <linux/uio.h>
++ _exit (cb (slavename, slave));
++ }
++ int status;
++ xwaitpid (pid, &status, 0);
++ VERIFY (WIFEXITED (status));
++ xclose (master);
++ xclose (slave);
++ return WEXITSTATUS (status);
++}
+
-+long
-+uio_maxiov_value (void)
++static int
++do_in_chroot_2 (int (*cb)(const char *, int))
+{
-+ return UIO_MAXIOV;
++ printf ("info: entering chroot 2\n");
++
++ int pid_pipe[2];
++ xpipe (pid_pipe);
++ int exit_pipe[2];
++ xpipe (exit_pipe);
++
++ /* Open the PTS that we'll be testing on. */
++ int master;
++ char *slavename;
++ VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0);
++ VERIFY ((slavename = ptsname (master)));
++ VERIFY (unlockpt (master) == 0);
++ if (strncmp (slavename, "/dev/pts/", 9) != 0)
++ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s",
++ slavename);
++ /* wait until in a new mount ns to open the slave */
++
++ /* enable `wait`ing on grandchildren */
++ VERIFY (prctl (PR_SET_CHILD_SUBREAPER, 1) == 0);
++
++ pid_t pid = xfork (); /* outer child */
++ if (pid == 0)
++ {
++ xclose (master);
++ xclose (pid_pipe[0]);
++ xclose (exit_pipe[1]);
++
++ if (!support_enter_mount_namespace ())
++ FAIL_UNSUPPORTED ("could not enter new mount namespace");
++
++ int slave = xopen (slavename, O_RDWR, 0);
++ if (!doit (slave, "basic smoketest",
++ (struct result_r){.name=slavename, .ret=0, .err=0}))
++ _exit (1);
++
++ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0);
++ VERIFY (chdir (chrootdir) == 0);
++
++ xmkdir ("proc", 0755);
++ xmkdir ("dev", 0755);
++ xmkdir ("dev/pts", 0755);
++
++ VERIFY (mount ("devpts", "dev/pts", "devpts",
++ MS_NOSUID|MS_NOEXEC,
++ "newinstance,ptmxmode=0666,mode=620") == 0);
++ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0);
++
++ touch ("console", 0);
++ touch ("dev/console", 0);
++ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
++
++ xchroot (".");
++
++ if (unshare (CLONE_NEWNS | CLONE_NEWPID) < 0)
++ FAIL_UNSUPPORTED ("could not enter new PID namespace");
++ pid = xfork (); /* inner child */
++ if (pid == 0)
++ {
++ xclose (pid_pipe[1]);
++
++ /* wait until the outer child has exited */
++ char c;
++ VERIFY (read (exit_pipe[0], &c, 1) == 0);
++ xclose (exit_pipe[0]);
++
++ VERIFY (mount ("proc", "/proc", "proc",
++ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) == 0);
++
++ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
++ char *target = proc_fd_readlink (linkname);
++ VERIFY (strcmp (target, strrchr (slavename, '/')) == 0);
++ free (linkname);
++
++ _exit (cb (slavename, slave));
++ }
++ xwrite (pid_pipe[1], &pid, sizeof pid);
++ _exit (0);
++ }
++ xclose (pid_pipe[1]);
++ xclose (exit_pipe[0]);
++ xclose (exit_pipe[1]);
++
++ /* wait for the outer child */
++ int status;
++ xwaitpid (pid, &status, 0);
++ VERIFY (WIFEXITED (status));
++ int ret = WEXITSTATUS (status);
++ if (ret != 0)
++ return ret;
++
++ /* set 'pid' to the inner child */
++ VERIFY (read (pid_pipe[0], &pid, sizeof pid) == sizeof pid);
++ xclose (pid_pipe[0]);
++
++ /* wait for the inner child */
++ xwaitpid (pid, &status, 0);
++ VERIFY (WIFEXITED (status));
++ xclose (master);
++ return WEXITSTATUS (status);
+}
-diff --git a/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c
-new file mode 100644
-index 0000000000..dfdf3da484
---- /dev/null
-+++ b/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c
-@@ -0,0 +1,40 @@
-+/* Check IOV_MAX definition for consistency (bug 22321).
-+ 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.
++/* main test */
+
-+ 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.
++static int
++run_chroot_tests (const char *slavename, int slave)
++{
++ struct stat st;
++ bool ok = true;
+
-+ 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/>. */
++ /* There are 3 groups of tests here. The first group fairly
++ generically does things known to mess up ttyname, and verifies
++ that ttyname copes correctly. The remaining groups are
++ increasingly convoluted, as we target specific parts of ttyname
++ to try to confuse. */
+
-+/* Defined in tst-sysconf-iov_max-uapi.c. */
-+long uio_maxiov_value (void);
++ /* Basic tests that it doesn't get confused by multiple devpts
++ instances. */
++ {
++ VERIFY (stat (slavename, &st) < 0); /* sanity check */
++ if (!doit (slave, "no conflict, no match",
++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
++ ok = false;
++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
++ if (!doit (slave, "no conflict, console",
++ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
++ ok = false;
++ VERIFY (umount ("/dev/console") == 0);
++
++ /* keep creating PTYs until we we get a name collision */
++ while (stat (slavename, &st) < 0)
++ posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK);
++ VERIFY (stat (slavename, &st) == 0);
++
++ if (!doit (slave, "conflict, no match",
++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
++ ok = false;
++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
++ if (!doit (slave, "conflict, console",
++ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
++ ok = false;
++ VERIFY (umount ("/dev/console") == 0);
++ }
+
++ /* The first tests kinda assumed that they hit certain code-paths
++ based on assuming that the readlink target is 'slavename', but
++ that's not quite always true. They're still a good preliminary
++ sanity check, so keep them, but let's add tests that make sure
++ that those code-paths are hit by doing a readlink ourself. */
++ {
++ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
++ char *target = proc_fd_readlink (linkname);
++ free (linkname);
++ /* Depeding on how we set up the chroot, the kernel may or may not
++ trim the leading path to the target (it may give us "/6",
++ instead of "/dev/pts/6"). We test it both ways (do_in_chroot_1
++ and do_in_chroot_2). This test group relies on the target
++ existing, so guarantee that it does exist by creating it if
++ necessary. */
++ if (stat (target, &st) < 0)
++ {
++ VERIFY (errno == ENOENT);
++ touch (target, 0);
++ }
+
-+#include <limits.h>
-+#include <support/check.h>
-+#include <sys/uio.h>
-+#include <unistd.h>
++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
++ VERIFY (mount ("/console", target, NULL, MS_BIND, NULL) == 0);
++ if (!doit (slave, "with readlink target",
++ (struct result_r){.name=target, .ret=0, .err=0}))
++ ok = false;
++ VERIFY (umount (target) == 0);
++ VERIFY (umount ("/dev/console") == 0);
++
++ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
++ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0);
++ if (!doit (slave, "with readlink trap; fallback",
++ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
++ ok = false;
++ VERIFY (umount (target) == 0);
++ VERIFY (umount ("/dev/console") == 0);
++
++ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0);
++ if (!doit (slave, "with readlink trap; no fallback",
++ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
++ ok = false;
++ VERIFY (umount (target) == 0);
++ }
++
++ /* This test makes sure that everything still works OK if readdir
++ finds a pseudo-match before and/or after the actual match. Now,
++ to do that, we need to control that readdir finds the
++ pseudo-matches before and after the actual match; and there's no
++ good way to control that order in absence of whitebox testing.
++ So, just create 3 files, then use opendir/readdir to see what
++ order they are in, and assign meaning based on that order, not by
++ name; assigning the first to be a pseudo-match, the second to be
++ the actual match, and the third to be a pseudo-match. This
++ assumes that (on tmpfs) ordering within the directory is stable
++ in the absence of modification, which seems reasonably safe. */
++ {
++ /* since we're testing the fallback search, disable the readlink
++ happy-path */
++ VERIFY (umount2 ("/proc", MNT_DETACH) == 0);
++
++ touch ("/dev/console1", 0);
++ touch ("/dev/console2", 0);
++ touch ("/dev/console3", 0);
++
++ char *c[3];
++ int ci = 0;
++ DIR *dirstream = opendir ("/dev");
++ VERIFY (dirstream != NULL);
++ struct dirent *d;
++ while ((d = readdir (dirstream)) != NULL && ci < 3)
++ {
++ if (strcmp (d->d_name, "console1") &&
++ strcmp (d->d_name, "console2") &&
++ strcmp (d->d_name, "console3") )
++ continue;
++ c[ci++] = xasprintf ("/dev/%s", d->d_name);
++ }
++ VERIFY (ci == 3);
++ VERIFY (closedir (dirstream) == 0);
++
++ VERIFY (mount (slavename, c[0], NULL, MS_BIND, NULL) == 0);
++ VERIFY (mount ("/console", c[1], NULL, MS_BIND, NULL) == 0);
++ VERIFY (mount (slavename, c[2], NULL, MS_BIND, NULL) == 0);
++ VERIFY (umount2 ("/dev/pts", MNT_DETACH) == 0);
++ if (!doit (slave, "with search-path trap",
++ (struct result_r){.name=c[1], .ret=0, .err=0}))
++ ok = false;
++ for (int i = 0; i < 3; i++)
++ {
++ VERIFY (umount (c[i]) == 0);
++ VERIFY (unlink (c[i]) == 0);
++ free (c[i]);
++ }
++ }
++
++ return ok ? 0 : 1;
++}
+
+static int
+do_test (void)
+{
-+ TEST_VERIFY (_XOPEN_IOV_MAX == 16); /* Value required by POSIX. */
-+ TEST_VERIFY (uio_maxiov_value () >= _XOPEN_IOV_MAX);
-+ TEST_VERIFY (IOV_MAX == uio_maxiov_value ());
-+ TEST_VERIFY (UIO_MAXIOV == uio_maxiov_value ());
-+ TEST_VERIFY (sysconf (_SC_UIO_MAXIOV) == uio_maxiov_value ());
-+ TEST_VERIFY (sysconf (_SC_IOV_MAX) == uio_maxiov_value ());
-+ return 0;
++ support_become_root ();
++
++ int ret1 = do_in_chroot_1 (run_chroot_tests);
++ if (ret1 == EXIT_UNSUPPORTED)
++ return ret1;
++
++ int ret2 = do_in_chroot_2 (run_chroot_tests);
++ if (ret2 == EXIT_UNSUPPORTED)
++ return ret2;
++
++ return ret1 | ret2;
+}
+
+#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c
+index 5909cb765f..f4c955f25b 100644
+--- a/sysdeps/unix/sysv/linux/ttyname.c
++++ b/sysdeps/unix/sysv/linux/ttyname.c
+@@ -35,16 +35,14 @@
+ char *__ttyname;
+ #endif
+
+-static char *getttyname (const char *dev, dev_t mydev,
+- ino64_t myino, int save, int *dostat)
+- internal_function;
+-
++static char *getttyname (const char *dev, const struct stat64 *mytty,
++ int save, int *dostat);
+
+ libc_freeres_ptr (static char *getttyname_name);
+
+ static char *
+-internal_function attribute_compat_text_section
+-getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
++attribute_compat_text_section
++getttyname (const char *dev, const struct stat64 *mytty, int save, int *dostat)
+ {
+ static size_t namelen;
+ struct stat64 st;
+@@ -65,7 +63,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
+ *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';
+
+ while ((d = __readdir64 (dirstream)) != NULL)
+- if ((d->d_fileno == myino || *dostat)
++ if ((d->d_fileno == mytty->st_ino || *dostat)
+ && strcmp (d->d_name, "stdin")
+ && strcmp (d->d_name, "stdout")
+ && strcmp (d->d_name, "stderr"))
+@@ -87,12 +85,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
+ }
+ memcpy (&getttyname_name[devlen], d->d_name, dlen);
+ if (__xstat64 (_STAT_VER, getttyname_name, &st) == 0
+-#ifdef _STATBUF_ST_RDEV
+- && S_ISCHR (st.st_mode) && st.st_rdev == mydev
+-#else
+- && d->d_fileno == myino && st.st_dev == mydev
+-#endif
+- )
++ && is_mytty (mytty, &st))
+ {
+ (void) __closedir (dirstream);
+ #if 0
+@@ -122,6 +115,7 @@ ttyname (int fd)
+ char procname[30];
+ struct stat64 st, st1;
+ int dostat = 0;
++ int doispty = 0;
+ char *name;
+ int save = errno;
+ struct termios term;
+@@ -169,30 +163,15 @@ ttyname (int fd)
+ /* Verify readlink result, fall back on iterating through devices. */
+ if (ttyname_buf[0] == '/'
+ && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
+-#ifdef _STATBUF_ST_RDEV
+- && S_ISCHR (st1.st_mode)
+- && st1.st_rdev == st.st_rdev
+-#endif
+- && st1.st_ino == st.st_ino
+- && st1.st_dev == st.st_dev)
++ && is_mytty (&st, &st1))
+ return ttyname_buf;
+
+- /* If the link doesn't exist, then it points to a device in another
+- namespace. */
+- if (is_pty (&st))
+- {
+- __set_errno (ENODEV);
+- return NULL;
+- }
++ doispty = 1;
+ }
+
+ if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
+ {
+-#ifdef _STATBUF_ST_RDEV
+- name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
+-#else
+- name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
+-#endif
++ name = getttyname ("/dev/pts", &st, save, &dostat);
+ }
+ else
+ {
+@@ -202,21 +181,23 @@ ttyname (int fd)
+
+ if (!name && dostat != -1)
+ {
+-#ifdef _STATBUF_ST_RDEV
+- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
+-#else
+- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
+-#endif
++ name = getttyname ("/dev", &st, save, &dostat);
+ }
+
+ if (!name && dostat != -1)
+ {
+ dostat = 1;
+-#ifdef _STATBUF_ST_RDEV
+- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
+-#else
+- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
+-#endif
++ name = getttyname ("/dev", &st, save, &dostat);
++ }
++
++ if (!name && doispty && is_pty (&st))
++ {
++ /* We failed to figure out the TTY's name, but we can at least
++ signal that we did verify that it really is a PTY slave.
++ This happens when we have inherited the file descriptor from
++ a different mount namespace. */
++ __set_errno (ENODEV);
++ return NULL;
+ }
+
+ return name;
+diff --git a/sysdeps/unix/sysv/linux/ttyname.h b/sysdeps/unix/sysv/linux/ttyname.h
+index 2e415e4e9c..48181330a9 100644
+--- a/sysdeps/unix/sysv/linux/ttyname.h
++++ b/sysdeps/unix/sysv/linux/ttyname.h
+@@ -16,13 +16,15 @@
+ not, see <http://www.gnu.org/licenses/>. */
+
+ #include <unistd.h>
++#include <stdbool.h>
+ #include <sys/sysmacros.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+
+ /* Return true if this is a UNIX98 pty device, as defined in
+- linux/Documentation/devices.txt. */
+-static inline int
++ linux/Documentation/devices.txt (on linux < 4.10) or
++ linux/Documentation/admin-guide/devices.txt (on linux >= 4.10). */
++static inline bool
+ is_pty (struct stat64 *sb)
+ {
+ #ifdef _STATBUF_ST_RDEV
+@@ -32,3 +34,15 @@ is_pty (struct stat64 *sb)
+ return false;
+ #endif
+ }
++
++static inline bool
++is_mytty (const struct stat64 *mytty, const struct stat64 *maybe)
++{
++ return (maybe->st_ino == mytty->st_ino
++ && maybe->st_dev == mytty->st_dev
++#ifdef _STATBUF_ST_RDEV
++ && S_ISCHR (maybe->st_mode)
++ && maybe->st_rdev == mytty->st_rdev
++#endif
++ );
++}
+diff --git a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c
+index dc863526ba..00eefc2c5c 100644
+--- a/sysdeps/unix/sysv/linux/ttyname_r.c
++++ b/sysdeps/unix/sysv/linux/ttyname_r.c
+@@ -31,12 +31,12 @@
+ #include "ttyname.h"
+
+ static int getttyname_r (char *buf, size_t buflen,
+- dev_t mydev, ino64_t myino, int save,
+- int *dostat) internal_function;
++ const struct stat64 *mytty, int save,
++ int *dostat);
+
+ static int
+-internal_function attribute_compat_text_section
+-getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
++attribute_compat_text_section
++getttyname_r (char *buf, size_t buflen, const struct stat64 *mytty,
+ int save, int *dostat)
+ {
+ struct stat64 st;
+@@ -52,7 +52,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
+ }
+
+ while ((d = __readdir64 (dirstream)) != NULL)
+- if ((d->d_fileno == myino || *dostat)
++ if ((d->d_fileno == mytty->st_ino || *dostat)
+ && strcmp (d->d_name, "stdin")
+ && strcmp (d->d_name, "stdout")
+ && strcmp (d->d_name, "stderr"))
+@@ -72,12 +72,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
+ cp[0] = '\0';
+
+ if (__xstat64 (_STAT_VER, buf, &st) == 0
+-#ifdef _STATBUF_ST_RDEV
+- && S_ISCHR (st.st_mode) && st.st_rdev == mydev
+-#else
+- && d->d_fileno == myino && st.st_dev == mydev
+-#endif
+- )
++ && is_mytty (mytty, &st))
+ {
+ (void) __closedir (dirstream);
+ __set_errno (save);
+@@ -100,6 +95,7 @@ __ttyname_r (int fd, char *buf, size_t buflen)
+ char procname[30];
+ struct stat64 st, st1;
+ int dostat = 0;
++ int doispty = 0;
+ int save = errno;
+
+ /* Test for the absolute minimal size. This makes life easier inside
+@@ -151,22 +147,10 @@ __ttyname_r (int fd, char *buf, size_t buflen)
+ /* Verify readlink result, fall back on iterating through devices. */
+ if (buf[0] == '/'
+ && __xstat64 (_STAT_VER, buf, &st1) == 0
+-#ifdef _STATBUF_ST_RDEV
+- && S_ISCHR (st1.st_mode)
+- && st1.st_rdev == st.st_rdev
+-#endif
+- && st1.st_ino == st.st_ino
+- && st1.st_dev == st.st_dev)
++ && is_mytty (&st, &st1))
+ return 0;
+
+- /* If the link doesn't exist, then it points to a device in another
+- * namespace.
+- */
+- if (is_pty (&st))
+- {
+- __set_errno (ENODEV);
+- return ENODEV;
+- }
++ doispty = 1;
+ }
+
+ /* Prepare the result buffer. */
+@@ -175,13 +159,8 @@ __ttyname_r (int fd, char *buf, size_t buflen)
+
+ if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
+ {
+-#ifdef _STATBUF_ST_RDEV
+- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
++ ret = getttyname_r (buf, buflen, &st, save,
+ &dostat);
+-#else
+- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
+- &dostat);
+-#endif
+ }
+ else
+ {
+@@ -193,26 +172,26 @@ __ttyname_r (int fd, char *buf, size_t buflen)
+ {
+ buf[sizeof ("/dev/") - 1] = '\0';
+ buflen += sizeof ("pts/") - 1;
+-#ifdef _STATBUF_ST_RDEV
+- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
+- &dostat);
+-#else
+- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
++ ret = getttyname_r (buf, buflen, &st, save,
+ &dostat);
+-#endif
+ }
+
+ if (ret && dostat != -1)
+ {
+ buf[sizeof ("/dev/") - 1] = '\0';
+ dostat = 1;
+-#ifdef _STATBUF_ST_RDEV
+- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
++ ret = getttyname_r (buf, buflen, &st,
+ save, &dostat);
+-#else
+- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
+- save, &dostat);
+-#endif
++ }
++
++ if (ret && doispty && is_pty (&st))
++ {
++ /* We failed to figure out the TTY's name, but we can at least
++ signal that we did verify that it really is a PTY slave.
++ This happens when we have inherited the file descriptor from
++ a different mount namespace. */
++ __set_errno (ENODEV);
++ return ENODEV;
+ }
+
+ return ret;
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/glob64.c b/sysdeps/unix/sysv/linux/wordsize-64/glob64.c
deleted file mode 100644
index eab7703d5c..0000000000
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-glibc/glibc.git
Reply to: