From 2d5de23aa1b5074b7505581690643fbd0a6c0d4e Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Mon, 5 Apr 2021 14:06:29 +0200 Subject: [PATCH] glibc: updated patch --- ...{glibc-2.32-2.patch => glibc-2.32-3.patch} | 2400 ++++++++++++++++- 1 file changed, 2338 insertions(+), 62 deletions(-) rename glibc/{glibc-2.32-2.patch => glibc-2.32-3.patch} (54%) diff --git a/glibc/glibc-2.32-2.patch b/glibc/glibc-2.32-3.patch similarity index 54% rename from glibc/glibc-2.32-2.patch rename to glibc/glibc-2.32-3.patch index 53476d2..8195ec3 100644 --- a/glibc/glibc-2.32-2.patch +++ b/glibc/glibc-2.32-3.patch @@ -1,25 +1,374 @@ diff --git a/NEWS b/NEWS -index 485b8ddffa..3030735839 100644 +index 485b8ddffa..f278041512 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,17 @@ See the end for copying conditions. +@@ -5,6 +5,25 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. +The following bugs are resolved with this release: + ++ [20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT ++ [26224] iconv hangs when converting some invalid inputs from several IBM ++ character sets (CVE-2020-27618) + [26534] libm.so 2.32 SIGILL in pow() due to FMA4 instruction on non-FMA4 + system + [26555] string: strerrorname_np does not return the documented value ++ [26600] Transaction ID collisions cause slow DNS lookups in getaddrinfo + [26636] libc: 32-bit shmctl(IPC_INFO) crashes when shminfo struct is + at the end of a memory mapping + [26637] libc: semctl SEM_STAT_ANY fails to pass the buffer specified + by the caller to the kernel + [26639] libc: msgctl IPC_INFO and MSG_INFO return garbage ++ [26853] aarch64: Missing unwind information in statically linked startup code ++ [26932] libc: sh: Multiple floating point functions defined as stubs only ++ [27130] "rep movsb" performance issue ++ [27177] GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on doesn't work + Version 2.32 Major new features: +@@ -185,6 +204,10 @@ Security related changes: + Dytrych of the Cisco Security Assessment and Penetration Team (See + TALOS-2020-1019). + ++ CVE-2020-27618: An infinite loop has been fixed in the iconv program when ++ invoked with input containing redundant shift sequences in the IBM1364, ++ IBM1371, IBM1388, IBM1390, or IBM1399 character sets. ++ + The following bugs are resolved with this release: + + [9809] localedata: ckb_IQ: new Kurdish Sorani locale +diff --git a/Rules b/Rules +index 8b771f6095..beab969fde 100644 +--- a/Rules ++++ b/Rules +@@ -155,6 +155,7 @@ xtests: tests $(xtests-special) + else + tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \ + $(tests-container:%=$(objpfx)%.out) \ ++ $(tests-mcheck:%=$(objpfx)%-mcheck.out) \ + $(tests-special) $(tests-printers-out) + xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) + endif +@@ -165,7 +166,7 @@ ifeq ($(run-built-tests),no) + tests-expected = + else + tests-expected = $(tests) $(tests-internal) $(tests-printers) \ +- $(tests-container) ++ $(tests-container) $(tests-mcheck:%=%-mcheck) + endif + tests: + $(..)scripts/merge-test-results.sh -s $(objpfx) $(subdir) \ +@@ -191,6 +192,7 @@ else + binaries-pie-tests = + binaries-pie-notests = + endif ++binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck) + else + binaries-all-notests = + binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) +@@ -200,6 +202,7 @@ binaries-static-tests = + binaries-static = + binaries-pie-tests = + binaries-pie-notests = ++binaries-mcheck-tests = + endif + + binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests) +@@ -223,6 +226,14 @@ $(addprefix $(objpfx),$(binaries-shared-tests)): %: %.o \ + $(+link-tests) + endif + ++ifneq "$(strip $(binaries-mcheck-tests))" "" ++$(addprefix $(objpfx),$(binaries-mcheck-tests)): %-mcheck: %.o \ ++ $(link-extra-libs-tests) \ ++ $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \ ++ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) ++ $(+link-tests) ++endif ++ + ifneq "$(strip $(binaries-pie-tests))" "" + $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \ + $(link-extra-libs-tests) \ +@@ -253,6 +264,12 @@ $(addprefix $(objpfx),$(binaries-static-tests)): %: %.o \ + $(+link-static-tests) + endif + ++# All mcheck tests will be run with MALLOC_CHECK_=3 ++define mcheck-ENVS ++$(1)-mcheck-ENV = MALLOC_CHECK_=3 ++endef ++$(foreach t,$(tests-mcheck),$(eval $(call mcheck-ENVS,$(t)))) ++ + ifneq "$(strip $(tests) $(tests-internal) $(xtests) $(test-srcs))" "" + # These are the implicit rules for making test outputs + # from the test programs and whatever input files are present. +diff --git a/debug/Makefile b/debug/Makefile +index 3a60d7af7a..0036edd187 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -51,7 +51,7 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \ + explicit_bzero_chk \ + stack_chk_fail fortify_fail \ + $(static-only-routines) +-static-only-routines := warning-nop stack_chk_fail_local ++static-only-routines := stack_chk_fail_local + + # Don't add stack_chk_fail_local.o to libc.a since __stack_chk_fail_local + # is an alias of __stack_chk_fail in stack_chk_fail.o. +diff --git a/debug/warning-nop.c b/debug/warning-nop.c +deleted file mode 100644 +index 4ab7e182b7..0000000000 +--- a/debug/warning-nop.c ++++ /dev/null +@@ -1,70 +0,0 @@ +-/* Dummy nop functions to elicit link-time warnings. +- Copyright (C) 2005-2020 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. +- +- In addition to the permissions in the GNU Lesser General Public +- License, the Free Software Foundation gives you unlimited +- permission to link the compiled version of this file with other +- programs, and to distribute those programs without any restriction +- coming from the use of this file. (The GNU Lesser General Public +- License restrictions do apply in other respects; for example, they +- cover modification of the file, and distribution when not linked +- into another program.) +- +- Note that people who make modified versions of this file are not +- obligated to grant this special exception for their modified +- versions; it is their choice whether to do so. The GNU Lesser +- General Public License gives permission to release a modified +- version without this exception; this exception also makes it +- possible to release a modified version which carries forward this +- exception. +- +- 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 +- . */ +- +-#include +- +-static void +-__attribute__ ((used)) +-nop (void) +-{ +-} +- +-/* Don't insert any other #include's before this #undef! */ +- +-#undef __warndecl +-#define __warndecl(name, msg) \ +- extern void name (void) __attribute__ ((alias ("nop"))) attribute_hidden; \ +- link_warning (name, msg) +- +-#undef __USE_FORTIFY_LEVEL +-#define __USE_FORTIFY_LEVEL 99 +- +-/* Following here we need an #include for each public header file +- that uses __warndecl. */ +- +-/* Define away to avoid warnings with compilers that do not have these +- builtins. */ +-#define __builtin___memcpy_chk(dest, src, len, bos) NULL +-#define __builtin___memmove_chk(dest, src, len, bos) NULL +-#define __builtin___mempcpy_chk(dest, src, len, bos) NULL +-#define __builtin___memset_chk(dest, ch, len, bos) NULL +-#define __builtin___stpcpy_chk(dest, src, bos) NULL +-#define __builtin___strcat_chk(dest, src, bos) NULL +-#define __builtin___strcpy_chk(dest, src, bos) NULL +-#define __builtin___strncat_chk(dest, src, len, bos) NULL +-#define __builtin___strncpy_chk(dest, src, len, bos) NULL +-#define __builtin_object_size(bos, level) 0 +- +-#include +diff --git a/elf/Makefile b/elf/Makefile +index 0b78721848..355e70037b 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1381,6 +1381,8 @@ CFLAGS-ifuncmain7pie.c += $(pie-ccflag) + CFLAGS-ifuncmain9pie.c += $(pie-ccflag) + CFLAGS-tst-ifunc-textrel.c += $(pic-ccflag) + ++LDFLAGS-ifuncmain6pie = -Wl,-z,lazy ++ + $(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so + $(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o + $(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so +diff --git a/elf/dl-load.c b/elf/dl-load.c +index e39980fb19..71867e7c1a 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -855,10 +855,12 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l, + + /* Process PT_GNU_PROPERTY program header PH in module L after + PT_LOAD segments are mapped. Only one NT_GNU_PROPERTY_TYPE_0 +- note is handled which contains processor specific properties. */ ++ note is handled which contains processor specific properties. ++ FD is -1 for the kernel mapped main executable otherwise it is ++ the fd used for loading module L. */ + + void +-_dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph) ++_dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph) + { + const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr); + const ElfW(Addr) size = ph->p_memsz; +@@ -905,7 +907,7 @@ _dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph) + last_type = type; + + /* Target specific property processing. */ +- if (_dl_process_gnu_property (l, type, datasz, ptr) == 0) ++ if (_dl_process_gnu_property (l, fd, type, datasz, ptr) == 0) + return; + + /* Check the next property item. */ +@@ -1251,21 +1253,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + maplength, has_holes, loader); + if (__glibc_unlikely (errstring != NULL)) + goto call_lose; +- +- /* Process program headers again after load segments are mapped in +- case processing requires accessing those segments. Scan program +- headers backward so that PT_NOTE can be skipped if PT_GNU_PROPERTY +- exits. */ +- for (ph = &phdr[l->l_phnum]; ph != phdr; --ph) +- switch (ph[-1].p_type) +- { +- case PT_NOTE: +- _dl_process_pt_note (l, &ph[-1]); +- break; +- case PT_GNU_PROPERTY: +- _dl_process_pt_gnu_property (l, &ph[-1]); +- break; +- } + } + + if (l->l_ld == 0) +@@ -1377,6 +1364,21 @@ cannot enable executable stack as shared object requires"); + if (l->l_tls_initimage != NULL) + l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr; + ++ /* Process program headers again after load segments are mapped in ++ case processing requires accessing those segments. Scan program ++ headers backward so that PT_NOTE can be skipped if PT_GNU_PROPERTY ++ exits. */ ++ for (ph = &l->l_phdr[l->l_phnum]; ph != l->l_phdr; --ph) ++ switch (ph[-1].p_type) ++ { ++ case PT_NOTE: ++ _dl_process_pt_note (l, fd, &ph[-1]); ++ break; ++ case PT_GNU_PROPERTY: ++ _dl_process_pt_gnu_property (l, fd, &ph[-1]); ++ break; ++ } ++ + /* We are done mapping in the file. We no longer need the descriptor. */ + if (__glibc_unlikely (__close_nocancel (fd) != 0)) + { +diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c +index 04faeb86ef..4a01906836 100644 +--- a/elf/ifuncmain6pie.c ++++ b/elf/ifuncmain6pie.c +@@ -9,7 +9,6 @@ + #include "ifunc-sel.h" + + typedef int (*foo_p) (void); +-extern foo_p foo_ptr; + + static int + one (void) +@@ -28,20 +27,17 @@ foo_ifunc (void) + } + + extern int foo (void); +-extern foo_p get_foo (void); ++extern int call_foo (void); + extern foo_p get_foo_p (void); + +-foo_p my_foo_ptr = foo; ++foo_p foo_ptr = foo; + + int + main (void) + { + foo_p p; + +- p = get_foo (); +- if (p != foo) +- abort (); +- if ((*p) () != -30) ++ if (call_foo () != -30) + abort (); + + p = get_foo_p (); +@@ -52,12 +48,8 @@ main (void) + + if (foo_ptr != foo) + abort (); +- if (my_foo_ptr != foo) +- abort (); + if ((*foo_ptr) () != -30) + abort (); +- if ((*my_foo_ptr) () != -30) +- abort (); + if (foo () != -30) + abort (); + +diff --git a/elf/ifuncmod6.c b/elf/ifuncmod6.c +index 2e16c1d06d..2f6d0715e6 100644 +--- a/elf/ifuncmod6.c ++++ b/elf/ifuncmod6.c +@@ -4,7 +4,7 @@ extern int foo (void); + + typedef int (*foo_p) (void); + +-foo_p foo_ptr = foo; ++extern foo_p foo_ptr; + + foo_p + get_foo_p (void) +@@ -12,8 +12,8 @@ get_foo_p (void) + return foo_ptr; + } + +-foo_p +-get_foo (void) ++int ++call_foo (void) + { +- return foo; ++ return foo (); + } +diff --git a/elf/rtld.c b/elf/rtld.c +index 5b882163fa..14a42ed00a 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1534,10 +1534,10 @@ of this helper program; chances are you did not intend to run this program.\n\ + switch (ph[-1].p_type) + { + case PT_NOTE: +- _dl_process_pt_note (main_map, &ph[-1]); ++ _dl_process_pt_note (main_map, -1, &ph[-1]); + break; + case PT_GNU_PROPERTY: +- _dl_process_pt_gnu_property (main_map, &ph[-1]); ++ _dl_process_pt_gnu_property (main_map, -1, &ph[-1]); + break; + } + diff --git a/iconv/Versions b/iconv/Versions index 8a5f4cf780..d51af52fa3 100644 --- a/iconv/Versions @@ -149,6 +498,425 @@ index b4334faa57..d59979759c 100644 if (res != __GCONV_OK) { +diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh +index 8298136b7f..d8db7b335c 100644 +--- a/iconv/tst-iconv_prog.sh ++++ b/iconv/tst-iconv_prog.sh +@@ -102,12 +102,16 @@ hangarray=( + "\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE" + "\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE" + "\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE" +-# These are known hangs that are yet to be fixed: +-# "\x00\x0f;-c;IBM1364;UTF-8" +-# "\x00\x0f;-c;IBM1371;UTF-8" +-# "\x00\x0f;-c;IBM1388;UTF-8" +-# "\x00\x0f;-c;IBM1390;UTF-8" +-# "\x00\x0f;-c;IBM1399;UTF-8" ++"\x00\x0f;-c;IBM1364;UTF-8" ++"\x0e\x0e;-c;IBM1364;UTF-8" ++"\x00\x0f;-c;IBM1371;UTF-8" ++"\x0e\x0e;-c;IBM1371;UTF-8" ++"\x00\x0f;-c;IBM1388;UTF-8" ++"\x0e\x0e;-c;IBM1388;UTF-8" ++"\x00\x0f;-c;IBM1390;UTF-8" ++"\x0e\x0e;-c;IBM1390;UTF-8" ++"\x00\x0f;-c;IBM1399;UTF-8" ++"\x0e\x0e;-c;IBM1399;UTF-8" + "\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE" + "\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE" + "\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE" +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index 4ec2741cdc..4eef07557e 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -73,7 +73,8 @@ modules.so := $(addsuffix .so, $(modules)) + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ +- bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 ++ bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \ ++ bug-iconv13 bug-iconv14 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -321,6 +322,8 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) + $(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) ++$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ ++ $(addprefix $(objpfx),$(modules.so)) + + $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) \ +diff --git a/iconvdata/bug-iconv13.c b/iconvdata/bug-iconv13.c +new file mode 100644 +index 0000000000..87aaff398e +--- /dev/null ++++ b/iconvdata/bug-iconv13.c +@@ -0,0 +1,53 @@ ++/* bug 24973: Test EUC-KR module ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* 0xfe (->0x7e : row 94) and 0xc9 (->0x49 : row 41) are user-defined ++ areas, which are not allowed and should be skipped over due to ++ //IGNORE. The trailing 0xfe also is an incomplete sequence, which ++ should be checked first. */ ++ char input[4] = { '\xc9', '\xa1', '\0', '\xfe' }; ++ char *inptr = input; ++ size_t insize = sizeof (input); ++ char output[4]; ++ char *outptr = output; ++ size_t outsize = sizeof (output); ++ ++ /* This used to crash due to buffer overrun. */ ++ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); ++ TEST_VERIFY (errno == EINVAL); ++ /* The conversion should produce one character, the converted null ++ character. */ ++ TEST_VERIFY (sizeof (output) - outsize == 1); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include +diff --git a/iconvdata/bug-iconv14.c b/iconvdata/bug-iconv14.c +new file mode 100644 +index 0000000000..902f140fa9 +--- /dev/null ++++ b/iconvdata/bug-iconv14.c +@@ -0,0 +1,127 @@ ++/* Assertion in ISO-2022-JP-3 due to two-character sequence (bug 27256). ++ Copyright (C) 2021 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* Use an escape sequence to return to the initial state. */ ++static void ++with_escape_sequence (void) ++{ ++ iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (c != (iconv_t) -1); ++ ++ char in[] = "\e$(O+D\e(B"; ++ char *inbuf = in; ++ size_t inleft = strlen (in); ++ char out[3]; /* Space for one output character. */ ++ char *outbuf; ++ size_t outleft; ++ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ TEST_COMPARE (inleft, 3); ++ TEST_COMPARE (inbuf - in, strlen (in) - 3); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xc3); ++ TEST_COMPARE (out[1] & 0xff, 0xa6); ++ ++ /* Return to the initial shift state, producing the pending ++ character. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), 0); ++ TEST_COMPARE (inleft, 0); ++ TEST_COMPARE (inbuf - in, strlen (in)); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ /* Nothing should be flushed the second time. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out)); ++ TEST_COMPARE (outbuf - out, 0); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ TEST_COMPARE (iconv_close (c), 0); ++} ++ ++/* Use an explicit flush to return to the initial state. */ ++static void ++with_flush (void) ++{ ++ iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (c != (iconv_t) -1); ++ ++ char in[] = "\e$(O+D"; ++ char *inbuf = in; ++ size_t inleft = strlen (in); ++ char out[3]; /* Space for one output character. */ ++ char *outbuf; ++ size_t outleft; ++ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ TEST_COMPARE (inleft, 0); ++ TEST_COMPARE (inbuf - in, strlen (in)); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xc3); ++ TEST_COMPARE (out[1] & 0xff, 0xa6); ++ ++ /* Flush the pending character. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ /* Nothing should be flushed the second time. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out)); ++ TEST_COMPARE (outbuf - out, 0); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ TEST_COMPARE (iconv_close (c), 0); ++} ++ ++static int ++do_test (void) ++{ ++ with_escape_sequence (); ++ with_flush (); ++ return 0; ++} ++ ++#include +diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c +index b0d56cf3ee..1045bae926 100644 +--- a/iconvdata/euc-kr.c ++++ b/iconvdata/euc-kr.c +@@ -80,11 +80,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp) + \ + if (ch <= 0x9f) \ + ++inptr; \ +- /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ +- user-defined areas. */ \ +- else if (__builtin_expect (ch == 0xa0, 0) \ +- || __builtin_expect (ch > 0xfe, 0) \ +- || __builtin_expect (ch == 0xc9, 0)) \ ++ else if (__glibc_unlikely (ch == 0xa0)) \ + { \ + /* This is illegal. */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (1); \ +diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c +index 49e7267ab4..521f0825b7 100644 +--- a/iconvdata/ibm1364.c ++++ b/iconvdata/ibm1364.c +@@ -158,24 +158,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c +index 8c3b7e627e..62cbc54a11 100644 +--- a/iconvdata/iso-2022-jp-3.c ++++ b/iconvdata/iso-2022-jp-3.c +@@ -67,23 +67,34 @@ enum + CURRENT_SEL_MASK = 7 << 3 + }; + +-/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the state +- also contains the last two bytes to be output, shifted by 6 bits, and a +- one-bit indicator whether they must be preceded by the shift sequence, +- in bit 22. */ ++/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the ++ state also contains the last two bytes to be output, shifted by 6 ++ bits, and a one-bit indicator whether they must be preceded by the ++ shift sequence, in bit 22. During ISO-2022-JP-3 to UCS-4 ++ conversion, COUNT may also contain a non-zero pending wide ++ character, shifted by six bits. This happens for certain inputs in ++ JISX0213_1_2004_set and JISX0213_2_set if the second wide character ++ in a combining sequence cannot be written because the buffer is ++ full. */ + + /* Since this is a stateful encoding we have to provide code which resets + the output state to the initial state. This has to be done during the + flushing. */ + #define EMIT_SHIFT_TO_INIT \ +- if ((data->__statep->__count & ~7) != ASCII_set) \ ++ if (data->__statep->__count != ASCII_set) \ + { \ + if (FROM_DIRECTION) \ + { \ +- /* It's easy, we don't have to emit anything, we just reset the \ +- state for the input. */ \ +- data->__statep->__count &= 7; \ +- data->__statep->__count |= ASCII_set; \ ++ if (__glibc_likely (outbuf + 4 <= outend)) \ ++ { \ ++ /* Write out the last character. */ \ ++ *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ ++ outbuf += sizeof (uint32_t); \ ++ data->__statep->__count = ASCII_set; \ ++ } \ ++ else \ ++ /* We don't have enough room in the output buffer. */ \ ++ status = __GCONV_FULL_OUTPUT; \ + } \ + else \ + { \ +@@ -151,7 +162,21 @@ enum + #define LOOPFCT FROM_LOOP + #define BODY \ + { \ +- uint32_t ch = *inptr; \ ++ uint32_t ch; \ ++ \ ++ /* Output any pending character. */ \ ++ ch = set >> 6; \ ++ if (__glibc_unlikely (ch != 0)) \ ++ { \ ++ put32 (outptr, ch); \ ++ outptr += 4; \ ++ /* Remove the pending character, but preserve state bits. */ \ ++ set &= (1 << 6) - 1; \ ++ continue; \ ++ } \ ++ \ ++ /* Otherwise read the next input byte. */ \ ++ ch = *inptr; \ + \ + /* Recognize escape sequences. */ \ + if (__glibc_unlikely (ch == ESC)) \ +@@ -297,21 +322,25 @@ enum + uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0]; \ + uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1]; \ + \ ++ inptr += 2; \ ++ \ ++ put32 (outptr, u1); \ ++ outptr += 4; \ ++ \ + /* See whether we have room for two characters. */ \ +- if (outptr + 8 <= outend) \ ++ if (outptr + 4 <= outend) \ + { \ +- inptr += 2; \ +- put32 (outptr, u1); \ +- outptr += 4; \ + put32 (outptr, u2); \ + outptr += 4; \ + continue; \ + } \ +- else \ +- { \ +- result = __GCONV_FULL_OUTPUT; \ +- break; \ +- } \ ++ \ ++ /* Otherwise store only the first character now, and \ ++ put the second one into the queue. */ \ ++ set |= u2 << 6; \ ++ /* Tell the caller why we terminate the loop. */ \ ++ result = __GCONV_FULL_OUTPUT; \ ++ break; \ + } \ + \ + inptr += 2; \ +diff --git a/iconvdata/ksc5601.h b/iconvdata/ksc5601.h +index d3eb3a4ff8..f5cdc72797 100644 +--- a/iconvdata/ksc5601.h ++++ b/iconvdata/ksc5601.h +@@ -50,15 +50,15 @@ ksc5601_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset) + unsigned char ch2; + int idx; + ++ if (avail < 2) ++ return 0; ++ + /* row 94(0x7e) and row 41(0x49) are user-defined area in KS C 5601 */ + + if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e + || (ch - offset) == 0x49) + return __UNKNOWN_10646_CHAR; + +- if (avail < 2) +- return 0; +- + ch2 = (*s)[1]; + if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f) + return __UNKNOWN_10646_CHAR; diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 2e7c662bc7..bd332e71da 100644 --- a/intl/dcigettext.c @@ -237,6 +1005,549 @@ index fd70432eca..e9f6e5e09f 100644 -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include +diff --git a/malloc/Makefile b/malloc/Makefile +index e22cbde22d..5093e8730e 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -62,6 +62,16 @@ endif + tests += $(tests-static) + test-srcs = tst-mtrace + ++# These tests either are run with MALLOC_CHECK_=3 by default or do not work ++# with MALLOC_CHECK_=3 because they expect a specific failure. ++tests-exclude-mcheck = tst-mcheck tst-malloc-usable \ ++ tst-interpose-nothread tst-interpose-static-nothread \ ++ tst-interpose-static-thread tst-malloc-too-large \ ++ tst-mxfast tst-safe-linking ++ ++# Run all tests with MALLOC_CHECK_=3 ++tests-mcheck = $(filter-out $(tests-exclude-mcheck),$(tests)) ++ + routines = malloc morecore mcheck mtrace obstack reallocarray \ + scratch_buffer_grow scratch_buffer_grow_preserve \ + scratch_buffer_set_array_size \ +@@ -100,6 +110,11 @@ $(objpfx)tst-malloc-thread-exit: $(shared-thread-library) + $(objpfx)tst-malloc-thread-fail: $(shared-thread-library) + $(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library) + $(objpfx)tst-malloc-stats-cancellation: $(shared-thread-library) ++$(objpfx)tst-malloc-backtrace-mcheck: $(shared-thread-library) ++$(objpfx)tst-malloc-thread-exit-mcheck: $(shared-thread-library) ++$(objpfx)tst-malloc-thread-fail-mcheck: $(shared-thread-library) ++$(objpfx)tst-malloc-fork-deadlock-mcheck: $(shared-thread-library) ++$(objpfx)tst-malloc-stats-cancellation-mcheck: $(shared-thread-library) + + # Export the __malloc_initialize_hook variable to libc.so. + LDFLAGS-tst-mallocstate = -rdynamic +@@ -239,6 +254,8 @@ $(tests:%=$(objpfx)%.o): CPPFLAGS += -DTEST_NO_MALLOPT + $(objpfx)tst-interpose-nothread: $(objpfx)tst-interpose-aux-nothread.o + $(objpfx)tst-interpose-thread: \ + $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library) ++$(objpfx)tst-interpose-thread-mcheck: \ ++ $(objpfx)tst-interpose-aux-thread.o $(shared-thread-library) + $(objpfx)tst-interpose-static-nothread: $(objpfx)tst-interpose-aux-nothread.o + $(objpfx)tst-interpose-static-thread: \ + $(objpfx)tst-interpose-aux-thread.o $(static-thread-library) +@@ -256,3 +273,6 @@ $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out + $(objpfx)tst-malloc-tcache-leak: $(shared-thread-library) + $(objpfx)tst-malloc_info: $(shared-thread-library) + $(objpfx)tst-mallocfork2: $(shared-thread-library) ++$(objpfx)tst-malloc-tcache-leak-mcheck: $(shared-thread-library) ++$(objpfx)tst-malloc_info-mcheck: $(shared-thread-library) ++$(objpfx)tst-mallocfork2-mcheck: $(shared-thread-library) +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 23ef0d40e7..d72d7a5ec0 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -432,7 +432,11 @@ set shared cache size in bytes for use in memory and string routines. + + @deftp Tunable glibc.cpu.x86_non_temporal_threshold + The @code{glibc.cpu.x86_non_temporal_threshold} tunable allows the user +-to set threshold in bytes for non temporal store. ++to set threshold in bytes for non temporal store. Non temporal stores ++give a hint to the hardware to move data directly to memory without ++displacing other data from the cache. This tunable is used by some ++platforms to determine when to use non temporal stores in operations ++like memmove and memcpy. + + This tunable is specific to i386 and x86-64. + @end deftp +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 19d9cc5cfe..38221d0b2a 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -124,13 +124,10 @@ + #define __bos0(ptr) __builtin_object_size (ptr, 0) + + #if __GNUC_PREREQ (4,3) +-# define __warndecl(name, msg) \ +- extern void name (void) __attribute__((__warning__ (msg))) + # define __warnattr(msg) __attribute__((__warning__ (msg))) + # define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) + #else +-# define __warndecl(name, msg) extern void name (void) + # define __warnattr(msg) + # define __errordecl(name, msg) extern void name (void) + #endif +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 88c69d1e9c..381aa721ef 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + : NULL); + ndomain = (ndomain ? newbuf + ndomaindiff + : NULL); +- buffer = newbuf; ++ *tofreep = buffer = newbuf; + } + + nhost = memcpy (buffer + bufused, +@@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { + buflen *= 2; +- buffer = xrealloc (buffer, buflen); ++ *tofreep = buffer = xrealloc (buffer, buflen); + } + else if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND +diff --git a/resolv/Makefile b/resolv/Makefile +index b61c0c3e0c..dbd8f8bf4f 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -61,6 +61,11 @@ tests += \ + tst-resolv-search \ + tst-resolv-trailing \ + ++# This test calls __res_context_send directly, which is not exported ++# from libresolv. ++tests-internal += tst-resolv-txnid-collision ++tests-static += tst-resolv-txnid-collision ++ + # These tests need libdl. + ifeq (yes,$(build-shared)) + tests += \ +@@ -191,6 +196,8 @@ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \ ++ $(static-thread-library) + $(objpfx)tst-resolv-canonname: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-trustad: $(objpfx)libresolv.so $(shared-thread-library) +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 7e5fec6646..70e5066031 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1342,15 +1342,6 @@ send_dg(res_state statp, + *terrno = EMSGSIZE; + return close_and_return_error (statp, resplen2); + } +- if ((recvresp1 || hp->id != anhp->id) +- && (recvresp2 || hp2->id != anhp->id)) { +- /* +- * response from old query, ignore it. +- * XXX - potential security hazard could +- * be detected here. +- */ +- goto wait; +- } + + /* Paranoia check. Due to the connected UDP socket, + the kernel has already filtered invalid addresses +@@ -1360,15 +1351,24 @@ send_dg(res_state statp, + + /* Check for the correct header layout and a matching + question. */ +- if ((recvresp1 || !res_queriesmatch(buf, buf + buflen, +- *thisansp, +- *thisansp +- + *thisanssizp)) +- && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2, +- *thisansp, +- *thisansp +- + *thisanssizp))) +- goto wait; ++ int matching_query = 0; /* Default to no matching query. */ ++ if (!recvresp1 ++ && anhp->id == hp->id ++ && res_queriesmatch (buf, buf + buflen, ++ *thisansp, *thisansp + *thisanssizp)) ++ matching_query = 1; ++ if (!recvresp2 ++ && anhp->id == hp2->id ++ && res_queriesmatch (buf2, buf2 + buflen2, ++ *thisansp, *thisansp + *thisanssizp)) ++ matching_query = 2; ++ if (matching_query == 0) ++ /* Spurious UDP packet. Drop it and continue ++ waiting. */ ++ { ++ need_recompute = 1; ++ goto wait; ++ } + + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || +@@ -1383,7 +1383,7 @@ send_dg(res_state statp, + /* No data from the first reply. */ + resplen = 0; + /* We are waiting for a possible second reply. */ +- if (hp->id == anhp->id) ++ if (matching_query == 1) + recvresp1 = 1; + else + recvresp2 = 1; +@@ -1414,7 +1414,7 @@ send_dg(res_state statp, + return (1); + } + /* Mark which reply we received. */ +- if (recvresp1 == 0 && hp->id == anhp->id) ++ if (matching_query == 1) + recvresp1 = 1; + else + recvresp2 = 1; +diff --git a/resolv/tst-resolv-txnid-collision.c b/resolv/tst-resolv-txnid-collision.c +new file mode 100644 +index 0000000000..189b76f126 +--- /dev/null ++++ b/resolv/tst-resolv-txnid-collision.c +@@ -0,0 +1,334 @@ ++/* Test parallel queries with transaction ID collisions. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Result of parsing a DNS question name. ++ ++ A question name has the form reorder-N-M-rcode-C.example.net, where ++ N and M are either 0 and 1, corresponding to the reorder member, ++ and C is a number that will be stored in the rcode field. ++ ++ Also see parse_qname below. */ ++struct parsed_qname ++{ ++ /* The DNS response code requested from the first server. The ++ second server always responds with RCODE zero. */ ++ int rcode; ++ ++ /* Indicates whether to perform reordering in the responses from the ++ respective server. */ ++ bool reorder[2]; ++}; ++ ++/* Fills *PARSED based on QNAME. */ ++static void ++parse_qname (struct parsed_qname *parsed, const char *qname) ++{ ++ int reorder0; ++ int reorder1; ++ int rcode; ++ char *suffix; ++ if (sscanf (qname, "reorder-%d-%d.rcode-%d.%ms", ++ &reorder0, &reorder1, &rcode, &suffix) == 4) ++ { ++ if (reorder0 != 0) ++ TEST_COMPARE (reorder0, 1); ++ if (reorder1 != 0) ++ TEST_COMPARE (reorder1, 1); ++ TEST_VERIFY (rcode >= 0 && rcode <= 15); ++ TEST_COMPARE_STRING (suffix, "example.net"); ++ free (suffix); ++ ++ parsed->rcode = rcode; ++ parsed->reorder[0] = reorder0; ++ parsed->reorder[1] = reorder1; ++ } ++ else ++ FAIL_EXIT1 ("unexpected query: %s", qname); ++} ++ ++/* Used to construct a response. The first server responds with an ++ error, the second server succeeds. */ ++static void ++build_response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ struct parsed_qname parsed; ++ parse_qname (&parsed, qname); ++ ++ switch (ctx->server_index) ++ { ++ case 0: ++ { ++ struct resolv_response_flags flags = { 0 }; ++ if (parsed.rcode == 0) ++ /* Simulate a delegation in case a NODATA (RCODE zero) ++ response is requested. */ ++ flags.clear_ra = true; ++ else ++ flags.rcode = parsed.rcode; ++ ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ } ++ break; ++ ++ case 1: ++ { ++ struct resolv_response_flags flags = { 0, }; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ ++ resolv_response_section (b, ns_s_an); ++ resolv_response_open_record (b, qname, qclass, qtype, 0); ++ if (qtype == T_A) ++ { ++ char ipv4[4] = { 192, 0, 2, 1 }; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ } ++ else ++ { ++ char ipv6[16] ++ = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ++ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); ++ } ++ resolv_response_close_record (b); ++ } ++ break; ++ } ++} ++ ++/* Used to reorder responses. */ ++struct resolv_response_context *previous_query; ++ ++/* Used to keep track of the queries received. */ ++static int previous_server_index = -1; ++static uint16_t previous_qtype; ++ ++/* For each server, buffer the first query and then send both answers ++ to the second query, reordered if requested. */ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ TEST_VERIFY (qtype == T_A || qtype == T_AAAA); ++ if (ctx->server_index != 0) ++ TEST_COMPARE (ctx->server_index, 1); ++ ++ struct parsed_qname parsed; ++ parse_qname (&parsed, qname); ++ ++ if (previous_query == NULL) ++ { ++ /* No buffered query. Record this query and do not send a ++ response. */ ++ TEST_COMPARE (previous_qtype, 0); ++ previous_query = resolv_response_context_duplicate (ctx); ++ previous_qtype = qtype; ++ resolv_response_drop (b); ++ previous_server_index = ctx->server_index; ++ ++ if (test_verbose) ++ printf ("info: buffering first query for: %s\n", qname); ++ } ++ else ++ { ++ TEST_VERIFY (previous_query != 0); ++ TEST_COMPARE (ctx->server_index, previous_server_index); ++ TEST_VERIFY (previous_qtype != qtype); /* Not a duplicate. */ ++ ++ /* If reordering, send a response for this query explicitly, and ++ then skip the implicit send. */ ++ if (parsed.reorder[ctx->server_index]) ++ { ++ if (test_verbose) ++ printf ("info: sending reordered second response for: %s\n", ++ qname); ++ build_response (ctx, b, qname, qclass, qtype); ++ resolv_response_send_udp (ctx, b); ++ resolv_response_drop (b); ++ } ++ ++ /* Build a response for the previous query and send it, thus ++ reordering the two responses. */ ++ { ++ if (test_verbose) ++ printf ("info: sending first response for: %s\n", qname); ++ struct resolv_response_builder *btmp ++ = resolv_response_builder_allocate (previous_query->query_buffer, ++ previous_query->query_length); ++ build_response (ctx, btmp, qname, qclass, previous_qtype); ++ resolv_response_send_udp (ctx, btmp); ++ resolv_response_builder_free (btmp); ++ } ++ ++ /* If not reordering, send the reply as usual. */ ++ if (!parsed.reorder[ctx->server_index]) ++ { ++ if (test_verbose) ++ printf ("info: sending non-reordered second response for: %s\n", ++ qname); ++ build_response (ctx, b, qname, qclass, qtype); ++ } ++ ++ /* Unbuffer the response and prepare for the next query. */ ++ resolv_response_context_free (previous_query); ++ previous_query = NULL; ++ previous_qtype = 0; ++ previous_server_index = -1; ++ } ++} ++ ++/* Runs a query for QNAME and checks for the expected reply. See ++ struct parsed_qname for the expected format for QNAME. */ ++static void ++test_qname (const char *qname, int rcode) ++{ ++ struct resolv_context *ctx = __resolv_context_get (); ++ TEST_VERIFY_EXIT (ctx != NULL); ++ ++ unsigned char q1[512]; ++ int q1len = res_mkquery (QUERY, qname, C_IN, T_A, NULL, 0, NULL, ++ q1, sizeof (q1)); ++ TEST_VERIFY_EXIT (q1len > 12); ++ ++ unsigned char q2[512]; ++ int q2len = res_mkquery (QUERY, qname, C_IN, T_AAAA, NULL, 0, NULL, ++ q2, sizeof (q2)); ++ TEST_VERIFY_EXIT (q2len > 12); ++ ++ /* Produce a transaction ID collision. */ ++ memcpy (q2, q1, 2); ++ ++ unsigned char ans1[512]; ++ unsigned char *ans1p = ans1; ++ unsigned char *ans2p = NULL; ++ int nans2p = 0; ++ int resplen2 = 0; ++ int ans2p_malloced = 0; ++ ++ /* Perform a parallel A/AAAA query. */ ++ int resplen1 = __res_context_send (ctx, q1, q1len, q2, q2len, ++ ans1, sizeof (ans1), &ans1p, ++ &ans2p, &nans2p, ++ &resplen2, &ans2p_malloced); ++ ++ TEST_VERIFY (resplen1 > 12); ++ TEST_VERIFY (resplen2 > 12); ++ if (resplen1 <= 12 || resplen2 <= 12) ++ return; ++ ++ if (rcode == 1 || rcode == 3) ++ { ++ /* Format Error and Name Error responses does not trigger ++ switching to the next server. */ ++ TEST_COMPARE (ans1p[3] & 0x0f, rcode); ++ TEST_COMPARE (ans2p[3] & 0x0f, rcode); ++ return; ++ } ++ ++ /* The response should be successful. */ ++ TEST_COMPARE (ans1p[3] & 0x0f, 0); ++ TEST_COMPARE (ans2p[3] & 0x0f, 0); ++ ++ /* Due to bug 19691, the answer may not be in the slot matching the ++ query. Assume that the AAAA response is the longer one. */ ++ unsigned char *a_answer; ++ int a_answer_length; ++ unsigned char *aaaa_answer; ++ int aaaa_answer_length; ++ if (resplen2 > resplen1) ++ { ++ a_answer = ans1p; ++ a_answer_length = resplen1; ++ aaaa_answer = ans2p; ++ aaaa_answer_length = resplen2; ++ } ++ else ++ { ++ a_answer = ans2p; ++ a_answer_length = resplen2; ++ aaaa_answer = ans1p; ++ aaaa_answer_length = resplen1; ++ } ++ ++ { ++ char *expected = xasprintf ("name: %s\n" ++ "address: 192.0.2.1\n", ++ qname); ++ check_dns_packet (qname, a_answer, a_answer_length, expected); ++ free (expected); ++ } ++ { ++ char *expected = xasprintf ("name: %s\n" ++ "address: 2001:db8::1\n", ++ qname); ++ check_dns_packet (qname, aaaa_answer, aaaa_answer_length, expected); ++ free (expected); ++ } ++ ++ if (ans2p_malloced) ++ free (ans2p); ++ ++ __resolv_context_put (ctx); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ ++ /* The response callback use global state (the previous_* ++ variables), and query processing must therefore be ++ serialized. */ ++ .single_thread_udp = true, ++ }); ++ ++ for (int rcode = 0; rcode <= 5; ++rcode) ++ for (int do_reorder_0 = 0; do_reorder_0 < 2; ++do_reorder_0) ++ for (int do_reorder_1 = 0; do_reorder_1 < 2; ++do_reorder_1) ++ { ++ char *qname = xasprintf ("reorder-%d-%d.rcode-%d.example.net", ++ do_reorder_0, do_reorder_1, rcode); ++ test_qname (qname, rcode); ++ free (qname); ++ } ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 8475fd1f09..eff0c98d82 100644 --- a/stdio-common/Makefile @@ -1002,8 +2313,609 @@ index fded208118..d77b81d507 100644 + TEST_COMPARE_STRING (strerrorname_np (EPROGUNAVAIL), "EPROGUNAVAIL"); +#endif - return 0; + return 0; + } +diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c +index 95b46dcbeb..3a323547f9 100644 +--- a/stdio-common/vfscanf-internal.c ++++ b/stdio-common/vfscanf-internal.c +@@ -277,7 +277,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + #endif + { + va_list arg; +- const CHAR_T *f = format; ++ const UCHAR_T *f = (const UCHAR_T *) format; + UCHAR_T fc; /* Current character of the format. */ + WINT_T done = 0; /* Assignments done. */ + size_t read_in = 0; /* Chars read in. */ +@@ -415,10 +415,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + #endif + + #ifndef COMPILE_WSCANF +- if (!isascii ((unsigned char) *f)) ++ if (!isascii (*f)) + { + /* Non-ASCII, may be a multibyte. */ +- int len = __mbrlen (f, strlen (f), &state); ++ int len = __mbrlen ((const char *) f, strlen ((const char *) f), ++ &state); + if (len > 0) + { + do +@@ -426,7 +427,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + c = inchar (); + if (__glibc_unlikely (c == EOF)) + input_error (); +- else if (c != (unsigned char) *f++) ++ else if (c != *f++) + { + ungetc_not_eof (c, s); + conv_error (); +@@ -484,9 +485,9 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + char_buffer_rewind (&charbuf); + + /* Check for a positional parameter specification. */ +- if (ISDIGIT ((UCHAR_T) *f)) ++ if (ISDIGIT (*f)) + { +- argpos = read_int ((const UCHAR_T **) &f); ++ argpos = read_int (&f); + if (*f == L_('$')) + ++f; + else +@@ -521,8 +522,8 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + + /* Find the maximum field width. */ + width = 0; +- if (ISDIGIT ((UCHAR_T) *f)) +- width = read_int ((const UCHAR_T **) &f); ++ if (ISDIGIT (*f)) ++ width = read_int (&f); + got_width: + if (width == 0) + width = -1; +@@ -2522,12 +2523,11 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, + } + + while ((fc = *f++) != '\0' && fc != ']') +- if (fc == '-' && *f != '\0' && *f != ']' +- && (unsigned char) f[-2] <= (unsigned char) *f) ++ if (fc == '-' && *f != '\0' && *f != ']' && f[-2] <= *f) + { + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ +- for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) ++ for (fc = f[-2]; fc < *f; ++fc) + ((char *)charbuf.scratch.data)[fc] = 1; + } + else +diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h +index 309d0f39b2..c8d3051af8 100644 +--- a/string/bits/string_fortified.h ++++ b/string/bits/string_fortified.h +@@ -22,11 +22,6 @@ + # error "Never use directly; include instead." + #endif + +-#if !__GNUC_PREREQ (5,0) +-__warndecl (__warn_memset_zero_len, +- "memset used with constant zero length parameter; this could be due to transposed parameters"); +-#endif +- + __fortify_function void * + __NTH (memcpy (void *__restrict __dest, const void *__restrict __src, + size_t __len)) +@@ -58,16 +53,6 @@ __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src, + __fortify_function void * + __NTH (memset (void *__dest, int __ch, size_t __len)) + { +- /* GCC-5.0 and newer implements these checks in the compiler, so we don't +- need them here. */ +-#if !__GNUC_PREREQ (5,0) +- if (__builtin_constant_p (__len) && __len == 0 +- && (!__builtin_constant_p (__ch) || __ch != 0)) +- { +- __warn_memset_zero_len (); +- return __dest; +- } +-#endif + return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest)); + } + +diff --git a/support/Makefile b/support/Makefile +index 93faafddf9..4154863511 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -35,6 +35,8 @@ libsupport-routines = \ + ignore_stderr \ + next_to_fault \ + oom_error \ ++ resolv_response_context_duplicate \ ++ resolv_response_context_free \ + resolv_test \ + set_fortify_handler \ + support-xfstat \ +diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c +new file mode 100644 +index 0000000000..f9c5c3462a +--- /dev/null ++++ b/support/resolv_response_context_duplicate.c +@@ -0,0 +1,37 @@ ++/* Duplicate a response context used in DNS resolver tests. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++struct resolv_response_context * ++resolv_response_context_duplicate (const struct resolv_response_context *ctx) ++{ ++ struct resolv_response_context *result = xmalloc (sizeof (*result)); ++ memcpy (result, ctx, sizeof (*result)); ++ if (result->client_address != NULL) ++ { ++ result->client_address = xmalloc (result->client_address_length); ++ memcpy (result->client_address, ctx->client_address, ++ result->client_address_length); ++ } ++ result->query_buffer = xmalloc (result->query_length); ++ memcpy (result->query_buffer, ctx->query_buffer, result->query_length); ++ return result; ++} +diff --git a/support/resolv_response_context_free.c b/support/resolv_response_context_free.c +new file mode 100644 +index 0000000000..b88c05ffd4 +--- /dev/null ++++ b/support/resolv_response_context_free.c +@@ -0,0 +1,28 @@ ++/* Free a response context used in DNS resolver tests. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++void ++resolv_response_context_free (struct resolv_response_context *ctx) ++{ ++ free (ctx->query_buffer); ++ free (ctx->client_address); ++ free (ctx); ++} +diff --git a/support/resolv_test.c b/support/resolv_test.c +index 53b7fc41ab..9878a040a3 100644 +--- a/support/resolv_test.c ++++ b/support/resolv_test.c +@@ -181,7 +181,9 @@ resolv_response_init (struct resolv_response_builder *b, + b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */ + if (flags.tc) + b->buffer[2] |= 0x02; +- b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */ ++ b->buffer[3] = flags.rcode; ++ if (!flags.clear_ra) ++ b->buffer[3] |= 0x80; + if (flags.ad) + b->buffer[3] |= 0x20; + +@@ -434,9 +436,9 @@ resolv_response_buffer (const struct resolv_response_builder *b) + return result; + } + +-static struct resolv_response_builder * +-response_builder_allocate +- (const unsigned char *query_buffer, size_t query_length) ++struct resolv_response_builder * ++resolv_response_builder_allocate (const unsigned char *query_buffer, ++ size_t query_length) + { + struct resolv_response_builder *b = xmalloc (sizeof (*b)); + memset (b, 0, offsetof (struct resolv_response_builder, buffer)); +@@ -445,8 +447,8 @@ response_builder_allocate + return b; + } + +-static void +-response_builder_free (struct resolv_response_builder *b) ++void ++resolv_response_builder_free (struct resolv_response_builder *b) + { + tdestroy (b->compression_offsets, free); + free (b); +@@ -661,13 +663,17 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + + struct resolv_response_context ctx = + { ++ .test = obj, ++ .client_address = &peer, ++ .client_address_length = peerlen, + .query_buffer = query, + .query_length = length, + .server_index = server_index, + .tcp = false, + .edns = qinfo.edns, + }; +- struct resolv_response_builder *b = response_builder_allocate (query, length); ++ struct resolv_response_builder *b ++ = resolv_response_builder_allocate (query, length); + obj->config.response_callback + (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype); + +@@ -684,7 +690,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + if (b->offset >= 12) + printf ("info: UDP server %d: sending response:" + " %zu bytes, RCODE %d (for %s/%u/%u)\n", +- server_index, b->offset, b->buffer[3] & 0x0f, ++ ctx.server_index, b->offset, b->buffer[3] & 0x0f, + qinfo.qname, qinfo.qclass, qinfo.qtype); + else + printf ("info: UDP server %d: sending response: %zu bytes" +@@ -694,23 +700,31 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + if (b->truncate_bytes > 0) + printf ("info: truncated by %u bytes\n", b->truncate_bytes); + } +- size_t to_send = b->offset; +- if (to_send < b->truncate_bytes) +- to_send = 0; +- else +- to_send -= b->truncate_bytes; +- +- /* Ignore most errors here because the other end may have closed +- the socket. */ +- if (sendto (obj->servers[server_index].socket_udp, +- b->buffer, to_send, 0, +- (struct sockaddr *) &peer, peerlen) < 0) +- TEST_VERIFY_EXIT (errno != EBADF); ++ resolv_response_send_udp (&ctx, b); + } +- response_builder_free (b); ++ resolv_response_builder_free (b); + return true; + } + ++void ++resolv_response_send_udp (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b) ++{ ++ TEST_VERIFY_EXIT (!ctx->tcp); ++ size_t to_send = b->offset; ++ if (to_send < b->truncate_bytes) ++ to_send = 0; ++ else ++ to_send -= b->truncate_bytes; ++ ++ /* Ignore most errors here because the other end may have closed ++ the socket. */ ++ if (sendto (ctx->test->servers[ctx->server_index].socket_udp, ++ b->buffer, to_send, 0, ++ ctx->client_address, ctx->client_address_length) < 0) ++ TEST_VERIFY_EXIT (errno != EBADF); ++} ++ + /* UDP thread_callback function. Variant for one thread per + server. */ + static void +@@ -897,14 +911,15 @@ server_thread_tcp_client (void *arg) + + struct resolv_response_context ctx = + { ++ .test = closure->obj, + .query_buffer = query_buffer, + .query_length = query_length, + .server_index = closure->server_index, + .tcp = true, + .edns = qinfo.edns, + }; +- struct resolv_response_builder *b = response_builder_allocate +- (query_buffer, query_length); ++ struct resolv_response_builder *b ++ = resolv_response_builder_allocate (query_buffer, query_length); + closure->obj->config.response_callback + (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype); + +@@ -936,7 +951,7 @@ server_thread_tcp_client (void *arg) + writev_fully (closure->client_socket, buffers, 2); + } + bool close_flag = b->close; +- response_builder_free (b); ++ resolv_response_builder_free (b); + free (query_buffer); + if (close_flag) + break; +diff --git a/support/resolv_test.h b/support/resolv_test.h +index 67819469a0..31a5c1c3e7 100644 +--- a/support/resolv_test.h ++++ b/support/resolv_test.h +@@ -35,25 +35,36 @@ struct resolv_edns_info + uint16_t payload_size; + }; + ++/* This opaque struct collects information about the resolver testing ++ currently in progress. */ ++struct resolv_test; ++ + /* This struct provides context information when the response callback + specified in struct resolv_redirect_config is invoked. */ + struct resolv_response_context + { +- const unsigned char *query_buffer; ++ struct resolv_test *test; ++ void *client_address; ++ size_t client_address_length; ++ unsigned char *query_buffer; + size_t query_length; + int server_index; + bool tcp; + struct resolv_edns_info edns; + }; + ++/* Produces a deep copy of the context. */ ++struct resolv_response_context * ++ resolv_response_context_duplicate (const struct resolv_response_context *); ++ ++/* Frees the copy. For the context passed to the response function, ++ this happens implicitly. */ ++void resolv_response_context_free (struct resolv_response_context *); ++ + /* This opaque struct is used to construct responses from within the + response callback function. */ + struct resolv_response_builder; + +-/* This opaque struct collects information about the resolver testing +- currently in progress. */ +-struct resolv_test; +- + enum + { + /* Maximum number of test servers supported by the framework. */ +@@ -137,6 +148,10 @@ struct resolv_response_flags + /* If true, the AD (authenticated data) flag will be set. */ + bool ad; + ++ /* If true, do not set the RA (recursion available) flag in the ++ response. */ ++ bool clear_ra; ++ + /* Initial section count values. Can be used to artificially + increase the counts, for malformed packet testing.*/ + unsigned short qdcount; +@@ -188,6 +203,22 @@ void resolv_response_close (struct resolv_response_builder *); + /* The size of the response packet built so far. */ + size_t resolv_response_length (const struct resolv_response_builder *); + ++/* Allocates a response builder tied to a specific query packet, ++ starting at QUERY_BUFFER, containing QUERY_LENGTH bytes. */ ++struct resolv_response_builder * ++ resolv_response_builder_allocate (const unsigned char *query_buffer, ++ size_t query_length); ++ ++/* Deallocates a response buffer. */ ++void resolv_response_builder_free (struct resolv_response_builder *); ++ ++/* Sends a UDP response using a specific context. This can be used to ++ reorder or duplicate responses, along with ++ resolv_response_context_duplicate and ++ response_builder_allocate. */ ++void resolv_response_send_udp (const struct resolv_response_context *, ++ struct resolv_response_builder *); ++ + __END_DECLS + + #endif /* SUPPORT_RESOLV_TEST_H */ +diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c +index 196e462520..cf7624aaa2 100644 +--- a/sysdeps/aarch64/dl-bti.c ++++ b/sysdeps/aarch64/dl-bti.c +@@ -19,43 +19,76 @@ + #include + #include + #include ++#include + +-static int +-enable_bti (struct link_map *map, const char *program) ++/* See elf/dl-load.h. */ ++#ifndef MAP_COPY ++# define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE) ++#endif ++ ++/* Enable BTI protection for MAP. */ ++ ++void ++_dl_bti_protect (struct link_map *map, int fd) + { ++ const size_t pagesz = GLRO(dl_pagesize); + const ElfW(Phdr) *phdr; +- unsigned prot; + + for (phdr = map->l_phdr; phdr < &map->l_phdr[map->l_phnum]; ++phdr) + if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) + { +- void *start = (void *) (phdr->p_vaddr + map->l_addr); +- size_t len = phdr->p_memsz; ++ size_t vstart = ALIGN_DOWN (phdr->p_vaddr, pagesz); ++ size_t vend = ALIGN_UP (phdr->p_vaddr + phdr->p_filesz, pagesz); ++ off_t off = ALIGN_DOWN (phdr->p_offset, pagesz); ++ void *start = (void *) (vstart + map->l_addr); ++ size_t len = vend - vstart; + +- prot = PROT_EXEC | PROT_BTI; ++ unsigned prot = PROT_EXEC | PROT_BTI; + if (phdr->p_flags & PF_R) + prot |= PROT_READ; + if (phdr->p_flags & PF_W) + prot |= PROT_WRITE; + +- if (__mprotect (start, len, prot) < 0) +- { +- if (program) +- _dl_fatal_printf ("%s: mprotect failed to turn on BTI\n", +- map->l_name); +- else +- _dl_signal_error (errno, map->l_name, "dlopen", +- N_("mprotect failed to turn on BTI")); +- } ++ if (fd == -1) ++ /* Ignore failures for kernel mapped binaries. */ ++ __mprotect (start, len, prot); ++ else ++ map->l_mach.bti_fail = __mmap (start, len, prot, ++ MAP_FIXED|MAP_COPY|MAP_FILE, ++ fd, off) == MAP_FAILED; + } +- return 0; + } + +-/* Enable BTI for L if required. */ ++ ++static void ++bti_failed (struct link_map *l, const char *program) ++{ ++ if (program) ++ _dl_fatal_printf ("%s: %s: failed to turn on BTI protection\n", ++ program, l->l_name); ++ else ++ /* Note: the errno value is not available any more. */ ++ _dl_signal_error (0, l->l_name, "dlopen", ++ N_("failed to turn on BTI protection")); ++} ++ ++ ++/* Enable BTI for L and its dependencies. */ + + void + _dl_bti_check (struct link_map *l, const char *program) + { +- if (GLRO(dl_aarch64_cpu_features).bti && l->l_mach.bti) +- enable_bti (l, program); ++ if (!GLRO(dl_aarch64_cpu_features).bti) ++ return; ++ ++ if (l->l_mach.bti_fail) ++ bti_failed (l, program); ++ ++ unsigned int i = l->l_searchlist.r_nlist; ++ while (i-- > 0) ++ { ++ struct link_map *dep = l->l_initfini[i]; ++ if (dep->l_mach.bti_fail) ++ bti_failed (dep, program); ++ } + } +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index 70b9ed3925..fde7cfd9e2 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -395,13 +395,6 @@ elf_machine_lazy_rel (struct link_map *map, + /* Check for unexpected PLT reloc type. */ + if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1)) + { +- if (map->l_mach.plt == 0) +- { +- /* Prelinking. */ +- *reloc_addr += l_addr; +- return; +- } +- + if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL)) + { + /* Check the symbol table for variant PCS symbols. */ +@@ -425,7 +418,10 @@ elf_machine_lazy_rel (struct link_map *map, + } + } + +- *reloc_addr = map->l_mach.plt; ++ if (map->l_mach.plt == 0) ++ *reloc_addr += l_addr; ++ else ++ *reloc_addr = map->l_mach.plt; + } + else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1)) + { +diff --git a/sysdeps/aarch64/dl-prop.h b/sysdeps/aarch64/dl-prop.h +index b0785bda83..e926e54984 100644 +--- a/sysdeps/aarch64/dl-prop.h ++++ b/sysdeps/aarch64/dl-prop.h +@@ -19,6 +19,8 @@ + #ifndef _DL_PROP_H + #define _DL_PROP_H + ++extern void _dl_bti_protect (struct link_map *, int) attribute_hidden; ++ + extern void _dl_bti_check (struct link_map *, const char *) + attribute_hidden; + +@@ -35,14 +37,18 @@ _dl_open_check (struct link_map *m) + } + + static inline void __attribute__ ((always_inline)) +-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph) ++_dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph) + { } + + static inline int +-_dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz, +- void *data) ++_dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, ++ uint32_t datasz, void *data) + { ++ if (!GLRO(dl_aarch64_cpu_features).bti) ++ /* Skip note processing. */ ++ return 0; ++ + if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) + { + /* Stop if the property note is ill-formed. */ +@@ -51,7 +57,7 @@ _dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz, + + unsigned int feature_1 = *(unsigned int *) data; + if (feature_1 & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) +- l->l_mach.bti = true; ++ _dl_bti_protect (l, fd); + + /* Stop if we processed the property note. */ + return 0; +diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h +index 847a03ace2..b3f7663b07 100644 +--- a/sysdeps/aarch64/linkmap.h ++++ b/sysdeps/aarch64/linkmap.h +@@ -22,5 +22,5 @@ struct link_map_machine + { + ElfW(Addr) plt; /* Address of .plt */ + void *tlsdesc_table; /* Address of TLS descriptor hash table. */ +- bool bti; /* Branch Target Identification is enabled. */ ++ bool bti_fail; /* Failed to enable Branch Target Identification. */ + }; diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c index 7cf5f033e8..799d60c98c 100644 --- a/sysdeps/aarch64/multiarch/memcpy.c @@ -1053,6 +2965,109 @@ index ad10aa8ac6..46a4cb3a54 100644 ? __memmove_simd : __memmove_generic))))); +diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S +index 75393e1c18..1998ea95d4 100644 +--- a/sysdeps/aarch64/start.S ++++ b/sysdeps/aarch64/start.S +@@ -43,11 +43,9 @@ + */ + + .text +- .globl _start +- .type _start,#function +-_start: +- BTI_C ++ENTRY(_start) + /* Create an initial frame with 0 LR and FP */ ++ cfi_undefined (x30) + mov x29, #0 + mov x30, #0 + +@@ -101,8 +99,10 @@ _start: + because crt1.o and rcrt1.o share code and the later must avoid the + use of GOT relocations before __libc_start_main is called. */ + __wrap_main: ++ BTI_C + b main + #endif ++END(_start) + + /* Define a symbol for the first piece of initialized data. */ + .data +diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h +index f1cf576fe3..df27ff8e6a 100644 +--- a/sysdeps/generic/dl-prop.h ++++ b/sysdeps/generic/dl-prop.h +@@ -37,15 +37,15 @@ _dl_open_check (struct link_map *m) + } + + static inline void __attribute__ ((always_inline)) +-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph) ++_dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph) + { + } + + /* Called for each property in the NT_GNU_PROPERTY_TYPE_0 note of L, + processing of the properties continues until this returns 0. */ + static inline int __attribute__ ((always_inline)) +-_dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz, +- void *data) ++_dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, ++ uint32_t datasz, void *data) + { + return 0; + } +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index ba114ab4b1..62ac40d81b 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -919,8 +919,9 @@ extern void _dl_rtld_di_serinfo (struct link_map *loader, + Dl_serinfo *si, bool counting); + + /* Process PT_GNU_PROPERTY program header PH in module L after +- PT_LOAD segments are mapped. */ +-void _dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph); ++ PT_LOAD segments are mapped from file FD. */ ++void _dl_process_pt_gnu_property (struct link_map *l, int fd, ++ const ElfW(Phdr) *ph); + + + /* Search loaded objects' symbol tables for a definition of the symbol +diff --git a/sysdeps/generic/unwind.h b/sysdeps/generic/unwind.h +index b667a5b652..c229603af3 100644 +--- a/sysdeps/generic/unwind.h ++++ b/sysdeps/generic/unwind.h +@@ -75,15 +75,21 @@ typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + + struct _Unwind_Exception + { +- _Unwind_Exception_Class exception_class; +- _Unwind_Exception_Cleanup_Fn exception_cleanup; +- _Unwind_Word private_1; +- _Unwind_Word private_2; +- +- /* @@@ The IA-64 ABI says that this structure must be double-word aligned. +- Taking that literally does not make much sense generically. Instead we +- provide the maximum alignment required by any type for the machine. */ +-} __attribute__((__aligned__)); ++ union ++ { ++ struct ++ { ++ _Unwind_Exception_Class exception_class; ++ _Unwind_Exception_Cleanup_Fn exception_cleanup; ++ _Unwind_Word private_1; ++ _Unwind_Word private_2; ++ }; ++ ++ /* The IA-64 ABI says that this structure must be double-word aligned. */ ++ _Unwind_Word unwind_exception_align[2] ++ __attribute__ ((__aligned__ (2 * sizeof (_Unwind_Word)))); ++ }; ++}; + + + /* The ACTIONS argument to the personality routine is a bitwise OR of one diff --git a/sysdeps/gnu/errlist.h b/sysdeps/gnu/errlist.h index 5d11ed723d..6329e5f393 100644 --- a/sysdeps/gnu/errlist.h @@ -1942,6 +3957,80 @@ index 5d11ed723d..6329e5f393 100644 -_S(ERR_MAP(EPROGUNAVAIL), N_("RPC program not available")) +_S(EPROGUNAVAIL, N_("RPC program not available")) #endif +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 0f08079e48..672d8f27ce 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -338,16 +338,22 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, + { + # ifndef RTLD_BOOTSTRAP + if (sym_map != map +- && sym_map->l_type != lt_executable + && !sym_map->l_relocated) + { + const char *strtab + = (const char *) D_PTR (map, l_info[DT_STRTAB]); +- _dl_error_printf ("\ ++ if (sym_map->l_type == lt_executable) ++ _dl_fatal_printf ("\ ++%s: IFUNC symbol '%s' referenced in '%s' is defined in the executable \ ++and creates an unsatisfiable circular dependency.\n", ++ RTLD_PROGNAME, strtab + refsym->st_name, ++ map->l_name); ++ else ++ _dl_error_printf ("\ + %s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", +- RTLD_PROGNAME, map->l_name, +- sym_map->l_name, +- strtab + refsym->st_name); ++ RTLD_PROGNAME, map->l_name, ++ sym_map->l_name, ++ strtab + refsym->st_name); + } + # endif + value = ((Elf32_Addr (*) (void)) value) (); +diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c +index 8a53a1088f..362a2b713c 100644 +--- a/sysdeps/powerpc/powerpc64/backtrace.c ++++ b/sysdeps/powerpc/powerpc64/backtrace.c +@@ -54,11 +54,22 @@ struct signal_frame_64 { + /* We don't care about the rest, since the IP value is at 'uc' field. */ + }; + ++/* Test if the address match to the inside the trampoline code. ++ Up to and including kernel 5.8, returning from an interrupt or syscall to a ++ signal handler starts execution directly at the handler's entry point, with ++ LR set to address of the sigreturn trampoline (the vDSO symbol). ++ Newer kernels will branch to signal handler from the trampoline instead, so ++ checking the stacktrace against the vDSO entrypoint does not work in such ++ case. ++ The vDSO branches with a 'bctrl' instruction, so checking either the ++ vDSO address itself and the next instruction should cover all kernel ++ versions. */ + static inline bool + is_sigtramp_address (void *nip) + { + #ifdef HAVE_SIGTRAMP_RT64 +- if (nip == GLRO (dl_vdso_sigtramp_rt64)) ++ if (nip == GLRO (dl_vdso_sigtramp_rt64) || ++ nip == GLRO (dl_vdso_sigtramp_rt64) + 4) + return true; + #endif + return false; +diff --git a/sysdeps/sh/be/sh4/fpu/Implies b/sysdeps/sh/be/sh4/fpu/Implies +new file mode 100644 +index 0000000000..71b28ee1a4 +--- /dev/null ++++ b/sysdeps/sh/be/sh4/fpu/Implies +@@ -0,0 +1 @@ ++sh/sh4/fpu +diff --git a/sysdeps/sh/le/sh4/fpu/Implies b/sysdeps/sh/le/sh4/fpu/Implies +new file mode 100644 +index 0000000000..71b28ee1a4 +--- /dev/null ++++ b/sysdeps/sh/le/sh4/fpu/Implies +@@ -0,0 +1 @@ ++sh/sh4/fpu diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 9b2a253032..34748ffcd1 100644 --- a/sysdeps/unix/sysv/linux/Makefile @@ -1955,23 +4044,6 @@ index 9b2a253032..34748ffcd1 100644 tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables -diff --git a/sysdeps/unix/sysv/linux/aarch64/configure b/sysdeps/unix/sysv/linux/aarch64/configure -index 27d50e1d3c..290670a67a 100644 ---- a/sysdeps/unix/sysv/linux/aarch64/configure -+++ b/sysdeps/unix/sysv/linux/aarch64/configure -@@ -6,10 +6,10 @@ arch_minimum_kernel=3.7.0 - test -n "$libc_cv_slibdir" || - case "$prefix" in - /usr | /usr/) -- libc_cv_slibdir='/lib64' -+ libc_cv_slibdir='/lib' - libc_cv_rtlddir='/lib' - if test "$libdir" = '${exec_prefix}/lib'; then -- libdir='${exec_prefix}/lib64'; -+ libdir='${exec_prefix}/lib'; - # Locale data can be shared between 32-bit and 64-bit libraries. - libc_cv_complocaledir='${exec_prefix}/lib/locale' - fi diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h index fc688450ee..00a4d0c8e7 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h @@ -2079,6 +4151,20 @@ index f131a26fc7..1cdabde8f2 100644 case IPC_INFO: /* arg.__buf */ case SEM_INFO: va_start (ap, cmd); +diff --git a/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies b/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies +new file mode 100644 +index 0000000000..7eeaf15a5a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sh/be/sh4/fpu/Implies +@@ -0,0 +1 @@ ++unix/sysv/linux/sh/sh4/fpu +diff --git a/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies b/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies +new file mode 100644 +index 0000000000..7eeaf15a5a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sh/le/sh4/fpu/Implies +@@ -0,0 +1 @@ ++unix/sysv/linux/sh/sh4/fpu diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c index 76d88441f1..1d19a798b1 100644 --- a/sysdeps/unix/sysv/linux/shmctl.c @@ -2699,49 +4785,165 @@ index 0000000000..7128ae2e14 +} + +#include -diff --git a/sysdeps/unix/sysv/linux/x86_64/64/configure b/sysdeps/unix/sysv/linux/x86_64/64/configure -index 9d298faba7..cef1ec842c 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/64/configure -+++ b/sysdeps/unix/sysv/linux/x86_64/64/configure -@@ -4,10 +4,10 @@ - test -n "$libc_cv_slibdir" || - case "$prefix" in - /usr | /usr/) -- libc_cv_slibdir='/lib64' -- libc_cv_rtlddir='/lib64' -+ libc_cv_slibdir='/lib' -+ libc_cv_rtlddir='/lib' - if test "$libdir" = '${exec_prefix}/lib'; then -- libdir='${exec_prefix}/lib64'; -+ libdir='${exec_prefix}/lib'; - # Locale data can be shared between 32-bit and 64-bit libraries. - libc_cv_complocaledir='${exec_prefix}/lib/locale' - fi -diff --git a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h b/sysdeps/unix/sysv/linux/x86_64/ldconfig.h -index 062c04689d..7783757726 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h -+++ b/sysdeps/unix/sysv/linux/x86_64/ldconfig.h -@@ -18,9 +18,9 @@ - #include +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index a6736aef25..9736a13e7b 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -12,6 +12,12 @@ endif + ifeq ($(subdir),setjmp) + gen-as-const-headers += jmp_buf-ssp.sym + sysdep_routines += __longjmp_cancel ++ifneq ($(enable-cet),no) ++ifneq ($(have-tunables),no) ++tests += tst-setjmp-cet ++tst-setjmp-cet-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on ++endif ++endif + endif - #define SYSDEP_KNOWN_INTERPRETER_NAMES \ -- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \ -+ { "/lib32/ld-linux.so.2", FLAG_ELF_LIBC6 }, \ - { "/libx32/ld-linux-x32.so.2", FLAG_ELF_LIBC6 }, \ -- { "/lib64/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 }, -+ { "/lib/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 }, - #define SYSDEP_KNOWN_LIBRARY_NAMES \ - { "libc.so.6", FLAG_ELF_LIBC6 }, \ - { "libm.so.6", FLAG_ELF_LIBC6 }, -diff --git a/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed -index 44d76e8aa1..7d6cb1e20b 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed -+++ b/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed -@@ -1,3 +1,3 @@ - /LD_TRACE_LOADED_OBJECTS=1/a\ - add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out" --s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\2\4\6 \264\4-x86-64\6 \2x32\4-x32\6"_ -+s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\232\4\6 \2\4-x86-64\6 \2x32\4-x32\6"_ + ifeq ($(subdir),string) +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index 217c21c34f..3fb4a028d8 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -808,7 +808,7 @@ init_cacheinfo (void) + threads = 1 << ((ecx >> 12) & 0x0f); + } + +- if (threads == 0) ++ if (threads == 0 || cpu_features->basic.family >= 0x17) + { + /* If APIC ID width is not available, use logical + processor count. */ +@@ -823,8 +823,22 @@ init_cacheinfo (void) + if (threads > 0) + shared /= threads; + +- /* Account for exclusive L2 and L3 caches. */ +- shared += core; ++ /* Get shared cache per ccx for Zen architectures. */ ++ if (cpu_features->basic.family >= 0x17) ++ { ++ unsigned int eax; ++ ++ /* Get number of threads share the L3 cache in CCX. */ ++ __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx); ++ ++ unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1; ++ shared *= threads_per_ccx; ++ } ++ else ++ { ++ /* Account for exclusive L2 and L3 caches. */ ++ shared += core; ++ } + } + } + +@@ -854,14 +868,20 @@ init_cacheinfo (void) + __x86_shared_cache_size = shared; + } + +- /* The large memcpy micro benchmark in glibc shows that 6 times of +- shared cache size is the approximate value above which non-temporal +- store becomes faster on a 8-core processor. This is the 3/4 of the +- total shared cache size. */ ++ /* The default setting for the non_temporal threshold is 3/4 of one ++ thread's share of the chip's cache. For most Intel and AMD processors ++ with an initial release date between 2017 and 2020, a thread's typical ++ share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4 ++ threshold leaves 125 KBytes to 500 KBytes of the thread's data ++ in cache after a maximum temporal copy, which will maintain ++ in cache a reasonable portion of the thread's stack and other ++ active data. If the threshold is set higher than one thread's ++ share of the cache, it has a substantial risk of negatively ++ impacting the performance of other threads running on the chip. */ + __x86_shared_non_temporal_threshold + = (cpu_features->non_temporal_threshold != 0 + ? cpu_features->non_temporal_threshold +- : __x86_shared_cache_size * threads * 3 / 4); ++ : __x86_shared_cache_size * 3 / 4); + + /* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */ + unsigned int minimum_rep_movsb_threshold; +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index 03572f7af6..3cc54a8d53 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -47,7 +47,10 @@ dl_cet_check (struct link_map *m, const char *program) + /* No legacy object check if both IBT and SHSTK are always on. */ + if (enable_ibt_type == cet_always_on + && enable_shstk_type == cet_always_on) +- return; ++ { ++ THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)); ++ return; ++ } + + /* Check if IBT is enabled by kernel. */ + bool ibt_enabled +diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h +index 89911e19e2..4eb3b85a7b 100644 +--- a/sysdeps/x86/dl-prop.h ++++ b/sysdeps/x86/dl-prop.h +@@ -145,15 +145,15 @@ _dl_process_cet_property_note (struct link_map *l, + } + + static inline void __attribute__ ((unused)) +-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph) ++_dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph) + { + const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr); + _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align); + } + + static inline int __attribute__ ((always_inline)) +-_dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz, +- void *data) ++_dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, ++ uint32_t datasz, void *data) + { + return 0; + } +diff --git a/sysdeps/x86/tst-setjmp-cet.c b/sysdeps/x86/tst-setjmp-cet.c +new file mode 100644 +index 0000000000..42c795d2a8 +--- /dev/null ++++ b/sysdeps/x86/tst-setjmp-cet.c +@@ -0,0 +1 @@ ++#include +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index ca73d8fef9..363a749cb2 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -315,16 +315,22 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + { + # ifndef RTLD_BOOTSTRAP + if (sym_map != map +- && sym_map->l_type != lt_executable + && !sym_map->l_relocated) + { + const char *strtab + = (const char *) D_PTR (map, l_info[DT_STRTAB]); +- _dl_error_printf ("\ ++ if (sym_map->l_type == lt_executable) ++ _dl_fatal_printf ("\ ++%s: IFUNC symbol '%s' referenced in '%s' is defined in the executable \ ++and creates an unsatisfiable circular dependency.\n", ++ RTLD_PROGNAME, strtab + refsym->st_name, ++ map->l_name); ++ else ++ _dl_error_printf ("\ + %s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", +- RTLD_PROGNAME, map->l_name, +- sym_map->l_name, +- strtab + refsym->st_name); ++ RTLD_PROGNAME, map->l_name, ++ sym_map->l_name, ++ strtab + refsym->st_name); + } + # endif + value = ((ElfW(Addr) (*) (void)) value) (); diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h index 7659758972..e5fd5ac9cb 100644 --- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h @@ -2755,6 +4957,46 @@ index 7659758972..e5fd5ac9cb 100644 return OPTIMIZE (fma4); return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +index bd5dc1a3f3..092f364bb6 100644 +--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +@@ -56,6 +56,13 @@ + # endif + #endif + ++/* Avoid short distance rep movsb only with non-SSE vector. */ ++#ifndef AVOID_SHORT_DISTANCE_REP_MOVSB ++# define AVOID_SHORT_DISTANCE_REP_MOVSB (VEC_SIZE > 16) ++#else ++# define AVOID_SHORT_DISTANCE_REP_MOVSB 0 ++#endif ++ + #ifndef PREFETCH + # define PREFETCH(addr) prefetcht0 addr + #endif +@@ -243,7 +250,21 @@ L(movsb): + cmpq %r9, %rdi + /* Avoid slow backward REP MOVSB. */ + jb L(more_8x_vec_backward) ++# if AVOID_SHORT_DISTANCE_REP_MOVSB ++ movq %rdi, %rcx ++ subq %rsi, %rcx ++ jmp 2f ++# endif + 1: ++# if AVOID_SHORT_DISTANCE_REP_MOVSB ++ movq %rsi, %rcx ++ subq %rdi, %rcx ++2: ++/* Avoid "rep movsb" if RCX, the distance between source and destination, ++ is N*4GB + [1..63] with N >= 0. */ ++ cmpl $63, %ecx ++ jbe L(more_2x_vec) /* Avoid "rep movsb" if ECX <= 63. */ ++# endif + mov %RDX_LP, %RCX_LP + rep movsb + L(nop): diff --git a/sysvipc/test-sysvsem.c b/sysvipc/test-sysvsem.c index 01dbff343a..b7284e0b48 100644 --- a/sysvipc/test-sysvsem.c @@ -2777,3 +5019,37 @@ index 83cd196798..e6ca7a8857 100644 -#define RELEASE "release" +#define RELEASE "stable" #define VERSION "2.32" +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/configure b/sysdeps/unix/sysv/linux/x86_64/64/configure +index 9d298faba7..cef1ec842c 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/configure ++++ b/sysdeps/unix/sysv/linux/x86_64/64/configure +@@ -4,10 +4,10 @@ + test -n "$libc_cv_slibdir" || + case "$prefix" in + /usr | /usr/) +- libc_cv_slibdir='/lib64' +- libc_cv_rtlddir='/lib64' ++ libc_cv_slibdir='/lib' ++ libc_cv_rtlddir='/lib' + if test "$libdir" = '${exec_prefix}/lib'; then +- libdir='${exec_prefix}/lib64'; ++ libdir='${exec_prefix}/lib'; + # Locale data can be shared between 32-bit and 64-bit libraries. + libc_cv_complocaledir='${exec_prefix}/lib/locale' + fi +diff --git a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h b/sysdeps/unix/sysv/linux/x86_64/ldconfig.h +index 062c04689d..7783757726 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h ++++ b/sysdeps/unix/sysv/linux/x86_64/ldconfig.h +@@ -18,9 +18,9 @@ + #include + + #define SYSDEP_KNOWN_INTERPRETER_NAMES \ +- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \ ++ { "/lib32/ld-linux.so.2", FLAG_ELF_LIBC6 }, \ + { "/libx32/ld-linux-x32.so.2", FLAG_ELF_LIBC6 }, \ +- { "/lib64/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 }, ++ { "/lib/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 }, + #define SYSDEP_KNOWN_LIBRARY_NAMES \ + { "libc.so.6", FLAG_ELF_LIBC6 }, \ + { "libm.so.6", FLAG_ELF_LIBC6 }, -- 2.26.2