core/glibc-32/glibc-2.25-updates.patch
2018-01-05 23:19:25 +01:00

3080 lines
104 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/ChangeLog b/ChangeLog
index f140ee67de..73546da9e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,215 @@
+2017-06-14 Florian Weimer <fweimer@redhat.com>
+
+ * sysdeps/i386/i686/multiarch/strcspn-c.c: Add IS_IN (libc) guard.
+ * sysdeps/i386/i686/multiarch/varshift.c: Likewise.
+
+2017-03-07 Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+ [BZ #21209]
+ * elf/rtld.c (process_envvars): Ignore LD_HWCAP_MASK for
+ AT_SECURE processes.
+ * sysdeps/generic/unsecvars.h: Add LD_HWCAP_MASK.
+ * elf/tst-env-setuid.c (test_parent): Test LD_HWCAP_MASK.
+ (test_child): Likewise.
+ * elf/Makefile (tst-env-setuid-ENV): Add LD_HWCAP_MASK.
+
+2017-06-19 Florian Weimer <fweimer@redhat.com>
+
+ * elf/rtld.c (audit_list_string): New variable.
+ (audit_list): Update comment.
+ (struct audit_list_iter): Define.
+ (audit_list_iter_init, audit_list_iter_next): New function.
+ (dl_main): Use struct audit_list_iter to process audit modules.
+ (process_dl_audit): Call dso_name_valid_for_suid.
+ (process_envvars): Set audit_list_string instead of calling
+ process_dl_audit.
+
+2017-06-19 Florian Weimer <fweimer@redhat.com>
+
+ * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
+ (dso_name_valid_for_suid): New function.
+ (handle_ld_preload): Likewise.
+ (dl_main): Call it. Remove alloca.
+
+2017-06-19 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21624]
+ CVE-2017-1000366
+ * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for
+ __libc_enable_secure.
+
+2017-05-12 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21386]
+ * sysdeps/nptl/fork.c (__libc_fork): Remove assertions on the
+ parent PID. The assertion in the child is incorrect with PID
+ namespaces.
+
+2017-03-15 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/x86/fpu/test-math-vector-sincos.h (INIT_VEC_PTRS_LOOP):
+ Use a union when storing pointers.
+ (VECTOR_WRAPPER_fFF_2): Do not take address of integer vector and
+ cast result when passing to INIT_VEC_PTRS_LOOP.
+ (VECTOR_WRAPPER_fFF_3): Likewise.
+ (VECTOR_WRAPPER_fFF_4): Likewise.
+
+2017-05-01 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ# 21182]
+ * string/test-memchr.c (do_test): Add BZ#21182 checks for address
+ near end of a page.
+ * sysdeps/i386/i686/multiarch/memchr-sse2.S (__memchr): Fix
+ overflow calculation.
+
+2017-04-28 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #21396]
+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set
+ Prefer_No_AVX512 if AVX512ER isn't available.
+ * sysdeps/x86/cpu-features.h (bit_arch_Prefer_No_AVX512): New.
+ (index_arch_Prefer_No_AVX512): Likewise.
+ * sysdeps/x86_64/multiarch/memcpy.S (__new_memcpy): Don't use
+ AVX512 version if Prefer_No_AVX512 is set.
+ * sysdeps/x86_64/multiarch/memcpy_chk.S (__memcpy_chk):
+ Likewise.
+ * sysdeps/x86_64/multiarch/memmove.S (__libc_memmove): Likewise.
+ * sysdeps/x86_64/multiarch/memmove_chk.S (__memmove_chk):
+ Likewise.
+ * sysdeps/x86_64/multiarch/mempcpy.S (__mempcpy): Likewise.
+ * sysdeps/x86_64/multiarch/mempcpy_chk.S (__mempcpy_chk):
+ Likewise.
+ * sysdeps/x86_64/multiarch/memset.S (memset): Likewise.
+ * sysdeps/x86_64/multiarch/memset_chk.S (__memset_chk):
+ Likewise.
+
+2017-04-28 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set
+ Prefer_No_VZEROUPPER if AVX512ER is available.
+ * sysdeps/x86/cpu-features.h
+ (bit_cpu_AVX512PF): New.
+ (bit_cpu_AVX512ER): Likewise.
+ (bit_cpu_AVX512CD): Likewise.
+ (bit_cpu_AVX512BW): Likewise.
+ (bit_cpu_AVX512VL): Likewise.
+ (index_cpu_AVX512PF): Likewise.
+ (index_cpu_AVX512ER): Likewise.
+ (index_cpu_AVX512CD): Likewise.
+ (index_cpu_AVX512BW): Likewise.
+ (index_cpu_AVX512VL): Likewise.
+ (reg_AVX512PF): Likewise.
+ (reg_AVX512ER): Likewise.
+ (reg_AVX512CD): Likewise.
+ (reg_AVX512BW): Likewise.
+ (reg_AVX512VL): Likewise.
+
+2017-04-11 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ * posix/globtest.sh: Add cleanup routine on trap 0.
+
+2017-04-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #21258]
+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve_opt):
+ Define only if _dl_runtime_resolve is defined to
+ _dl_runtime_resolve_sse_vex.
+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_opt):
+ Fallthrough to _dl_runtime_resolve_sse_vex.
+
+2017-04-03 Mike Frysinger <vapier@gentoo.org>
+
+ [BZ #21253]
+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Increase argv_size
+ slack space by 32KiB.
+
+2017-04-03 Wladimir van der Laan <laanwj@gmail.com>
+
+ [BZ# 21338]
+ * malloc/malloc.c: Call do_set_arena_max for M_ARENA_MAX
+ instead of incorrect do_set_arena_test
+
+2017-03-31 Slava Barinov <v.barinov@samsung.com>
+
+ [BZ #21289]
+ * io/fts.h (fts_set): Replace __REDIRECT with __REDIRECT_NTH.
+
+2017-03-20 Mike Frysinger <vapier@gentoo.org>
+
+ [BZ #21275]
+ * sysdeps/unix/sysv/linux/spawni.c [__ia64__] (CLONE): Rename
+ __stack to __stackbase.
+ (STACK): Invert _STACK_GROWS_DOWN and _STACK_GROWS_UP order of
+ checks so we can include defined(__ia64__) first.
+
+2017-03-15 Mike Frysinger <vapier@gentoo.org>
+
+ * sysdeps/x86_64/mempcpy_chk.S (__mempcpy_chk): Check for SHARED
+ instead of PIC.
+
+2017-03-15 John David Anglin <danglin@gcc.gnu.org>
+
+ * sysdeps/hppa/dl-machine.h (DL_STACK_END): Define.
+ (RTLD_START): Don't record stack end address in _dl_start_user.
+
+2017-03-02 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21015]
+ * manual/install.texi (Configuring and compiling): Document
+ --enable-bind-now.
+ * Makeconfig [bind-now] (LDFLAGS-lib.so): Set.
+ (build-shlib-helper): Use $(LDFLAGS-lib.so).
+ (format.lds): Likewise.
+ [bind-now] (LDFLAGS-c.so): Remove.
+ * sysdeps/x86_64/localplt.data (libm.so): matherr relocation can
+ be R_X86_64_GLOB_DAT.
+ * sysdeps/unix/sysv/linux/i386/localplt.data (libm.so): matherr
+ relocation can be R_386_GLOB_DAT.
+ * sysdeps/unix/sysv/linux/alpha/localplt.data (libm.so): matherr
+ relocaiton can be R_ALPHA_GLOB_DAT.
+ * iconvdata/Makefile [bind-now] (LDFLAGS.so): Add -Wl,-z,now.
+
+2017-02-28 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #20257]
+ * inet/Makefile (routines): Add deadline.
+ (tests-static): Add tst-deadline.
+ * inet/net-internal.h (struct deadline_current_time)
+ (__deadline_current_time, struct deadline, __deadline_is_infinite)
+ (__deadline_elapsed, __deadline_first, __deadline_from_timeval)
+ (__deadline_to_ms, __is_timeval_valid_timeout): Declare.
+ * inet/deadline.c: New file.
+ * inet/tst-deadline.c: Likewise.
+ * sunrpc/Makefile (tests): Add tst-udp-nonblocking,
+ tst-udp-timeout, tst-udp-garbage.
+ (tst-udp-nonblocking, tst-udp-timeout): Link against libc.so
+ explicitly.
+ (tst-udp-garbage): Likewise. Also link against thread library.
+ * sunrpc/clnt_udp.c (struct cu_data): Mention in comment that the
+ struct layout is part of the ABI.
+ (clntudp_call): Rework timeout handling.
+ * sunrpc/tst-udp-garbage.c: New file.
+ * sunrpc/tst-udp-nonblocking.c: Likewise.
+ * sunrpc/tst-udp-timeout.c: Likewise.
+
+2017-02-27 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21115]
+ * sunrpc/clnt_udp.c (clntudp_call): Free ancillary data later.
+ * sunrpc/Makefile (tests): Add tst-udp-error.
+ (tst-udp-error): Link against libc.so explicitly.
+ * sunrpc/tst-udp-error: New file.
+
+2017-02-08 Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+ [BZ #21109]
+ * elf/dl-tunable-types.h (tunable_callback_t): Accept
+ tunable_val_t as argument.
+ * elf/dl-tunables.c (__tunable_set_val): Add comment.
+ * malloc/arena.c (set_mallopt_check): Take tunable_val_t as
+ argument.
+ (DL_TUNABLE_CALLBACK_FNDECL): Likewise.
+
2017-02-05 Siddhesh Poyarekar <siddhesh@sourceware.org>
* version.h (RELEASE): Set to "stable"
diff --git a/INSTALL b/INSTALL
index 3b3fd121b2..e77cb2d4e2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -146,6 +146,12 @@ will be used, and CFLAGS sets optimization options for the compiler.
of routines called directly from assembler are excluded from this
protection.
+'--enable-bind-now'
+ Disable lazy binding for installed shared objects. This provides
+ additional security hardening because it enables full RELRO and a
+ read-only global offset table (GOT), at the cost of slightly
+ increased program load times.
+
'--enable-pt_chown'
The file 'pt_chown' is a helper binary for 'grantpt' (*note
Pseudo-Terminals: Allocation.) that is installed setuid root to fix
diff --git a/Makeconfig b/Makeconfig
index 97a15b569e..1c815113b9 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -386,6 +386,13 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
LDFLAGS-rtld += $(hashstyle-LDFLAGS)
endif
+# If lazy relocations are disabled, add the -z now flag. Use
+# LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to
+# test modules.
+ifeq ($(bind-now),yes)
+LDFLAGS-lib.so += -Wl,-z,now
+endif
+
# Command to run after every final link (executable or shared object).
# This is invoked with $(call after-link,...), so it should operate on
# the file $1. This can be set to do some sort of post-processing on
diff --git a/Makerules b/Makerules
index e9194e54cf..7f0eef8096 100644
--- a/Makerules
+++ b/Makerules
@@ -588,7 +588,7 @@ $(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \
$(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \
$(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \
-Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \
- $(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
+ $(LDFLAGS.so) $(LDFLAGS-lib.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
-L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
endef
@@ -686,10 +686,6 @@ LDFLAGS-c.so = -nostdlib -nostartfiles
LDLIBS-c.so += $(libc.so-gnulib)
# Give libc.so an entry point and make it directly runnable itself.
LDFLAGS-c.so += -e __libc_main
-# If lazy relocation is disabled add the -z now flag.
-ifeq ($(bind-now),yes)
-LDFLAGS-c.so += -Wl,-z,now
-endif
# Pre-link the objects of libc_pic.a so that we can locally resolve
# COMMON symbols before we link against ld.so. This is because ld.so
# contains some of libc_pic.a already, which will prevent the COMMONs
@@ -1104,7 +1100,8 @@ $(common-objpfx)format.lds: $(..)scripts/output-format.sed \
ifneq (unknown,$(output-format))
echo > $@.new 'OUTPUT_FORMAT($(output-format))'
else
- $(LINK.o) -shared $(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \
+ $(LINK.o) -shared $(sysdep-LDFLAGS) $(rtld-LDFLAGS) \
+ $(LDFLAGS.so) $(LDFLAGS-lib.so) \
-x c /dev/null -o $@.so -Wl,--verbose -v 2>&1 \
| sed -n -f $< > $@.new
test -s $@.new
diff --git a/NEWS b/NEWS
index ec15dde761..7be238c404 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,19 @@ See the end for copying conditions.
Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
+Version 2.25.1
+
+The following bugs are resolved with this release:
+
+ [20257] sunrpc: clntudp_call does not enforce timeout when receiving data
+ [21015] Document and fix --enable-bind-now
+ [21109] Tunables broken on big-endian
+ [21115] sunrpc: Use-after-free in error path in clntudp_call
+ [21209] Ignore and remove LD_HWCAP_MASK for AT_SECURE programs
+ [21289] Fix symbol redirect for fts_set
+ [21386] Assertion in fork for distinct parent PID is incorrect
+ [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
+
Version 2.25
* The feature test macro __STDC_WANT_LIB_EXT2__, from ISO/IEC TR
diff --git a/elf/Makefile b/elf/Makefile
index 61abeb59ee..cc4aeb25b6 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1398,6 +1398,7 @@ $(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so
$(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
$(objpfx)tst-nodelete-dlclose-plugin.so
-tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096
+tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
+ LD_HWCAP_MASK=0xffffffff
tst-env-setuid-tunables-ENV = \
GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
index a986f0b593..37a4e8021f 100644
--- a/elf/dl-tunable-types.h
+++ b/elf/dl-tunable-types.h
@@ -21,8 +21,6 @@
# define _TUNABLE_TYPES_H_
#include <stddef.h>
-typedef void (*tunable_callback_t) (void *);
-
typedef enum
{
TUNABLE_TYPE_INT_32,
@@ -43,6 +41,8 @@ typedef union
const char *strval;
} tunable_val_t;
+typedef void (*tunable_callback_t) (tunable_val_t *);
+
/* Security level for tunables. This decides what to do with individual
tunables for AT_SECURE binaries. */
typedef enum
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index a8d53d6a31..e42aa67003 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -455,6 +455,8 @@ __tunable_set_val (tunable_id_t id, void *valp, tunable_callback_t callback)
if (cur->strval == NULL)
return;
+ /* Caller does not need the value, just call the callback with our tunable
+ value. */
if (valp == NULL)
goto cb;
diff --git a/elf/rtld.c b/elf/rtld.c
index a036ece956..9362a21e73 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -99,14 +99,121 @@ uintptr_t __pointer_chk_guard_local
strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
#endif
+/* Length limits for names and paths, to protect the dynamic linker,
+ particularly when __libc_enable_secure is active. */
+#ifdef NAME_MAX
+# define SECURE_NAME_LIMIT NAME_MAX
+#else
+# define SECURE_NAME_LIMIT 255
+#endif
+#ifdef PATH_MAX
+# define SECURE_PATH_LIMIT PATH_MAX
+#else
+# define SECURE_PATH_LIMIT 1024
+#endif
+
+/* Check that AT_SECURE=0, or that the passed name does not contain
+ directories and is not overly long. Reject empty names
+ unconditionally. */
+static bool
+dso_name_valid_for_suid (const char *p)
+{
+ if (__glibc_unlikely (__libc_enable_secure))
+ {
+ /* Ignore pathnames with directories for AT_SECURE=1
+ programs, and also skip overlong names. */
+ size_t len = strlen (p);
+ if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
+ return false;
+ }
+ return *p != '\0';
+}
-/* List of auditing DSOs. */
+/* LD_AUDIT variable contents. Must be processed before the
+ audit_list below. */
+const char *audit_list_string;
+
+/* Cyclic list of auditing DSOs. audit_list->next is the first
+ element. */
static struct audit_list
{
const char *name;
struct audit_list *next;
} *audit_list;
+/* Iterator for audit_list_string followed by audit_list. */
+struct audit_list_iter
+{
+ /* Tail of audit_list_string still needing processing, or NULL. */
+ const char *audit_list_tail;
+
+ /* The list element returned in the previous iteration. NULL before
+ the first element. */
+ struct audit_list *previous;
+
+ /* Scratch buffer for returning a name which is part of
+ audit_list_string. */
+ char fname[SECURE_NAME_LIMIT];
+};
+
+/* Initialize an audit list iterator. */
+static void
+audit_list_iter_init (struct audit_list_iter *iter)
+{
+ iter->audit_list_tail = audit_list_string;
+ iter->previous = NULL;
+}
+
+/* Iterate through both audit_list_string and audit_list. */
+static const char *
+audit_list_iter_next (struct audit_list_iter *iter)
+{
+ if (iter->audit_list_tail != NULL)
+ {
+ /* First iterate over audit_list_string. */
+ while (*iter->audit_list_tail != '\0')
+ {
+ /* Split audit list at colon. */
+ size_t len = strcspn (iter->audit_list_tail, ":");
+ if (len > 0 && len < sizeof (iter->fname))
+ {
+ memcpy (iter->fname, iter->audit_list_tail, len);
+ iter->fname[len] = '\0';
+ }
+ else
+ /* Do not return this name to the caller. */
+ iter->fname[0] = '\0';
+
+ /* Skip over the substring and the following delimiter. */
+ iter->audit_list_tail += len;
+ if (*iter->audit_list_tail == ':')
+ ++iter->audit_list_tail;
+
+ /* If the name is valid, return it. */
+ if (dso_name_valid_for_suid (iter->fname))
+ return iter->fname;
+ /* Otherwise, wrap around and try the next name. */
+ }
+ /* Fall through to the procesing of audit_list. */
+ }
+
+ if (iter->previous == NULL)
+ {
+ if (audit_list == NULL)
+ /* No pre-parsed audit list. */
+ return NULL;
+ /* Start of audit list. The first list element is at
+ audit_list->next (cyclic list). */
+ iter->previous = audit_list->next;
+ return iter->previous->name;
+ }
+ if (iter->previous == audit_list)
+ /* Cyclic list wrap-around. */
+ return NULL;
+ iter->previous = iter->previous->next;
+ return iter->previous->name;
+}
+
#ifndef HAVE_INLINED_SYSCALLS
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
@@ -716,6 +823,42 @@ static const char *preloadlist attribute_relro;
/* Nonzero if information about versions has to be printed. */
static int version_info attribute_relro;
+/* The LD_PRELOAD environment variable gives list of libraries
+ separated by white space or colons that are loaded before the
+ executable's dependencies and prepended to the global scope list.
+ (If the binary is running setuid all elements containing a '/' are
+ ignored since it is insecure.) Return the number of preloads
+ performed. */
+unsigned int
+handle_ld_preload (const char *preloadlist, struct link_map *main_map)
+{
+ unsigned int npreloads = 0;
+ const char *p = preloadlist;
+ char fname[SECURE_PATH_LIMIT];
+
+ while (*p != '\0')
+ {
+ /* Split preload list at space/colon. */
+ size_t len = strcspn (p, " :");
+ if (len > 0 && len < sizeof (fname))
+ {
+ memcpy (fname, p, len);
+ fname[len] = '\0';
+ }
+ else
+ fname[0] = '\0';
+
+ /* Skip over the substring and the following delimiter. */
+ p += len;
+ if (*p != '\0')
+ ++p;
+
+ if (dso_name_valid_for_suid (fname))
+ npreloads += do_preload (fname, main_map, "LD_PRELOAD");
+ }
+ return npreloads;
+}
+
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
@@ -1238,11 +1381,13 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
/* If we have auditing DSOs to load, do it now. */
- if (__glibc_unlikely (audit_list != NULL))
+ bool need_security_init = true;
+ if (__glibc_unlikely (audit_list != NULL)
+ || __glibc_unlikely (audit_list_string != NULL))
{
- /* Iterate over all entries in the list. The order is important. */
struct audit_ifaces *last_audit = NULL;
- struct audit_list *al = audit_list->next;
+ struct audit_list_iter al_iter;
+ audit_list_iter_init (&al_iter);
/* Since we start using the auditing DSOs right away we need to
initialize the data structures now. */
@@ -1253,9 +1398,14 @@ of this helper program; chances are you did not intend to run this program.\n\
use different values (especially the pointer guard) and will
fail later on. */
security_init ();
+ need_security_init = false;
- do
+ while (true)
{
+ const char *name = audit_list_iter_next (&al_iter);
+ if (name == NULL)
+ break;
+
int tls_idx = GL(dl_tls_max_dtv_idx);
/* Now it is time to determine the layout of the static TLS
@@ -1264,7 +1414,7 @@ of this helper program; chances are you did not intend to run this program.\n\
no DF_STATIC_TLS bit is set. The reason is that we know
glibc will use the static model. */
struct dlmopen_args dlmargs;
- dlmargs.fname = al->name;
+ dlmargs.fname = name;
dlmargs.map = NULL;
const char *objname;
@@ -1277,7 +1427,7 @@ of this helper program; chances are you did not intend to run this program.\n\
not_loaded:
_dl_error_printf ("\
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
- al->name, err_str);
+ name, err_str);
if (malloced)
free ((char *) err_str);
}
@@ -1381,10 +1531,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
goto not_loaded;
}
}
-
- al = al->next;
}
- while (al != audit_list->next);
/* If we have any auditing modules, announce that we already
have two objects loaded. */
@@ -1462,23 +1609,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
if (__glibc_unlikely (preloadlist != NULL))
{
- /* The LD_PRELOAD environment variable gives list of libraries
- separated by white space or colons that are loaded before the
- executable's dependencies and prepended to the global scope
- list. If the binary is running setuid all elements
- containing a '/' are ignored since it is insecure. */
- char *list = strdupa (preloadlist);
- char *p;
-
HP_TIMING_NOW (start);
-
- /* Prevent optimizing strsep. Speed is not important here. */
- while ((p = (strsep) (&list, " :")) != NULL)
- if (p[0] != '\0'
- && (__builtin_expect (! __libc_enable_secure, 1)
- || strchr (p, '/') == NULL))
- npreloads += do_preload (p, main_map, "LD_PRELOAD");
-
+ npreloads += handle_ld_preload (preloadlist, main_map);
HP_TIMING_NOW (stop);
HP_TIMING_DIFF (diff, start, stop);
HP_TIMING_ACCUM_NT (load_time, diff);
@@ -1663,7 +1795,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
if (tcbp == NULL)
tcbp = init_tls ();
- if (__glibc_likely (audit_list == NULL))
+ if (__glibc_likely (need_security_init))
/* Initialize security features. But only if we have not done it
earlier. */
security_init ();
@@ -2294,9 +2426,7 @@ process_dl_audit (char *str)
char *p;
while ((p = (strsep) (&str, ":")) != NULL)
- if (p[0] != '\0'
- && (__builtin_expect (! __libc_enable_secure, 1)
- || strchr (p, '/') == NULL))
+ if (dso_name_valid_for_suid (p))
{
/* This is using the local malloc, not the system malloc. The
memory can never be freed. */
@@ -2360,7 +2490,7 @@ process_envvars (enum mode *modep)
break;
}
if (memcmp (envline, "AUDIT", 5) == 0)
- process_dl_audit (&envline[6]);
+ audit_list_string = &envline[6];
break;
case 7:
@@ -2404,7 +2534,8 @@ process_envvars (enum mode *modep)
case 10:
/* Mask for the important hardware capabilities. */
- if (memcmp (envline, "HWCAP_MASK", 10) == 0)
+ if (!__libc_enable_secure
+ && memcmp (envline, "HWCAP_MASK", 10) == 0)
GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
0, 0);
break;
@@ -2418,7 +2549,8 @@ process_envvars (enum mode *modep)
case 12:
/* The library search path. */
- if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
+ if (!__libc_enable_secure
+ && memcmp (envline, "LIBRARY_PATH", 12) == 0)
{
library_path = &envline[13];
break;
diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c
index 6ec3fa5874..eec408eb5d 100644
--- a/elf/tst-env-setuid.c
+++ b/elf/tst-env-setuid.c
@@ -213,6 +213,12 @@ test_child (void)
return 1;
}
+ if (getenv ("LD_HWCAP_MASK") != NULL)
+ {
+ printf ("LD_HWCAP_MASK still set\n");
+ return 1;
+ }
+
return 0;
}
#endif
@@ -233,6 +239,12 @@ test_parent (void)
return 1;
}
+ if (getenv ("LD_HWCAP_MASK") == NULL)
+ {
+ printf ("LD_HWCAP_MASK lost\n");
+ return 1;
+ }
+
return 0;
}
#endif
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index 04157b25c5..e4845871f5 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -63,6 +63,11 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \
MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \
CP770 CP771 CP772 CP773 CP774
+# If lazy binding is disabled, use BIND_NOW for the gconv modules.
+ifeq ($(bind-now),yes)
+LDFLAGS.so += -Wl,-z,now
+endif
+
modules.so := $(addsuffix .so, $(modules))
ifeq (yes,$(build-shared))
diff --git a/inet/Makefile b/inet/Makefile
index 010792af8f..6a7d3e0664 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -45,14 +45,18 @@ routines := htonl htons \
in6_addr getnameinfo if_index ifaddrs inet6_option \
getipv4sourcefilter setipv4sourcefilter \
getsourcefilter setsourcefilter inet6_opt inet6_rth \
- inet6_scopeid_pton
+ inet6_scopeid_pton deadline
aux := check_pf check_native ifreq
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \
- tst-sockaddr tst-inet6_scopeid_pton test-hnto-types
+ tst-sockaddr tst-inet6_scopeid_pton test-hnto-types tst-deadline
+
+# tst-deadline must be linked statically so that we can access
+# internal functions.
+tests-static += tst-deadline
include ../Rules
diff --git a/inet/deadline.c b/inet/deadline.c
new file mode 100644
index 0000000000..c1fa415a39
--- /dev/null
+++ b/inet/deadline.c
@@ -0,0 +1,122 @@
+/* Computing deadlines for timeouts.
+ 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 <net-internal.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <time.h>
+
+struct deadline_current_time internal_function
+__deadline_current_time (void)
+{
+ struct deadline_current_time result;
+ if (__clock_gettime (CLOCK_MONOTONIC, &result.current) != 0)
+ {
+ struct timeval current_tv;
+ if (__gettimeofday (&current_tv, NULL) == 0)
+ __libc_fatal ("Fatal error: gettimeofday system call failed\n");
+ result.current.tv_sec = current_tv.tv_sec;
+ result.current.tv_nsec = current_tv.tv_usec * 1000;
+ }
+ assert (result.current.tv_sec >= 0);
+ return result;
+}
+
+/* A special deadline value for which __deadline_is_infinite is
+ true. */
+static inline struct deadline
+infinite_deadline (void)
+{
+ return (struct deadline) { { -1, -1 } };
+}
+
+struct deadline internal_function
+__deadline_from_timeval (struct deadline_current_time current,
+ struct timeval tv)
+{
+ assert (__is_timeval_valid_timeout (tv));
+
+ /* Compute second-based deadline. Perform the addition in
+ uintmax_t, which is unsigned, to simply overflow detection. */
+ uintmax_t sec = current.current.tv_sec;
+ sec += tv.tv_sec;
+ if (sec < (uintmax_t) tv.tv_sec)
+ return infinite_deadline ();
+
+ /* Compute nanosecond deadline. */
+ int nsec = current.current.tv_nsec + tv.tv_usec * 1000;
+ if (nsec >= 1000 * 1000 * 1000)
+ {
+ /* Carry nanosecond overflow to seconds. */
+ nsec -= 1000 * 1000 * 1000;
+ if (sec + 1 < sec)
+ return infinite_deadline ();
+ ++sec;
+ }
+ /* This uses a GCC extension, otherwise these casts for detecting
+ overflow would not be defined. */
+ if ((time_t) sec < 0 || sec != (uintmax_t) (time_t) sec)
+ return infinite_deadline ();
+
+ return (struct deadline) { { sec, nsec } };
+}
+
+int internal_function
+__deadline_to_ms (struct deadline_current_time current,
+ struct deadline deadline)
+{
+ if (__deadline_is_infinite (deadline))
+ return INT_MAX;
+
+ if (current.current.tv_sec > deadline.absolute.tv_sec
+ || (current.current.tv_sec == deadline.absolute.tv_sec
+ && current.current.tv_nsec >= deadline.absolute.tv_nsec))
+ return 0;
+ time_t sec = deadline.absolute.tv_sec - current.current.tv_sec;
+ if (sec >= INT_MAX)
+ /* This value will overflow below. */
+ return INT_MAX;
+ int nsec = deadline.absolute.tv_nsec - current.current.tv_nsec;
+ if (nsec < 0)
+ {
+ /* Borrow from the seconds field. */
+ assert (sec > 0);
+ --sec;
+ nsec += 1000 * 1000 * 1000;
+ }
+
+ /* Prepare for rounding up to milliseconds. */
+ nsec += 999999;
+ if (nsec > 1000 * 1000 * 1000)
+ {
+ assert (sec < INT_MAX);
+ ++sec;
+ nsec -= 1000 * 1000 * 1000;
+ }
+
+ unsigned int msec = nsec / (1000 * 1000);
+ if (sec > INT_MAX / 1000)
+ return INT_MAX;
+ msec += sec * 1000;
+ if (msec > INT_MAX)
+ return INT_MAX;
+ return msec;
+}
diff --git a/inet/net-internal.h b/inet/net-internal.h
index 087597ed99..2b2632c7ba 100644
--- a/inet/net-internal.h
+++ b/inet/net-internal.h
@@ -20,11 +20,100 @@
#define _NET_INTERNAL_H 1
#include <arpa/inet.h>
+#include <stdbool.h>
#include <stdint.h>
+#include <sys/time.h>
int __inet6_scopeid_pton (const struct in6_addr *address,
const char *scope, uint32_t *result)
internal_function attribute_hidden;
libc_hidden_proto (__inet6_scopeid_pton)
+
+/* Deadline handling for enforcing timeouts.
+
+ Code should call __deadline_current_time to obtain the current time
+ and cache it locally. The cache needs updating after every
+ long-running or potentially blocking operation. Deadlines relative
+ to the current time can be computed using __deadline_from_timeval.
+ The deadlines may have to be recomputed in response to certain
+ events (such as an incoming packet), but they are absolute (not
+ relative to the current time). A timeout suitable for use with the
+ poll function can be computed from such a deadline using
+ __deadline_to_ms.
+
+ The fields in the structs defined belowed should only be used
+ within the implementation. */
+
+/* Cache of the current time. Used to compute deadlines from relative
+ timeouts and vice versa. */
+struct deadline_current_time
+{
+ struct timespec current;
+};
+
+/* Return the current time. Terminates the process if the current
+ time is not available. */
+struct deadline_current_time __deadline_current_time (void)
+ internal_function attribute_hidden;
+
+/* Computed absolute deadline. */
+struct deadline
+{
+ struct timespec absolute;
+};
+
+
+/* For internal use only. */
+static inline bool
+__deadline_is_infinite (struct deadline deadline)
+{
+ return deadline.absolute.tv_nsec < 0;
+}
+
+/* Return true if the current time is at the deadline or past it. */
+static inline bool
+__deadline_elapsed (struct deadline_current_time current,
+ struct deadline deadline)
+{
+ return !__deadline_is_infinite (deadline)
+ && (current.current.tv_sec > deadline.absolute.tv_sec
+ || (current.current.tv_sec == deadline.absolute.tv_sec
+ && current.current.tv_nsec >= deadline.absolute.tv_nsec));
+}
+
+/* Return the deadline which occurs first. */
+static inline struct deadline
+__deadline_first (struct deadline left, struct deadline right)
+{
+ if (__deadline_is_infinite (right)
+ || left.absolute.tv_sec < right.absolute.tv_sec
+ || (left.absolute.tv_sec == right.absolute.tv_sec
+ && left.absolute.tv_nsec < right.absolute.tv_nsec))
+ return left;
+ else
+ return right;
+}
+
+/* Add TV to the current time and return it. Returns a special
+ infinite absolute deadline on overflow. */
+struct deadline __deadline_from_timeval (struct deadline_current_time,
+ struct timeval tv)
+ internal_function attribute_hidden;
+
+/* Compute the number of milliseconds until the specified deadline,
+ from the current time in the argument. The result is mainly for
+ use with poll. If the deadline has already passed, return 0. If
+ the result would overflow an int, return INT_MAX. */
+int __deadline_to_ms (struct deadline_current_time, struct deadline)
+ internal_function attribute_hidden;
+
+/* Return true if TV.tv_sec is non-negative and TV.tv_usec is in the
+ interval [0, 999999]. */
+static inline bool
+__is_timeval_valid_timeout (struct timeval tv)
+{
+ return tv.tv_sec >= 0 && tv.tv_usec >= 0 && tv.tv_usec < 1000 * 1000;
+}
+
#endif /* _NET_INTERNAL_H */
diff --git a/inet/tst-deadline.c b/inet/tst-deadline.c
new file mode 100644
index 0000000000..ed04345c35
--- /dev/null
+++ b/inet/tst-deadline.c
@@ -0,0 +1,188 @@
+/* Tests for computing deadlines for timeouts.
+ 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 <inet/net-internal.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <support/check.h>
+
+/* Find the maximum value which can be represented in a time_t. */
+static time_t
+time_t_max (void)
+{
+ _Static_assert (0 > (time_t) -1, "time_t is signed");
+ uintmax_t current = 1;
+ while (true)
+ {
+ uintmax_t next = current * 2;
+ /* This cannot happen because time_t is signed. */
+ TEST_VERIFY_EXIT (next > current);
+ ++next;
+ if ((time_t) next < 0 || next != (uintmax_t) (time_t) next)
+ /* Value cannot be represented in time_t. Return the previous
+ value. */
+ return current;
+ current = next;
+ }
+}
+
+static int
+do_test (void)
+{
+ {
+ struct deadline_current_time current_time = __deadline_current_time ();
+ TEST_VERIFY (current_time.current.tv_sec >= 0);
+ current_time = __deadline_current_time ();
+ /* Due to CLOCK_MONOTONIC, either seconds or nanoseconds are
+ greater than zero. This is also true for the gettimeofday
+ fallback. */
+ TEST_VERIFY (current_time.current.tv_sec >= 0);
+ TEST_VERIFY (current_time.current.tv_sec > 0
+ || current_time.current.tv_nsec > 0);
+ }
+
+ /* Check basic computations of deadlines. */
+ struct deadline_current_time current_time = { { 1, 123456789 } };
+ struct deadline deadline = __deadline_from_timeval
+ (current_time, (struct timeval) { 0, 1 });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 123457789);
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1);
+
+ deadline = __deadline_from_timeval
+ (current_time, ((struct timeval) { 0, 2 }));
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 123458789);
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1);
+
+ deadline = __deadline_from_timeval
+ (current_time, ((struct timeval) { 1, 0 }));
+ TEST_VERIFY (deadline.absolute.tv_sec == 2);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 123456789);
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
+
+ /* Check if timeouts are correctly rounded up to the next
+ millisecond. */
+ for (int i = 0; i < 999999; ++i)
+ {
+ ++current_time.current.tv_nsec;
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
+ }
+
+ /* A full millisecond has elapsed, so the time to the deadline is
+ now less than 1000. */
+ ++current_time.current.tv_nsec;
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999);
+
+ /* Check __deadline_to_ms carry-over. */
+ current_time = (struct deadline_current_time) { { 9, 123456789 } };
+ deadline = (struct deadline) { { 10, 122456789 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999);
+ deadline = (struct deadline) { { 10, 122456790 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
+ deadline = (struct deadline) { { 10, 123456788 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
+ deadline = (struct deadline) { { 10, 123456789 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
+
+ /* Check __deadline_to_ms overflow. */
+ deadline = (struct deadline) { { INT_MAX - 1, 1 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == INT_MAX);
+
+ /* Check __deadline_to_ms for elapsed deadlines. */
+ current_time = (struct deadline_current_time) { { 9, 123456789 } };
+ deadline.absolute = current_time.current;
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
+ current_time = (struct deadline_current_time) { { 9, 123456790 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
+ current_time = (struct deadline_current_time) { { 10, 0 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
+ current_time = (struct deadline_current_time) { { 10, 123456788 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
+ current_time = (struct deadline_current_time) { { 10, 123456789 } };
+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
+
+ /* Check carry-over in __deadline_from_timeval. */
+ current_time = (struct deadline_current_time) { { 9, 998000001 } };
+ for (int i = 0; i < 2000; ++i)
+ {
+ deadline = __deadline_from_timeval
+ (current_time, (struct timeval) { 1, i });
+ TEST_VERIFY (deadline.absolute.tv_sec == 10);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 998000001 + i * 1000);
+ }
+ for (int i = 2000; i < 3000; ++i)
+ {
+ deadline = __deadline_from_timeval
+ (current_time, (struct timeval) { 2, i });
+ TEST_VERIFY (deadline.absolute.tv_sec == 12);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 1 + (i - 2000) * 1000);
+ }
+
+ /* Check infinite deadlines. */
+ deadline = __deadline_from_timeval
+ ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1000 } },
+ (struct timeval) { time_t_max (), 1 });
+ TEST_VERIFY (__deadline_is_infinite (deadline));
+ deadline = __deadline_from_timeval
+ ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1001 } },
+ (struct timeval) { time_t_max (), 1 });
+ TEST_VERIFY (!__deadline_is_infinite (deadline));
+ deadline = __deadline_from_timeval
+ ((struct deadline_current_time)
+ { { time_t_max (), 1000 * 1000 * 1000 - 1000 } },
+ (struct timeval) { 0, 1 });
+ TEST_VERIFY (__deadline_is_infinite (deadline));
+ deadline = __deadline_from_timeval
+ ((struct deadline_current_time)
+ { { time_t_max () / 2 + 1, 0 } },
+ (struct timeval) { time_t_max () / 2 + 1, 0 });
+ TEST_VERIFY (__deadline_is_infinite (deadline));
+
+ /* Check __deadline_first behavior. */
+ deadline = __deadline_first
+ ((struct deadline) { { 1, 2 } },
+ (struct deadline) { { 1, 3 } });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 2);
+ deadline = __deadline_first
+ ((struct deadline) { { 1, 3 } },
+ (struct deadline) { { 1, 2 } });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 2);
+ deadline = __deadline_first
+ ((struct deadline) { { 1, 2 } },
+ (struct deadline) { { 2, 1 } });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 2);
+ deadline = __deadline_first
+ ((struct deadline) { { 1, 2 } },
+ (struct deadline) { { 2, 4 } });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 2);
+ deadline = __deadline_first
+ ((struct deadline) { { 2, 4 } },
+ (struct deadline) { { 1, 2 } });
+ TEST_VERIFY (deadline.absolute.tv_sec == 1);
+ TEST_VERIFY (deadline.absolute.tv_nsec == 2);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/io/fts.h b/io/fts.h
index b9cff534e9..ab15567001 100644
--- a/io/fts.h
+++ b/io/fts.h
@@ -193,7 +193,7 @@ FTS *__REDIRECT (fts_open, (char * const *, int,
int (*)(const FTSENT **, const FTSENT **)),
fts64_open);
FTSENT *__REDIRECT (fts_read, (FTS *), fts64_read);
-int __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW;
+int __REDIRECT_NTH (fts_set, (FTS *, FTSENT *, int), fts64_set);
# else
# define fts_children fts64_children
# define fts_close fts64_close
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index 0cdb097ab6..127c1cfb35 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -1,3 +1,11 @@
+2017-06-11 Santhosh Thottingal <santhosh.thottingal@gmail.com>
+
+ [BZ #19922]
+ * locales/iso14651_t1_common: Add collation rules for U+07DA to U+07DF.
+
+ [BZ #19919]
+ * locales/iso14651_t1_common: Correct collation of U+0D36 and U+0D37.
+
2017-01-01 Joseph Myers <joseph@codesourcery.com>
* All files with FSF copyright notices: Update copyright dates
diff --git a/localedata/locales/iso14651_t1_common b/localedata/locales/iso14651_t1_common
index eef75ba65e..0e64f26a12 100644
--- a/localedata/locales/iso14651_t1_common
+++ b/localedata/locales/iso14651_t1_common
@@ -1042,9 +1042,9 @@ collating-element <ml-bh> from "<U0D2D><U0D4D>"
collating-element <ml-m> from "<U0D2E><U0D4D>"
collating-element <ml-y> from "<U0D2F><U0D4D>"
collating-element <ml-v> from "<U0D35><U0D4D>"
-collating-element <ml-s> from "<U0D38><U0D4D>"
collating-element <ml-ss> from "<U0D36><U0D4D>"
collating-element <ml-sh> from "<U0D37><U0D4D>"
+collating-element <ml-s> from "<U0D38><U0D4D>"
collating-element <ml-h> from "<U0D39><U0D4D>"
collating-element <ml-zh> from "<U0D34><U0D4D>"
collating-element <ml-rr> from "<U0D31><U0D4D>"
@@ -1103,8 +1103,8 @@ collating-symbol <ml-rra>
collating-symbol <ml-la>
collating-symbol <ml-lla>
collating-symbol <ml-va>
-collating-symbol <ml-sha>
collating-symbol <ml-ssa>
+collating-symbol <ml-sha>
collating-symbol <ml-sa>
collating-symbol <ml-ha>
collating-symbol <ml-avagrah>
@@ -1126,6 +1126,12 @@ collating-symbol <mlvs-o>
collating-symbol <mlvs-au>
collating-symbol <ml-visarga>
collating-symbol <ml-virama>
+collating-symbol <ml-atomic-chillu-k>
+collating-symbol <ml-atomic-chillu-n>
+collating-symbol <ml-atomic-chillu-nn>
+collating-symbol <ml-atomic-chillu-l>
+collating-symbol <ml-atomic-chillu-ll>
+collating-symbol <ml-atomic-chillu-r>
#
# <BENGALI>
#
@@ -4552,6 +4558,12 @@ collating-symbol <TIB-subA>
<mlvs-o>
<mlvs-au>
<ml-visarga>
+<ml-atomic-chillu-k>
+<ml-atomic-chillu-n>
+<ml-atomic-chillu-nn>
+<ml-atomic-chillu-l>
+<ml-atomic-chillu-ll>
+<ml-atomic-chillu-r>
#
# <BENGALI>
#
@@ -7252,6 +7264,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
<U0D13> <mlvw-o>;<BAS>;<MIN>;IGNORE
<U0D14> <mlvw-au>;<BAS>;<MIN>;IGNORE
<ml-chillu-k> "<ml-ka><ml-virama>";<BAS>;<MIN>;IGNORE
+<U0D7F> "<ml-ka><ml-virama>";<ml-atomic-chillu-k>;<MIN>;IGNORE
<U0D15> "<ml-ka><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-kh> "<ml-kha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D16> "<ml-kha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
@@ -7280,6 +7293,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
<ml-dh> "<ml-dha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D22> "<ml-dha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-nn> "<ml-nna><ml-virama>";<BAS>;<MIN>;IGNORE # ണ്‍ = ണ + ് + zwj
+<U0D7A> "<ml-nna><ml-virama>";<ml-atomic-chillu-nn>;<MIN>;IGNORE
<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ണ = ണ + ് + അ
<ml-th> "<ml-tha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D24> "<ml-tha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
@@ -7290,6 +7304,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
<ml-ddh> "<ml-ddha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D27> "<ml-ddha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-n> "<ml-na><ml-virama>";<BAS>;<MIN>;IGNORE # ന്‍= ന + ് + zwj
+<U0D7B> "<ml-na><ml-virama>";<ml-atomic-chillu-n>;<MIN>;IGNORE
<U0D28> "<ml-na><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE #ന = ന + ് + അ
<ml-p> "<ml-pa><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D2A> "<ml-pa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
@@ -7305,20 +7320,23 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
<ml-y> "<ml-ya><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D2F> "<ml-ya><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-r> "<ml-ra><ml-virama>";<BAS>;<MIN>;IGNORE # ര = ര + ് + zwj
+<U0D7C> "<ml-ra><ml-virama>";<ml-atomic-chillu-r>;<MIN>;IGNORE
<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ര = ര + ് + അ
<ml-chillu-l> <ml-la>;<BAS>;<MIN>;IGNORE # ല്‍ = ല + ് + zwj
+<U0D7D> "<ml-la><ml-virama>";<ml-atomic-chillu-l>;<MIN>;IGNORE
<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ല = ല + ് + അ
<ml-v> "<ml-va><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D35> "<ml-va><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-ss> "<ml-ssa><ml-virama>";<BAS>;<MIN>;IGNORE
-<U0D37> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
+<U0D36> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-sh> "<ml-sha><ml-virama>";<BAS>;<MIN>;IGNORE
-<U0D36> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
+<U0D37> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-s> "<ml-sa><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D38> "<ml-sa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-h> "<ml-ha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D39> "<ml-ha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
<ml-chillu-ll> "<ml-lla><ml-virama>";<BAS>;<MIN>;IGNORE # ള്‍ = ള + ് + zwj
+<U0D7E> "<ml-lla><ml-virama>";<ml-atomic-chillu-ll>;<MIN>;IGNORE
<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ള = ള + ് + അ
<ml-zh> "<ml-zha><ml-virama>";<BAS>;<MIN>;IGNORE
<U0D34> "<ml-zha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
diff --git a/malloc/arena.c b/malloc/arena.c
index b91d7d6b16..d49e4a21c8 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -212,9 +212,9 @@ __malloc_fork_unlock_child (void)
#if HAVE_TUNABLES
static inline int do_set_mallopt_check (int32_t value);
void
-DL_TUNABLE_CALLBACK (set_mallopt_check) (void *valp)
+DL_TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp)
{
- int32_t value = *(int32_t *) valp;
+ int32_t value = (int32_t) valp->numval;
do_set_mallopt_check (value);
if (check_action != 0)
__malloc_check_init ();
@@ -223,9 +223,9 @@ DL_TUNABLE_CALLBACK (set_mallopt_check) (void *valp)
# define DL_TUNABLE_CALLBACK_FNDECL(__name, __type) \
static inline int do_ ## __name (__type value); \
void \
-DL_TUNABLE_CALLBACK (__name) (void *valp) \
+DL_TUNABLE_CALLBACK (__name) (tunable_val_t *valp) \
{ \
- __type value = *(__type *) valp; \
+ __type value = (__type) (valp)->numval; \
do_ ## __name (value); \
}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 4885793905..4e076638b0 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -4902,7 +4902,7 @@ __libc_mallopt (int param_number, int value)
case M_ARENA_MAX:
if (value > 0)
- do_set_arena_test (value);
+ do_set_arena_max (value);
break;
}
__libc_lock_unlock (av->mutex);
diff --git a/manual/install.texi b/manual/install.texi
index 266add8ba9..3398cfab02 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -175,6 +175,12 @@ options to detect stack overruns. Only the dynamic linker and a small
number of routines called directly from assembler are excluded from this
protection.
+@item --enable-bind-now
+Disable lazy binding for installed shared objects. This provides
+additional security hardening because it enables full RELRO and a
+read-only global offset table (GOT), at the cost of slightly increased
+program load times.
+
@pindex pt_chown
@findex grantpt
@item --enable-pt_chown
diff --git a/posix/globtest.sh b/posix/globtest.sh
index f9cc80b4b5..73f7ae31cc 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -47,7 +47,12 @@ testout=${common_objpfx}posix/globtest-out
rm -rf $testdir $testout
mkdir $testdir
-trap 'chmod 777 $testdir/noread; rm -fr $testdir $testout' 1 2 3 15
+cleanup() {
+ chmod 777 $testdir/noread
+ rm -fr $testdir $testout
+}
+
+trap cleanup 0 HUP INT QUIT TERM
echo 1 > $testdir/file1
echo 2 > $testdir/file2
@@ -811,8 +816,6 @@ if test $failed -ne 0; then
fi
if test $result -eq 0; then
- chmod 777 $testdir/noread
- rm -fr $testdir $testout
echo "All OK." > $logfile
fi
diff --git a/string/test-memchr.c b/string/test-memchr.c
index d62889ff8f..6431605c7e 100644
--- a/string/test-memchr.c
+++ b/string/test-memchr.c
@@ -208,6 +208,12 @@ test_main (void)
do_test (0, i, i + 1, i + 1, 0);
}
+ /* BZ#21182 - wrong overflow calculation for i686 implementation
+ with address near end of the page. */
+ for (i = 2; i < 16; ++i)
+ /* page_size is in fact getpagesize() * 2. */
+ do_test (page_size / 2 - i, i, i, 1, 0x9B);
+
do_random_tests ();
return ret;
}
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
index 0c1e6124ff..7e5d2955a0 100644
--- a/sunrpc/Makefile
+++ b/sunrpc/Makefile
@@ -93,11 +93,12 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs))
others += rpcgen
-tests = tst-xdrmem tst-xdrmem2 test-rpcent
+tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \
+ tst-udp-nonblocking
xtests := tst-getmyaddr
ifeq ($(have-thread-library),yes)
-xtests += thrsvc
+xtests += thrsvc tst-udp-garbage
endif
ifeq ($(run-built-tests),yes)
@@ -155,6 +156,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS)
$(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so
$(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so
$(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so
+$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so
$(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs))
@@ -234,3 +236,8 @@ $(rpcgen-tests): $(objpfx)%.out: %.x $(objpfx)rpcgen
$(built-program-cmd) -c $< -o $@; \
$(evaluate-test)
endif
+
+$(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so
+$(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so
+$(objpfx)tst-udp-garbage: \
+ $(common-objpfx)linkobj/libc.so $(shared-thread-library)
diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index 4d9acb1e6a..6ce16eb298 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -55,6 +55,7 @@
#endif
#include <kernel-features.h>
+#include <inet/net-internal.h>
extern u_long _create_xid (void);
@@ -80,7 +81,9 @@ static const struct clnt_ops udp_ops =
};
/*
- * Private data kept per client handle
+ * Private data kept per client handle. This private struct is
+ * unfortunately part of the ABI; ypbind contains a copy of it and
+ * accesses it through CLIENT::cl_private field.
*/
struct cu_data
{
@@ -278,28 +281,38 @@ clntudp_call (/* client handle */
int inlen;
socklen_t fromlen;
struct pollfd fd;
- int milliseconds = (cu->cu_wait.tv_sec * 1000) +
- (cu->cu_wait.tv_usec / 1000);
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
- struct timeval time_waited;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
- struct timeval timeout;
int anyup; /* any network interface up */
- if (cu->cu_total.tv_usec == -1)
- {
- timeout = utimeout; /* use supplied timeout */
- }
- else
+ struct deadline_current_time current_time = __deadline_current_time ();
+ struct deadline total_deadline; /* Determined once by overall timeout. */
+ struct deadline response_deadline; /* Determined anew for each query. */
+
+ /* Choose the timeout value. For non-sending usage (xargs == NULL),
+ the total deadline does not matter, only cu->cu_wait is used
+ below. */
+ if (xargs != NULL)
{
- timeout = cu->cu_total; /* use default timeout */
+ struct timeval tv;
+ if (cu->cu_total.tv_usec == -1)
+ /* Use supplied timeout. */
+ tv = utimeout;
+ else
+ /* Use default timeout. */
+ tv = cu->cu_total;
+ if (!__is_timeval_valid_timeout (tv))
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ total_deadline = __deadline_from_timeval (current_time, tv);
}
- time_waited.tv_sec = 0;
- time_waited.tv_usec = 0;
+ /* Guard against bad timeout specification. */
+ if (!__is_timeval_valid_timeout (cu->cu_wait))
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
call_again:
xdrs = &(cu->cu_outxdrs);
if (xargs == NULL)
@@ -325,27 +338,46 @@ send_again:
return (cu->cu_error.re_status = RPC_CANTSEND);
}
- /*
- * Hack to provide rpc-based message passing
- */
- if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
- {
- return (cu->cu_error.re_status = RPC_TIMEDOUT);
- }
+ /* sendto may have blocked, so recompute the current time. */
+ current_time = __deadline_current_time ();
get_reply:
- /*
- * sub-optimal code appears here because we have
- * some clock time to spare while the packets are in flight.
- * (We assume that this is actually only executed once.)
- */
+ response_deadline = __deadline_from_timeval (current_time, cu->cu_wait);
+
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
fd.fd = cu->cu_sock;
fd.events = POLLIN;
anyup = 0;
+
+ /* Per-response retry loop. current_time must be up-to-date at the
+ top of the loop. */
for (;;)
{
+ int milliseconds;
+ if (xargs != NULL)
+ {
+ if (__deadline_elapsed (current_time, total_deadline))
+ /* Overall timeout expired. */
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ milliseconds = __deadline_to_ms
+ (current_time, __deadline_first (total_deadline,
+ response_deadline));
+ if (milliseconds == 0)
+ /* Per-query timeout expired. */
+ goto send_again;
+ }
+ else
+ {
+ /* xatgs == NULL. Collect a response without sending a
+ query. In this mode, we need to ignore the total
+ deadline. */
+ milliseconds = __deadline_to_ms (current_time, response_deadline);
+ if (milliseconds == 0)
+ /* Cannot send again, so bail out. */
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ }
+
switch (__poll (&fd, 1, milliseconds))
{
@@ -356,27 +388,10 @@ send_again:
if (!anyup)
return (cu->cu_error.re_status = RPC_CANTRECV);
}
-
- time_waited.tv_sec += cu->cu_wait.tv_sec;
- time_waited.tv_usec += cu->cu_wait.tv_usec;
- while (time_waited.tv_usec >= 1000000)
- {
- time_waited.tv_sec++;
- time_waited.tv_usec -= 1000000;
- }
- if ((time_waited.tv_sec < timeout.tv_sec) ||
- ((time_waited.tv_sec == timeout.tv_sec) &&
- (time_waited.tv_usec < timeout.tv_usec)))
- goto send_again;
- return (cu->cu_error.re_status = RPC_TIMEDOUT);
-
- /*
- * buggy in other cases because time_waited is not being
- * updated.
- */
+ goto next_response;
case -1:
if (errno == EINTR)
- continue;
+ goto next_response;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
@@ -421,9 +436,9 @@ send_again:
cmsg = CMSG_NXTHDR (&msg, cmsg))
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
- free (cbuf);
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
+ free (cbuf);
return (cu->cu_error.re_status = RPC_CANTRECV);
}
free (cbuf);
@@ -440,20 +455,22 @@ send_again:
if (inlen < 0)
{
if (errno == EWOULDBLOCK)
- continue;
+ goto next_response;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
- if (inlen < 4)
- continue;
-
- /* see if reply transaction id matches sent id.
- Don't do this if we only wait for a replay */
- if (xargs != NULL
- && memcmp (cu->cu_inbuf, cu->cu_outbuf, sizeof (u_int32_t)) != 0)
- continue;
- /* we now assume we have the proper reply */
- break;
+ /* Accept the response if the packet is sufficiently long and
+ the transaction ID matches the query (if available). */
+ if (inlen >= 4
+ && (xargs == NULL
+ || memcmp (cu->cu_inbuf, cu->cu_outbuf,
+ sizeof (u_int32_t)) == 0))
+ break;
+
+ next_response:
+ /* Update the current time because poll and recvmsg waited for
+ an unknown time. */
+ current_time = __deadline_current_time ();
}
/*
diff --git a/sunrpc/tst-udp-error.c b/sunrpc/tst-udp-error.c
new file mode 100644
index 0000000000..1efc02f5c6
--- /dev/null
+++ b/sunrpc/tst-udp-error.c
@@ -0,0 +1,62 @@
+/* Check for use-after-free in clntudp_call (bug 21115).
+ 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 <netinet/in.h>
+#include <rpc/clnt.h>
+#include <rpc/svc.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xsocket.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ support_enter_network_namespace ();
+
+ /* Obtain a likely-unused port number. */
+ struct sockaddr_in sin =
+ {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
+ };
+ {
+ int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ xbind (fd, (struct sockaddr *) &sin, sizeof (sin));
+ socklen_t sinlen = sizeof (sin);
+ xgetsockname (fd, (struct sockaddr *) &sin, &sinlen);
+ /* Close the socket, so that we will receive an error below. */
+ close (fd);
+ }
+
+ int sock = RPC_ANYSOCK;
+ CLIENT *clnt = clntudp_create
+ (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock);
+ TEST_VERIFY_EXIT (clnt != NULL);
+ TEST_VERIFY (clnt_call (clnt, 3,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL,
+ ((struct timeval) { 3, 0 }))
+ == RPC_CANTRECV);
+ clnt_destroy (clnt);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sunrpc/tst-udp-garbage.c b/sunrpc/tst-udp-garbage.c
new file mode 100644
index 0000000000..4abda93f08
--- /dev/null
+++ b/sunrpc/tst-udp-garbage.c
@@ -0,0 +1,104 @@
+/* Test that garbage packets do not affect timeout handling.
+ 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 <netinet/in.h>
+#include <rpc/clnt.h>
+#include <rpc/svc.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xsocket.h>
+#include <support/xthread.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+/* Descriptor for the server UDP socket. */
+static int server_fd;
+
+static void *
+garbage_sender_thread (void *unused)
+{
+ while (true)
+ {
+ struct sockaddr_storage sa;
+ socklen_t salen = sizeof (sa);
+ char buf[1];
+ if (recvfrom (server_fd, buf, sizeof (buf), 0,
+ (struct sockaddr *) &sa, &salen) < 0)
+ FAIL_EXIT1 ("recvfrom: %m");
+
+ /* Send garbage packets indefinitely. */
+ buf[0] = 0;
+ while (true)
+ {
+ /* sendto can fail if the client closed the socket. */
+ if (sendto (server_fd, buf, sizeof (buf), 0,
+ (struct sockaddr *) &sa, salen) < 0)
+ break;
+
+ /* Wait a bit, to avoid burning too many CPU cycles in a
+ tight loop. The wait period must be much shorter than
+ the client timeouts configured below. */
+ usleep (50 * 1000);
+ }
+ }
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ support_enter_network_namespace ();
+
+ server_fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
+ struct sockaddr_in server_address =
+ {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
+ };
+ xbind (server_fd,
+ (struct sockaddr *) &server_address, sizeof (server_address));
+ {
+ socklen_t sinlen = sizeof (server_address);
+ xgetsockname (server_fd, (struct sockaddr *) &server_address, &sinlen);
+ TEST_VERIFY (sizeof (server_address) == sinlen);
+ }
+
+ /* Garbage packet source. */
+ xpthread_detach (xpthread_create (NULL, garbage_sender_thread, NULL));
+
+ /* Test client. Use an arbitrary timeout of one second, which is
+ much longer than the garbage packet interval, but still
+ reasonably short, so that the test completes quickly. */
+ int client_fd = RPC_ANYSOCK;
+ CLIENT *clnt = clntudp_create (&server_address,
+ 1, 2, /* Arbitrary RPC endpoint numbers. */
+ (struct timeval) { 1, 0 },
+ &client_fd);
+ if (clnt == NULL)
+ FAIL_EXIT1 ("clntudp_create: %m");
+
+ TEST_VERIFY (clnt_call (clnt, 3, /* Arbitrary RPC procedure number. */
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL,
+ ((struct timeval) { 1, 0 })));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sunrpc/tst-udp-nonblocking.c b/sunrpc/tst-udp-nonblocking.c
new file mode 100644
index 0000000000..1d6a7f4b56
--- /dev/null
+++ b/sunrpc/tst-udp-nonblocking.c
@@ -0,0 +1,333 @@
+/* Test non-blocking use of the UDP client.
+ 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 <netinet/in.h>
+#include <rpc/clnt.h>
+#include <rpc/svc.h>
+#include <stdbool.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/test-driver.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Test data serialization and deserialization. */
+
+struct test_query
+{
+ uint32_t a;
+ uint32_t b;
+ uint32_t timeout_ms;
+};
+
+static bool_t
+xdr_test_query (XDR *xdrs, void *data, ...)
+{
+ struct test_query *p = data;
+ return xdr_uint32_t (xdrs, &p->a)
+ && xdr_uint32_t (xdrs, &p->b)
+ && xdr_uint32_t (xdrs, &p->timeout_ms);
+}
+
+struct test_response
+{
+ uint32_t server_id;
+ uint32_t seq;
+ uint32_t sum;
+};
+
+static bool_t
+xdr_test_response (XDR *xdrs, void *data, ...)
+{
+ struct test_response *p = data;
+ return xdr_uint32_t (xdrs, &p->server_id)
+ && xdr_uint32_t (xdrs, &p->seq)
+ && xdr_uint32_t (xdrs, &p->sum);
+}
+
+/* Implementation of the test server. */
+
+enum
+ {
+ /* Number of test servers to run. */
+ SERVER_COUNT = 3,
+
+ /* RPC parameters, chosen at random. */
+ PROGNUM = 8242,
+ VERSNUM = 19654,
+
+ /* Main RPC operation. */
+ PROC_ADD = 1,
+
+ /* Request process termination. */
+ PROC_EXIT,
+
+ /* Special exit status to mark successful processing. */
+ EXIT_MARKER = 55,
+ };
+
+/* Set by the parent process to tell test servers apart. */
+static int server_id;
+
+/* Implementation of the test server. */
+static void
+server_dispatch (struct svc_req *request, SVCXPRT *transport)
+{
+ /* Query sequence number. */
+ static uint32_t seq = 0;
+ ++seq;
+ static bool proc_add_seen;
+
+ if (test_verbose)
+ printf ("info: server_dispatch server_id=%d seq=%u rq_proc=%lu\n",
+ server_id, seq, request->rq_proc);
+
+ switch (request->rq_proc)
+ {
+ case PROC_ADD:
+ {
+ struct test_query query;
+ memset (&query, 0xc0, sizeof (query));
+ TEST_VERIFY_EXIT
+ (svc_getargs (transport, xdr_test_query,
+ (void *) &query));
+
+ if (test_verbose)
+ printf (" a=%u b=%u timeout_ms=%u\n",
+ query.a, query.b, query.timeout_ms);
+
+ usleep (query.timeout_ms * 1000);
+
+ struct test_response response =
+ {
+ .server_id = server_id,
+ .seq = seq,
+ .sum = query.a + query.b,
+ };
+ TEST_VERIFY (svc_sendreply (transport, xdr_test_response,
+ (void *) &response));
+ if (test_verbose)
+ printf (" server id %d response seq=%u sent\n", server_id, seq);
+ proc_add_seen = true;
+ }
+ break;
+
+ case PROC_EXIT:
+ TEST_VERIFY (proc_add_seen);
+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL));
+ _exit (EXIT_MARKER);
+ break;
+
+ default:
+ FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc);
+ break;
+ }
+}
+
+/* Return the number seconds since an arbitrary point in time. */
+static double
+get_ticks (void)
+{
+ {
+ struct timespec ts;
+ if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
+ return ts.tv_sec + ts.tv_nsec * 1e-9;
+ }
+ {
+ struct timeval tv;
+ TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0);
+ return tv.tv_sec + tv.tv_usec * 1e-6;
+ }
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ support_enter_network_namespace ();
+
+ /* Information about the test servers. */
+ struct
+ {
+ SVCXPRT *transport;
+ struct sockaddr_in address;
+ pid_t pid;
+ uint32_t xid;
+ } servers[SERVER_COUNT];
+
+ /* Spawn the test servers. */
+ for (int i = 0; i < SERVER_COUNT; ++i)
+ {
+ servers[i].transport = svcudp_create (RPC_ANYSOCK);
+ TEST_VERIFY_EXIT (servers[i].transport != NULL);
+ servers[i].address = (struct sockaddr_in)
+ {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
+ .sin_port = htons (servers[i].transport->xp_port),
+ };
+ servers[i].xid = 0xabcd0101 + i;
+ if (test_verbose)
+ printf ("info: setting up server %d xid=%x on port %d\n",
+ i, servers[i].xid, servers[i].transport->xp_port);
+
+ server_id = i;
+ servers[i].pid = xfork ();
+ if (servers[i].pid == 0)
+ {
+ TEST_VERIFY (svc_register (servers[i].transport,
+ PROGNUM, VERSNUM, server_dispatch, 0));
+ svc_run ();
+ FAIL_EXIT1 ("supposed to be unreachable");
+ }
+ /* We need to close the socket so that we do not accidentally
+ consume the request. */
+ TEST_VERIFY (close (servers[i].transport->xp_sock) == 0);
+ }
+
+
+ /* The following code mirrors what ypbind does. */
+
+ /* Copied from clnt_udp.c (like ypbind). */
+ struct cu_data
+ {
+ int cu_sock;
+ bool_t cu_closeit;
+ struct sockaddr_in cu_raddr;
+ int cu_rlen;
+ struct timeval cu_wait;
+ struct timeval cu_total;
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ u_int cu_xdrpos;
+ u_int cu_sendsz;
+ char *cu_outbuf;
+ u_int cu_recvsz;
+ char cu_inbuf[1];
+ };
+
+ int client_socket = xsocket (AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+ CLIENT *clnt = clntudp_create (&servers[0].address, PROGNUM, VERSNUM,
+ /* 5 seconds per-response timeout. */
+ ((struct timeval) { 5, 0 }),
+ &client_socket);
+ TEST_VERIFY (clnt != NULL);
+ clnt->cl_auth = authunix_create_default ();
+ {
+ struct timeval zero = { 0, 0 };
+ TEST_VERIFY (clnt_control (clnt, CLSET_TIMEOUT, (void *) &zero));
+ }
+
+ /* Poke at internal data structures (like ypbind). */
+ struct cu_data *cu = (struct cu_data *) clnt->cl_private;
+
+ /* Send a ping to each server. */
+ double before_pings = get_ticks ();
+ for (int i = 0; i < SERVER_COUNT; ++i)
+ {
+ if (test_verbose)
+ printf ("info: sending server %d ping\n", i);
+ /* Reset the xid because it is changed by each invocation of
+ clnt_call. Subtract one to compensate for the xid update
+ during the call. */
+ *((u_int32_t *) (cu->cu_outbuf)) = servers[i].xid - 1;
+ cu->cu_raddr = servers[i].address;
+
+ struct test_query query = { .a = 100, .b = i + 1 };
+ if (i == 1)
+ /* Shorter timeout to prefer this server. These timeouts must
+ be much shorter than the 5-second per-response timeout
+ configured with clntudp_create. */
+ query.timeout_ms = 700;
+ else
+ query.timeout_ms = 1400;
+ struct test_response response = { 0 };
+ /* NB: Do not check the return value. The server reply will
+ prove that the call worked. */
+ double before_one_ping = get_ticks ();
+ clnt_call (clnt, PROC_ADD,
+ xdr_test_query, (void *) &query,
+ xdr_test_response, (void *) &response,
+ ((struct timeval) { 0, 0 }));
+ double after_one_ping = get_ticks ();
+ if (test_verbose)
+ printf ("info: non-blocking send took %f seconds\n",
+ after_one_ping - before_one_ping);
+ /* clnt_call should return immediately. Accept some delay in
+ case the process is descheduled. */
+ TEST_VERIFY (after_one_ping - before_one_ping < 0.3);
+ }
+
+ /* Collect the non-blocking response. */
+ if (test_verbose)
+ printf ("info: collecting response\n");
+ struct test_response response = { 0 };
+ TEST_VERIFY
+ (clnt_call (clnt, PROC_ADD, NULL, NULL,
+ xdr_test_response, (void *) &response,
+ ((struct timeval) { 0, 0 })) == RPC_SUCCESS);
+ double after_pings = get_ticks ();
+ if (test_verbose)
+ printf ("info: send/receive took %f seconds\n",
+ after_pings - before_pings);
+ /* Expected timeout is 0.7 seconds. */
+ TEST_VERIFY (0.7 <= after_pings - before_pings);
+ TEST_VERIFY (after_pings - before_pings < 1.2);
+
+ uint32_t xid;
+ memcpy (&xid, &cu->cu_inbuf, sizeof (xid));
+ if (test_verbose)
+ printf ("info: non-blocking response: xid=%x server_id=%u seq=%u sum=%u\n",
+ xid, response.server_id, response.seq, response.sum);
+ /* Check that the reply from the preferred server was used. */
+ TEST_VERIFY (servers[1].xid == xid);
+ TEST_VERIFY (response.server_id == 1);
+ TEST_VERIFY (response.seq == 1);
+ TEST_VERIFY (response.sum == 102);
+
+ auth_destroy (clnt->cl_auth);
+ clnt_destroy (clnt);
+
+ for (int i = 0; i < SERVER_COUNT; ++i)
+ {
+ if (test_verbose)
+ printf ("info: requesting server %d termination\n", i);
+ client_socket = RPC_ANYSOCK;
+ clnt = clntudp_create (&servers[i].address, PROGNUM, VERSNUM,
+ ((struct timeval) { 5, 0 }),
+ &client_socket);
+ TEST_VERIFY_EXIT (clnt != NULL);
+ TEST_VERIFY (clnt_call (clnt, PROC_EXIT,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL,
+ ((struct timeval) { 3, 0 })) == RPC_SUCCESS);
+ clnt_destroy (clnt);
+
+ int status;
+ xwaitpid (servers[i].pid, &status, 0);
+ TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sunrpc/tst-udp-timeout.c b/sunrpc/tst-udp-timeout.c
new file mode 100644
index 0000000000..db9943a03e
--- /dev/null
+++ b/sunrpc/tst-udp-timeout.c
@@ -0,0 +1,402 @@
+/* Test timeout handling in the UDP client.
+ 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 <netinet/in.h>
+#include <rpc/clnt.h>
+#include <rpc/svc.h>
+#include <stdbool.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/test-driver.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Test data serialization and deserialization. */
+
+struct test_query
+{
+ uint32_t a;
+ uint32_t b;
+ uint32_t timeout_ms;
+ uint32_t wait_for_seq;
+ uint32_t garbage_packets;
+};
+
+static bool_t
+xdr_test_query (XDR *xdrs, void *data, ...)
+{
+ struct test_query *p = data;
+ return xdr_uint32_t (xdrs, &p->a)
+ && xdr_uint32_t (xdrs, &p->b)
+ && xdr_uint32_t (xdrs, &p->timeout_ms)
+ && xdr_uint32_t (xdrs, &p->wait_for_seq)
+ && xdr_uint32_t (xdrs, &p->garbage_packets);
+}
+
+struct test_response
+{
+ uint32_t seq;
+ uint32_t sum;
+};
+
+static bool_t
+xdr_test_response (XDR *xdrs, void *data, ...)
+{
+ struct test_response *p = data;
+ return xdr_uint32_t (xdrs, &p->seq)
+ && xdr_uint32_t (xdrs, &p->sum);
+}
+
+/* Implementation of the test server. */
+
+enum
+ {
+ /* RPC parameters, chosen at random. */
+ PROGNUM = 15717,
+ VERSNUM = 13689,
+
+ /* Main RPC operation. */
+ PROC_ADD = 1,
+
+ /* Reset the sequence number. */
+ PROC_RESET_SEQ,
+
+ /* Request process termination. */
+ PROC_EXIT,
+
+ /* Special exit status to mark successful processing. */
+ EXIT_MARKER = 55,
+ };
+
+static void
+server_dispatch (struct svc_req *request, SVCXPRT *transport)
+{
+ /* Query sequence number. */
+ static uint32_t seq = 0;
+ ++seq;
+
+ if (test_verbose)
+ printf ("info: server_dispatch seq=%u rq_proc=%lu\n",
+ seq, request->rq_proc);
+
+ switch (request->rq_proc)
+ {
+ case PROC_ADD:
+ {
+ struct test_query query;
+ memset (&query, 0xc0, sizeof (query));
+ TEST_VERIFY_EXIT
+ (svc_getargs (transport, xdr_test_query,
+ (void *) &query));
+
+ if (test_verbose)
+ printf (" a=%u b=%u timeout_ms=%u wait_for_seq=%u"
+ " garbage_packets=%u\n",
+ query.a, query.b, query.timeout_ms, query.wait_for_seq,
+ query.garbage_packets);
+
+ if (seq < query.wait_for_seq)
+ {
+ /* No response at this point. */
+ if (test_verbose)
+ printf (" skipped response\n");
+ break;
+ }
+
+ if (query.garbage_packets > 0)
+ {
+ int per_packet_timeout;
+ if (query.timeout_ms > 0)
+ per_packet_timeout
+ = query.timeout_ms * 1000 / query.garbage_packets;
+ else
+ per_packet_timeout = 0;
+
+ char buf[20];
+ memset (&buf, 0xc0, sizeof (buf));
+ for (int i = 0; i < query.garbage_packets; ++i)
+ {
+ /* 13 is relatively prime to 20 = sizeof (buf) + 1, so
+ the len variable will cover the entire interval
+ [0, 20] if query.garbage_packets is sufficiently
+ large. */
+ size_t len = (i * 13 + 1) % (sizeof (buf) + 1);
+ TEST_VERIFY (sendto (transport->xp_sock,
+ buf, len, MSG_NOSIGNAL,
+ (struct sockaddr *) &transport->xp_raddr,
+ transport->xp_addrlen) == len);
+ if (per_packet_timeout > 0)
+ usleep (per_packet_timeout);
+ }
+ }
+ else if (query.timeout_ms > 0)
+ usleep (query.timeout_ms * 1000);
+
+ struct test_response response =
+ {
+ .seq = seq,
+ .sum = query.a + query.b,
+ };
+ TEST_VERIFY (svc_sendreply (transport, xdr_test_response,
+ (void *) &response));
+ }
+ break;
+
+ case PROC_RESET_SEQ:
+ seq = 0;
+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL));
+ break;
+
+ case PROC_EXIT:
+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL));
+ _exit (EXIT_MARKER);
+ break;
+
+ default:
+ FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc);
+ break;
+ }
+}
+
+/* Implementation of the test client. */
+
+static struct test_response
+test_call (CLIENT *clnt, int proc, struct test_query query,
+ struct timeval timeout)
+{
+ if (test_verbose)
+ printf ("info: test_call proc=%d timeout=%lu.%06lu\n",
+ proc, (unsigned long) timeout.tv_sec,
+ (unsigned long) timeout.tv_usec);
+ struct test_response response;
+ TEST_VERIFY_EXIT (clnt_call (clnt, proc,
+ xdr_test_query, (void *) &query,
+ xdr_test_response, (void *) &response,
+ timeout)
+ == RPC_SUCCESS);
+ return response;
+}
+
+static void
+test_call_timeout (CLIENT *clnt, int proc, struct test_query query,
+ struct timeval timeout)
+{
+ struct test_response response;
+ TEST_VERIFY (clnt_call (clnt, proc,
+ xdr_test_query, (void *) &query,
+ xdr_test_response, (void *) &response,
+ timeout)
+ == RPC_TIMEDOUT);
+}
+
+/* Complete one regular RPC call to drain the server socket
+ buffer. Resets the sequence number. */
+static void
+test_call_flush (CLIENT *clnt)
+{
+ /* This needs a longer timeout to flush out all pending requests.
+ The choice of 5 seconds is larger than the per-response timeouts
+ requested via the timeout_ms field. */
+ if (test_verbose)
+ printf ("info: flushing pending queries\n");
+ TEST_VERIFY_EXIT (clnt_call (clnt, PROC_RESET_SEQ,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL,
+ ((struct timeval) { 5, 0 }))
+ == RPC_SUCCESS);
+}
+
+/* Return the number seconds since an arbitrary point in time. */
+static double
+get_ticks (void)
+{
+ {
+ struct timespec ts;
+ if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
+ return ts.tv_sec + ts.tv_nsec * 1e-9;
+ }
+ {
+ struct timeval tv;
+ TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0);
+ return tv.tv_sec + tv.tv_usec * 1e-6;
+ }
+}
+
+static void
+test_udp_server (int port)
+{
+ struct sockaddr_in sin =
+ {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK),
+ .sin_port = htons (port)
+ };
+ int sock = RPC_ANYSOCK;
+
+ /* The client uses a 1.5 second timeout for retries. The timeouts
+ are arbitrary, but chosen so that there is a substantial gap
+ between them, but the total time spent waiting is not too
+ large. */
+ CLIENT *clnt = clntudp_create (&sin, PROGNUM, VERSNUM,
+ (struct timeval) { 1, 500 * 1000 },
+ &sock);
+ TEST_VERIFY_EXIT (clnt != NULL);
+
+ /* Basic call/response test. */
+ struct test_response response = test_call
+ (clnt, PROC_ADD,
+ (struct test_query) { .a = 17, .b = 4 },
+ (struct timeval) { 3, 0 });
+ TEST_VERIFY (response.sum == 21);
+ TEST_VERIFY (response.seq == 1);
+
+ /* Check that garbage packets do not interfere with timeout
+ processing. */
+ double before = get_ticks ();
+ response = test_call
+ (clnt, PROC_ADD,
+ (struct test_query) {
+ .a = 19, .b = 4, .timeout_ms = 500, .garbage_packets = 21,
+ },
+ (struct timeval) { 3, 0 });
+ TEST_VERIFY (response.sum == 23);
+ TEST_VERIFY (response.seq == 2);
+ double after = get_ticks ();
+ if (test_verbose)
+ printf ("info: 21 garbage packets took %f seconds\n", after - before);
+ /* Expected timeout is 0.5 seconds. Add some slack in case process
+ scheduling delays processing the query or response, but do not
+ accept a retry (which would happen at 1.5 seconds). */
+ TEST_VERIFY (0.5 <= after - before);
+ TEST_VERIFY (after - before < 1.2);
+ test_call_flush (clnt);
+
+ /* Check that missing a response introduces a 1.5 second timeout, as
+ requested when calling clntudp_create. */
+ before = get_ticks ();
+ response = test_call
+ (clnt, PROC_ADD,
+ (struct test_query) { .a = 170, .b = 40, .wait_for_seq = 2 },
+ (struct timeval) { 3, 0 });
+ TEST_VERIFY (response.sum == 210);
+ TEST_VERIFY (response.seq == 2);
+ after = get_ticks ();
+ if (test_verbose)
+ printf ("info: skipping one response took %f seconds\n",
+ after - before);
+ /* Expected timeout is 1.5 seconds. Do not accept a second retry
+ (which would happen at 3 seconds). */
+ TEST_VERIFY (1.5 <= after - before);
+ TEST_VERIFY (after - before < 2.9);
+ test_call_flush (clnt);
+
+ /* Check that the overall timeout wins against the per-query
+ timeout. */
+ before = get_ticks ();
+ test_call_timeout
+ (clnt, PROC_ADD,
+ (struct test_query) { .a = 170, .b = 41, .wait_for_seq = 2 },
+ (struct timeval) { 0, 750 * 1000 });
+ after = get_ticks ();
+ if (test_verbose)
+ printf ("info: 0.75 second timeout took %f seconds\n",
+ after - before);
+ TEST_VERIFY (0.75 <= after - before);
+ TEST_VERIFY (after - before < 1.4);
+ test_call_flush (clnt);
+
+ for (int with_garbage = 0; with_garbage < 2; ++with_garbage)
+ {
+ /* Check that no response at all causes the client to bail out. */
+ before = get_ticks ();
+ test_call_timeout
+ (clnt, PROC_ADD,
+ (struct test_query) {
+ .a = 170, .b = 40, .timeout_ms = 1200,
+ .garbage_packets = with_garbage * 21
+ },
+ (struct timeval) { 0, 750 * 1000 });
+ after = get_ticks ();
+ if (test_verbose)
+ printf ("info: test_udp_server: 0.75 second timeout took %f seconds"
+ " (garbage %d)\n",
+ after - before, with_garbage);
+ TEST_VERIFY (0.75 <= after - before);
+ TEST_VERIFY (after - before < 1.4);
+ test_call_flush (clnt);
+
+ /* As above, but check the total timeout. */
+ before = get_ticks ();
+ test_call_timeout
+ (clnt, PROC_ADD,
+ (struct test_query) {
+ .a = 170, .b = 40, .timeout_ms = 3000,
+ .garbage_packets = with_garbage * 30
+ },
+ (struct timeval) { 2, 300 * 1000 });
+ after = get_ticks ();
+ if (test_verbose)
+ printf ("info: test_udp_server: 2.3 second timeout took %f seconds"
+ " (garbage %d)\n",
+ after - before, with_garbage);
+ TEST_VERIFY (2.3 <= after - before);
+ TEST_VERIFY (after - before < 3.0);
+ test_call_flush (clnt);
+ }
+
+ TEST_VERIFY_EXIT (clnt_call (clnt, PROC_EXIT,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL,
+ ((struct timeval) { 5, 0 }))
+ == RPC_SUCCESS);
+ clnt_destroy (clnt);
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ support_enter_network_namespace ();
+
+ SVCXPRT *transport = svcudp_create (RPC_ANYSOCK);
+ TEST_VERIFY_EXIT (transport != NULL);
+ TEST_VERIFY (svc_register (transport, PROGNUM, VERSNUM, server_dispatch, 0));
+
+ pid_t pid = xfork ();
+ if (pid == 0)
+ {
+ svc_run ();
+ FAIL_EXIT1 ("supposed to be unreachable");
+ }
+ test_udp_server (transport->xp_port);
+
+ int status;
+ xwaitpid (pid, &status, 0);
+ TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER);
+
+ SVC_DESTROY (transport);
+ return 0;
+}
+
+/* The minimum run time is around 17 seconds. */
+#define TIMEOUT 25
+#include <support/test-driver.c>
diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h
index a74083786e..5ea8a4a259 100644
--- a/sysdeps/generic/unsecvars.h
+++ b/sysdeps/generic/unsecvars.h
@@ -16,6 +16,7 @@
"LD_DEBUG\0" \
"LD_DEBUG_OUTPUT\0" \
"LD_DYNAMIC_WEAK\0" \
+ "LD_HWCAP_MASK\0" \
"LD_LIBRARY_PATH\0" \
"LD_ORIGIN_PATH\0" \
"LD_PRELOAD\0" \
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
index 339c7bb771..787b95f502 100644
--- a/sysdeps/hppa/dl-machine.h
+++ b/sysdeps/hppa/dl-machine.h
@@ -302,6 +302,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
#define ARCH_LA_PLTENTER hppa_gnu_pltenter
#define ARCH_LA_PLTEXIT hppa_gnu_pltexit
+/* Adjust DL_STACK_END to get value we want in __libc_stack_end. */
+#define DL_STACK_END(cookie) \
+ ((void *) (((long) (cookie)) + 0x160))
+
/* Initial entry point code for the dynamic linker.
The C function `_dl_start' is the real entry point;
its return value is the user program's entry point. */
@@ -401,11 +405,6 @@ asm ( \
/* Save the entry point in %r3. */ \
" copy %ret0,%r3\n" \
\
- /* Remember the lowest stack address. */ \
-" addil LT'__libc_stack_end,%r19\n" \
-" ldw RT'__libc_stack_end(%r1),%r20\n" \
-" stw %sp,0(%r20)\n" \
- \
/* See if we were called as a command with the executable file \
name as an extra leading argument. */ \
" addil LT'_dl_skip_args,%r19\n" \
diff --git a/sysdeps/i386/i686/multiarch/memchr-sse2.S b/sysdeps/i386/i686/multiarch/memchr-sse2.S
index 910679cfc0..e41f324a77 100644
--- a/sysdeps/i386/i686/multiarch/memchr-sse2.S
+++ b/sysdeps/i386/i686/multiarch/memchr-sse2.S
@@ -117,7 +117,6 @@ L(crosscache):
# ifndef USE_AS_RAWMEMCHR
jnz L(match_case2_prolog1)
- lea -16(%edx), %edx
/* Calculate the last acceptable address and check for possible
addition overflow by using satured math:
edx = ecx + edx
@@ -125,6 +124,7 @@ L(crosscache):
add %ecx, %edx
sbb %eax, %eax
or %eax, %edx
+ sub $16, %edx
jbe L(return_null)
lea 16(%edi), %edi
# else
diff --git a/sysdeps/i386/i686/multiarch/strcspn-c.c b/sysdeps/i386/i686/multiarch/strcspn-c.c
index 6d61e190a8..ec230fb383 100644
--- a/sysdeps/i386/i686/multiarch/strcspn-c.c
+++ b/sysdeps/i386/i686/multiarch/strcspn-c.c
@@ -1,2 +1,4 @@
-#define __strcspn_sse2 __strcspn_ia32
-#include <sysdeps/x86_64/multiarch/strcspn-c.c>
+#if IS_IN (libc)
+# define __strcspn_sse2 __strcspn_ia32
+# include <sysdeps/x86_64/multiarch/strcspn-c.c>
+#endif
diff --git a/sysdeps/i386/i686/multiarch/varshift.c b/sysdeps/i386/i686/multiarch/varshift.c
index 7760b966e2..6742a35d41 100644
--- a/sysdeps/i386/i686/multiarch/varshift.c
+++ b/sysdeps/i386/i686/multiarch/varshift.c
@@ -1 +1,3 @@
-#include <sysdeps/x86_64/multiarch/varshift.c>
+#if IS_IN (libc)
+# include <sysdeps/x86_64/multiarch/varshift.c>
+#endif
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
index db6d721fce..4bb87e2331 100644
--- a/sysdeps/nptl/fork.c
+++ b/sysdeps/nptl/fork.c
@@ -131,10 +131,6 @@ __libc_fork (void)
call_function_static_weak (__malloc_fork_lock_parent);
}
-#ifndef NDEBUG
- pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
-#endif
-
#ifdef ARCH_FORK
pid = ARCH_FORK ();
#else
@@ -147,8 +143,6 @@ __libc_fork (void)
{
struct pthread *self = THREAD_SELF;
- assert (THREAD_GETMEM (self, tid) != ppid);
-
/* See __pthread_once. */
if (__fork_generation_pointer != NULL)
*__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR;
@@ -230,8 +224,6 @@ __libc_fork (void)
}
else
{
- assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid);
-
/* Release acquired locks in the multi-threaded case. */
if (multiple_threads)
{
diff --git a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data
index cca17f1e34..1f0e3b494e 100644
--- a/sysdeps/unix/sysv/linux/alpha/localplt.data
+++ b/sysdeps/unix/sysv/linux/alpha/localplt.data
@@ -20,7 +20,7 @@ libc.so: free + RELA R_ALPHA_GLOB_DAT
libc.so: malloc + RELA R_ALPHA_GLOB_DAT
libc.so: memalign + RELA R_ALPHA_GLOB_DAT
libc.so: realloc + RELA R_ALPHA_GLOB_DAT
-libm.so: matherr
+libm.so: matherr + RELA R_ALPHA_GLOB_DAT
# We used to offer inline functions that used this, so it must be exported.
# Ought to reorg things such that carg isn't thus forced to use a plt.
libm.so: __atan2
diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data
index 2c2584956d..8ea4333846 100644
--- a/sysdeps/unix/sysv/linux/i386/localplt.data
+++ b/sysdeps/unix/sysv/linux/i386/localplt.data
@@ -6,7 +6,7 @@ libc.so: free + REL R_386_GLOB_DAT
libc.so: malloc + REL R_386_GLOB_DAT
libc.so: memalign + REL R_386_GLOB_DAT
libc.so: realloc + REL R_386_GLOB_DAT
-libm.so: matherr
+libm.so: matherr + REL R_386_GLOB_DAT
# The main malloc is interposed into the dynamic linker, for
# allocations after the initial link (when dlopen is used).
ld.so: malloc + REL R_386_GLOB_DAT
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
index 2daf0c5ef0..29d8f25ab5 100644
--- a/sysdeps/unix/sysv/linux/spawni.c
+++ b/sysdeps/unix/sysv/linux/spawni.c
@@ -61,17 +61,18 @@
#define SPAWN_ERROR 127
#ifdef __ia64__
-# define CLONE(__fn, __stack, __stacksize, __flags, __args) \
- __clone2 (__fn, __stack, __stacksize, __flags, __args, 0, 0, 0)
+# define CLONE(__fn, __stackbase, __stacksize, __flags, __args) \
+ __clone2 (__fn, __stackbase, __stacksize, __flags, __args, 0, 0, 0)
#else
# define CLONE(__fn, __stack, __stacksize, __flags, __args) \
__clone (__fn, __stack, __flags, __args)
#endif
-#if _STACK_GROWS_DOWN
-# define STACK(__stack, __stack_size) (__stack + __stack_size)
-#elif _STACK_GROWS_UP
+/* Since ia64 wants the stackbase w/clone2, re-use the grows-up macro. */
+#if _STACK_GROWS_UP || defined (__ia64__)
# define STACK(__stack, __stack_size) (__stack)
+#elif _STACK_GROWS_DOWN
+# define STACK(__stack, __stack_size) (__stack + __stack_size)
#endif
@@ -318,6 +319,11 @@ __spawnix (pid_t * pid, const char *file,
/* Add a slack area for child's stack. */
size_t argv_size = (argc * sizeof (void *)) + 512;
+ /* We need at least a few pages in case the compiler's stack checking is
+ enabled. In some configs, it is known to use at least 24KiB. We use
+ 32KiB to be "safe" from anything the compiler might do. Besides, the
+ extra pages won't actually be allocated unless they get used. */
+ argv_size += (32 * 1024);
size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
void *stack = __mmap (NULL, stack_size, prot,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index 1c714a4017..9afd74c42e 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -139,8 +139,6 @@ init_cpu_features (struct cpu_features *cpu_features)
case 0x57:
/* Knights Landing. Enable Silvermont optimizations. */
- cpu_features->feature[index_arch_Prefer_No_VZEROUPPER]
- |= bit_arch_Prefer_No_VZEROUPPER;
case 0x5c:
case 0x5f:
@@ -226,6 +224,16 @@ init_cpu_features (struct cpu_features *cpu_features)
cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
|= bit_arch_AVX_Fast_Unaligned_Load;
+ /* Since AVX512ER is unique to Xeon Phi, set Prefer_No_VZEROUPPER
+ if AVX512ER is available. Don't use AVX512 to avoid lower CPU
+ frequency if AVX512ER isn't available. */
+ if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
+ cpu_features->feature[index_arch_Prefer_No_VZEROUPPER]
+ |= bit_arch_Prefer_No_VZEROUPPER;
+ else
+ cpu_features->feature[index_arch_Prefer_No_AVX512]
+ |= bit_arch_Prefer_No_AVX512;
+
/* To avoid SSE transition penalty, use _dl_runtime_resolve_slow.
If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. */
cpu_features->feature[index_arch_Use_dl_runtime_resolve_slow]
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index 95f0fcff87..a409db67d8 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -39,6 +39,7 @@
#define bit_arch_Prefer_ERMS (1 << 19)
#define bit_arch_Use_dl_runtime_resolve_opt (1 << 20)
#define bit_arch_Use_dl_runtime_resolve_slow (1 << 21)
+#define bit_arch_Prefer_No_AVX512 (1 << 22)
/* CPUID Feature flags. */
@@ -62,6 +63,11 @@
#define bit_cpu_AVX2 (1 << 5)
#define bit_cpu_AVX512F (1 << 16)
#define bit_cpu_AVX512DQ (1 << 17)
+#define bit_cpu_AVX512PF (1 << 26)
+#define bit_cpu_AVX512ER (1 << 27)
+#define bit_cpu_AVX512CD (1 << 28)
+#define bit_cpu_AVX512BW (1 << 30)
+#define bit_cpu_AVX512VL (1u << 31)
/* XCR0 Feature flags. */
#define bit_XMM_state (1 << 1)
@@ -111,6 +117,7 @@
# define index_arch_Prefer_ERMS FEATURE_INDEX_1*FEATURE_SIZE
# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1*FEATURE_SIZE
# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1*FEATURE_SIZE
+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1*FEATURE_SIZE
# if defined (_LIBC) && !IS_IN (nonlib)
@@ -236,6 +243,11 @@ extern const struct cpu_features *__get_cpu_features (void)
# define index_cpu_AVX2 COMMON_CPUID_INDEX_7
# define index_cpu_AVX512F COMMON_CPUID_INDEX_7
# define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7
+# define index_cpu_AVX512PF COMMON_CPUID_INDEX_7
+# define index_cpu_AVX512ER COMMON_CPUID_INDEX_7
+# define index_cpu_AVX512CD COMMON_CPUID_INDEX_7
+# define index_cpu_AVX512BW COMMON_CPUID_INDEX_7
+# define index_cpu_AVX512VL COMMON_CPUID_INDEX_7
# define index_cpu_ERMS COMMON_CPUID_INDEX_7
# define index_cpu_RTM COMMON_CPUID_INDEX_7
# define index_cpu_FMA COMMON_CPUID_INDEX_1
@@ -254,6 +266,11 @@ extern const struct cpu_features *__get_cpu_features (void)
# define reg_AVX2 ebx
# define reg_AVX512F ebx
# define reg_AVX512DQ ebx
+# define reg_AVX512PF ebx
+# define reg_AVX512ER ebx
+# define reg_AVX512CD ebx
+# define reg_AVX512BW ebx
+# define reg_AVX512VL ebx
# define reg_ERMS ebx
# define reg_RTM ebx
# define reg_FMA ecx
@@ -283,6 +300,7 @@ extern const struct cpu_features *__get_cpu_features (void)
# define index_arch_Prefer_ERMS FEATURE_INDEX_1
# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1
# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1
#endif /* !__ASSEMBLER__ */
diff --git a/sysdeps/x86/fpu/test-math-vector-sincos.h b/sysdeps/x86/fpu/test-math-vector-sincos.h
index 5043b32563..95282a3ac7 100644
--- a/sysdeps/x86/fpu/test-math-vector-sincos.h
+++ b/sysdeps/x86/fpu/test-math-vector-sincos.h
@@ -17,14 +17,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define INIT_VEC_PTRS_LOOP(vec, val, len) \
- do \
- { \
- for (i = 0; i < len; i++) \
- { \
- vec[i] = &val[i]; \
- } \
- } \
+#define INIT_VEC_PTRS_LOOP(vec, val, len) \
+ do \
+ { \
+ union { VEC_INT_TYPE v; __typeof__ ((val)[0]) *a[(len)]; } u; \
+ for (i = 0; i < len; i++) \
+ u.a[i] = &(val)[i]; \
+ (vec) = u.v; \
+ } \
while (0)
/* Wrapper for vector sincos/sincosf compatible with x86_64 and x32 variants
@@ -40,8 +40,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \
VEC_TYPE mx; \
VEC_INT_TYPE mr, mr1; \
INIT_VEC_LOOP (mx, x, VEC_LEN); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN); \
+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN); \
+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN); \
vector_func (mx, mr, mr1); \
TEST_VEC_LOOP (r_loc, VEC_LEN); \
TEST_VEC_LOOP (r1_loc, VEC_LEN); \
@@ -63,8 +63,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \
VEC_TYPE mx; \
VEC_INT_TYPE mr, mr1; \
INIT_VEC_LOOP (mx, x, VEC_LEN); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN/2); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN/2); \
+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN/2); \
+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN/2); \
vector_func (mx, mr, mr, mr1, mr1); \
TEST_VEC_LOOP (r_loc, VEC_LEN/2); \
TEST_VEC_LOOP (r1_loc, VEC_LEN/2); \
@@ -87,8 +87,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \
VEC_TYPE mx; \
VEC_INT_TYPE mr, mr1; \
INIT_VEC_LOOP (mx, x, VEC_LEN); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN/4); \
- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN/4); \
+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN/4); \
+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN/4); \
vector_func (mx, mr, mr, mr, mr, mr1, mr1, mr1, mr1); \
TEST_VEC_LOOP (r_loc, VEC_LEN/4); \
TEST_VEC_LOOP (r1_loc, VEC_LEN/4); \
diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
index 33d7fcf7d0..c14c61aa58 100644
--- a/sysdeps/x86_64/dl-trampoline.S
+++ b/sysdeps/x86_64/dl-trampoline.S
@@ -87,11 +87,9 @@
#endif
#define VEC(i) zmm##i
#define _dl_runtime_resolve _dl_runtime_resolve_avx512
-#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx512_opt
#define _dl_runtime_profile _dl_runtime_profile_avx512
#include "dl-trampoline.h"
#undef _dl_runtime_resolve
-#undef _dl_runtime_resolve_opt
#undef _dl_runtime_profile
#undef VEC
#undef VMOV
@@ -145,4 +143,5 @@
# define VMOV vmovdqu
#endif
#define _dl_runtime_resolve _dl_runtime_resolve_sse_vex
+#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx512_opt
#include "dl-trampoline.h"
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
index b27fa06974..8db24c16ac 100644
--- a/sysdeps/x86_64/dl-trampoline.h
+++ b/sysdeps/x86_64/dl-trampoline.h
@@ -129,19 +129,20 @@ _dl_runtime_resolve_opt:
# YMM state isn't in use.
PRESERVE_BND_REGS_PREFIX
jz _dl_runtime_resolve_sse_vex
-# elif VEC_SIZE == 64
+# elif VEC_SIZE == 16
# For ZMM registers, check if YMM state and ZMM state are in
# use.
andl $(bit_YMM_state | bit_ZMM0_15_state), %r11d
cmpl $bit_YMM_state, %r11d
- # Preserve %xmm0 - %xmm7 registers with the zero upper 384 bits if
- # neither YMM state nor ZMM state are in use.
+ # Preserve %zmm0 - %zmm7 registers if ZMM state is in use.
PRESERVE_BND_REGS_PREFIX
- jl _dl_runtime_resolve_sse_vex
+ jg _dl_runtime_resolve_avx512
# Preserve %ymm0 - %ymm7 registers with the zero upper 256 bits if
# ZMM state isn't in use.
PRESERVE_BND_REGS_PREFIX
je _dl_runtime_resolve_avx
+ # Preserve %xmm0 - %xmm7 registers with the zero upper 384 bits if
+ # neither YMM state nor ZMM state are in use.
# else
# error Unsupported VEC_SIZE!
# endif
diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data
index 014a9f4554..a1840cff31 100644
--- a/sysdeps/x86_64/localplt.data
+++ b/sysdeps/x86_64/localplt.data
@@ -8,7 +8,7 @@ libc.so: free + RELA R_X86_64_GLOB_DAT
libc.so: malloc + RELA R_X86_64_GLOB_DAT
libc.so: memalign + RELA R_X86_64_GLOB_DAT
libc.so: realloc + RELA R_X86_64_GLOB_DAT
-libm.so: matherr
+libm.so: matherr + RELA R_X86_64_GLOB_DAT
# The main malloc is interposed into the dynamic linker, for
# allocations after the initial link (when dlopen is used).
ld.so: malloc + RELA R_X86_64_GLOB_DAT
diff --git a/sysdeps/x86_64/mempcpy_chk.S b/sysdeps/x86_64/mempcpy_chk.S
index f8a9260e6e..f912291576 100644
--- a/sysdeps/x86_64/mempcpy_chk.S
+++ b/sysdeps/x86_64/mempcpy_chk.S
@@ -19,7 +19,7 @@
#include <sysdep.h>
#include "asm-syntax.h"
-#ifndef PIC
+#ifndef SHARED
/* For libc.so this is defined in memcpy.S.
For libc.a, this is a separate source to avoid
mempcpy bringing in __chk_fail and all routines
diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S
index 1f83ee3e84..af2770397c 100644
--- a/sysdeps/x86_64/multiarch/memcpy.S
+++ b/sysdeps/x86_64/multiarch/memcpy.S
@@ -32,6 +32,8 @@ ENTRY(__new_memcpy)
lea __memcpy_erms(%rip), %RAX_LP
HAS_ARCH_FEATURE (Prefer_ERMS)
jnz 2f
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __memcpy_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/memcpy_chk.S b/sysdeps/x86_64/multiarch/memcpy_chk.S
index 54923420f1..8737fb9755 100644
--- a/sysdeps/x86_64/multiarch/memcpy_chk.S
+++ b/sysdeps/x86_64/multiarch/memcpy_chk.S
@@ -30,6 +30,8 @@
ENTRY(__memcpy_chk)
.type __memcpy_chk, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __memcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/memmove.S b/sysdeps/x86_64/multiarch/memmove.S
index 2021bfc30c..8c534e83e0 100644
--- a/sysdeps/x86_64/multiarch/memmove.S
+++ b/sysdeps/x86_64/multiarch/memmove.S
@@ -30,6 +30,8 @@ ENTRY(__libc_memmove)
lea __memmove_erms(%rip), %RAX_LP
HAS_ARCH_FEATURE (Prefer_ERMS)
jnz 2f
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __memmove_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/memmove_chk.S b/sysdeps/x86_64/multiarch/memmove_chk.S
index 8a252adcae..7870dd0247 100644
--- a/sysdeps/x86_64/multiarch/memmove_chk.S
+++ b/sysdeps/x86_64/multiarch/memmove_chk.S
@@ -29,6 +29,8 @@
ENTRY(__memmove_chk)
.type __memmove_chk, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __memmove_chk_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/mempcpy.S b/sysdeps/x86_64/multiarch/mempcpy.S
index 79c840d075..b8b2b28094 100644
--- a/sysdeps/x86_64/multiarch/mempcpy.S
+++ b/sysdeps/x86_64/multiarch/mempcpy.S
@@ -32,6 +32,8 @@ ENTRY(__mempcpy)
lea __mempcpy_erms(%rip), %RAX_LP
HAS_ARCH_FEATURE (Prefer_ERMS)
jnz 2f
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __mempcpy_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/mempcpy_chk.S b/sysdeps/x86_64/multiarch/mempcpy_chk.S
index 6927962e81..072b22c49f 100644
--- a/sysdeps/x86_64/multiarch/mempcpy_chk.S
+++ b/sysdeps/x86_64/multiarch/mempcpy_chk.S
@@ -30,6 +30,8 @@
ENTRY(__mempcpy_chk)
.type __mempcpy_chk, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 1f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 1f
lea __mempcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/memset.S b/sysdeps/x86_64/multiarch/memset.S
index c958b2f49f..9d33118cf8 100644
--- a/sysdeps/x86_64/multiarch/memset.S
+++ b/sysdeps/x86_64/multiarch/memset.S
@@ -41,6 +41,8 @@ ENTRY(memset)
jnz L(AVX512F)
lea __memset_avx2_unaligned(%rip), %RAX_LP
L(AVX512F):
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 2f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 2f
lea __memset_avx512_no_vzeroupper(%rip), %RAX_LP
diff --git a/sysdeps/x86_64/multiarch/memset_chk.S b/sysdeps/x86_64/multiarch/memset_chk.S
index 79eaa37bb6..7e08311cdf 100644
--- a/sysdeps/x86_64/multiarch/memset_chk.S
+++ b/sysdeps/x86_64/multiarch/memset_chk.S
@@ -38,6 +38,8 @@ ENTRY(__memset_chk)
jnz L(AVX512F)
lea __memset_chk_avx2_unaligned(%rip), %RAX_LP
L(AVX512F):
+ HAS_ARCH_FEATURE (Prefer_No_AVX512)
+ jnz 2f
HAS_ARCH_FEATURE (AVX512F_Usable)
jz 2f
lea __memset_chk_avx512_no_vzeroupper(%rip), %RAX_LP