diff options
author | Juergen Daubert <jue@jue.li> | 2022-02-10 19:31:19 +0100 |
---|---|---|
committer | Juergen Daubert <jue@jue.li> | 2022-02-10 19:31:19 +0100 |
commit | c776c651ffcaed27dcff47818b02f5a29442eac2 (patch) | |
tree | a8b3422c9d165d09b78db504d14afe4f067e202e /glibc-32 | |
parent | b09bbfd7165fbef7e82421846b122a4fdf7cdc4a (diff) | |
download | core-c776c651ffcaed27dcff47818b02f5a29442eac2.tar.gz core-c776c651ffcaed27dcff47818b02f5a29442eac2.tar.xz |
glibc-32: update to 2.35
Diffstat (limited to 'glibc-32')
-rw-r--r-- | glibc-32/.footprint | 1 | ||||
-rw-r--r-- | glibc-32/.signature | 12 | ||||
-rw-r--r-- | glibc-32/Pkgfile | 4 | ||||
-rw-r--r-- | glibc-32/glibc-2.34-1.patch | 4419 | ||||
-rw-r--r-- | glibc-32/glibc-2.35-1.patch | 230 |
5 files changed, 238 insertions, 4428 deletions
diff --git a/glibc-32/.footprint b/glibc-32/.footprint index 88c87295..6f994a53 100644 --- a/glibc-32/.footprint +++ b/glibc-32/.footprint @@ -6,7 +6,6 @@ lrwxrwxrwx root/root lib/ld-linux.so.2 -> /lib32/ld-linux.so.2 drwxr-xr-x root/root lib32/ -rwxr-xr-x root/root lib32/ld-linux.so.2 -rwxr-xr-x root/root lib32/libBrokenLocale.so.1 --rwxr-xr-x root/root lib32/libSegFault.so -rwxr-xr-x root/root lib32/libanl.so.1 -rwxr-xr-x root/root lib32/libc.so.6 -rwxr-xr-x root/root lib32/libc_malloc_debug.so.0 diff --git a/glibc-32/.signature b/glibc-32/.signature index 5dcca12b..07e2119f 100644 --- a/glibc-32/.signature +++ b/glibc-32/.signature @@ -1,8 +1,8 @@ untrusted comment: verify with /etc/ports/core.pub -RWRJc1FUaeVeqjMglBs29r0xnkWCM0kkBzI2ipNRYJiVx7kAKgjUOTi7W7bcnMDbNDPmm2007uR8Ap9ycVgMVNkdPHDQjMHoYwM= -SHA256 (Pkgfile) = 1aa584a9e2fb75c2e2b1591e6bc8711ff723e7a62d5956bf05215e5720cd7cf3 -SHA256 (.footprint) = 54c55f2d06c68fe3fb88ea56cdcf13038a41794a90855c8c17e4112d8eb7cbdc -SHA256 (glibc-2.34.tar.xz) = 44d26a1fe20b8853a48f470ead01e4279e869ac149b195dda4e44a195d981ab2 -SHA256 (linux-5.15.11.tar.xz) = c1178b7e7e12d91292e670191268e3fe9a3563faf899eef43e468577e973a1ce -SHA256 (glibc-2.34-1.patch) = 38455bc201d53743b34335464a10d8ab2bfc456e71c49c116a58397ca48c7e2a +RWRJc1FUaeVeqh19lKx4wk8KE2AhxflKslbkarbdSukAiOJ6+8ga9luqkksDm1m7U1Yto0Z7EXUQiCJ7p7fKnn3JpbZkkVeVIgE= +SHA256 (Pkgfile) = fd483db30bbd4bf632ee56d2511724f33edfed5d9bad80ea070d92b53ae58a9f +SHA256 (.footprint) = f676700a19f936a1af944e81a516dbf182723d6ac244eadabd3fd19e9a01daa5 +SHA256 (glibc-2.35.tar.xz) = 5123732f6b67ccd319305efd399971d58592122bcc2a6518a1bd2510dd0cf52e +SHA256 (linux-5.15.21.tar.xz) = 294eeb6cd7dc9b144c3c3c8b8c7b3fca9c6b072b6ed9bf9d6c922f9deb70fbd1 +SHA256 (glibc-2.35-1.patch) = f9041b36bd2194753d43da1053320d58d75acc76cfdcc2bd13e502b247d90b4e SHA256 (lib32.conf) = 2f174d2bcefe1c29327690514f34d6970fffdd54398320ca23a11b5f1e3c9b2d diff --git a/glibc-32/Pkgfile b/glibc-32/Pkgfile index 8df32af0..f7a6e182 100644 --- a/glibc-32/Pkgfile +++ b/glibc-32/Pkgfile @@ -3,9 +3,9 @@ # Maintainer: CRUX System Team, core-ports at crux dot nu name=glibc-32 -version=2.34 +version=2.35 release=1 -_kernel_version=5.15.11 +_kernel_version=5.15.21 source=(https://ftp.gnu.org/gnu/glibc/glibc-$version.tar.xz https://www.kernel.org/pub/linux/kernel/v5.x/linux-$_kernel_version.tar.xz diff --git a/glibc-32/glibc-2.34-1.patch b/glibc-32/glibc-2.34-1.patch deleted file mode 100644 index 19452841..00000000 --- a/glibc-32/glibc-2.34-1.patch +++ /dev/null @@ -1,4419 +0,0 @@ -diff --git a/NEWS b/NEWS -index 3c610744c9..698964bb9e 100644 ---- a/NEWS -+++ b/NEWS -@@ -4,6 +4,25 @@ See the end for copying conditions. - - Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> - using `glibc' in the "product" field. -+ -+Version 2.34.1 -+ -+The following bugs are resolved with this release: -+ -+ [12889] nptl: Fix race between pthread_kill and thread exit -+ [19193] nptl: pthread_kill, pthread_cancel should not fail after exit -+ [28036] Incorrect types for pthread_mutexattr_set/getrobust_np -+ [28182] _TIME_BITS=64 in C++ has issues with fcntl, ioctl, prctl -+ [28310] Do not use affinity mask for sysconf (_SC_NPROCESSORS_CONF) -+ [28340] ld.so crashes while loading a DSO with a read-only dynamic section -+ [28357] deadlock between pthread_create and ELF constructors -+ [28361] nptl: Avoid setxid deadlock with blocked signals in thread exit -+ [28407] pthread_kill assumes that kill and tgkill are equivalent -+ [28524] Conversion from ISO-2022-JP-3 with iconv may emit spurious NULs -+ [28607] Masked signals are delivered on thread exit -+ [28532] powerpc64[le]: CFI for assembly templated syscalls is incorrect -+ [28678] nptl/tst-create1 hangs sporadically -+ - - Version 2.34 - -diff --git a/bits/stdlib-bsearch.h b/bits/stdlib-bsearch.h -index 4132dc6af0..e2fcea6e17 100644 ---- a/bits/stdlib-bsearch.h -+++ b/bits/stdlib-bsearch.h -@@ -29,14 +29,23 @@ bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size, - while (__l < __u) - { - __idx = (__l + __u) / 2; -- __p = (void *) (((const char *) __base) + (__idx * __size)); -+ __p = (const void *) (((const char *) __base) + (__idx * __size)); - __comparison = (*__compar) (__key, __p); - if (__comparison < 0) - __u = __idx; - else if (__comparison > 0) - __l = __idx + 1; - else -- return (void *) __p; -+ { -+#if __GNUC_PREREQ(4, 6) -+# pragma GCC diagnostic push -+# pragma GCC diagnostic ignored "-Wcast-qual" -+#endif -+ return (void *) __p; -+#if __GNUC_PREREQ(4, 6) -+# pragma GCC diagnostic pop -+#endif -+ } - } - - return NULL; -diff --git a/elf/Makefile b/elf/Makefile -index d05f410592..118d579c42 100644 ---- a/elf/Makefile -+++ b/elf/Makefile -@@ -224,7 +224,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ - tst-tls-ie tst-tls-ie-dlmopen argv0test \ - tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ - tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \ -- tst-dl-is_dso -+ tst-dl-is_dso tst-ro-dynamic - # reldep9 - tests-internal += loadtest unload unload2 circleload1 \ - neededtest neededtest2 neededtest3 neededtest4 \ -@@ -357,7 +357,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ - libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ - tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \ - tst-auxvalmod \ -- tst-dlmopen-gethostbyname-mod \ -+ tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \ - - # Most modules build with _ISOMAC defined, but those filtered out - # depend on internal headers. -@@ -399,8 +399,9 @@ endif - modules-execstack-yes = tst-execstack-mod - extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) - --# filtmod1.so, tst-big-note-lib.so have special rules. --modules-names-nobuild := filtmod1 tst-big-note-lib -+# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special -+# rules. -+modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod - - tests += $(tests-static) - -@@ -1906,3 +1907,10 @@ $(objpfx)tst-getauxval-static.out: $(objpfx)tst-auxvalmod.so - tst-getauxval-static-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx) - - $(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so -+ -+$(objpfx)tst-ro-dynamic: $(objpfx)tst-ro-dynamic-mod.so -+$(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \ -+ tst-ro-dynamic-mod.map -+ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ -+ -Wl,--script=tst-ro-dynamic-mod.map \ -+ $(objpfx)tst-ro-dynamic-mod.os -diff --git a/elf/dl-close.c b/elf/dl-close.c -index f39001cab9..cd7b9c9fe8 100644 ---- a/elf/dl-close.c -+++ b/elf/dl-close.c -@@ -549,6 +549,9 @@ _dl_close_worker (struct link_map *map, bool force) - size_t tls_free_end; - tls_free_start = tls_free_end = NO_TLS_OFFSET; - -+ /* Protects global and module specitic TLS state. */ -+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); -+ - /* We modify the list of loaded objects. */ - __rtld_lock_lock_recursive (GL(dl_load_write_lock)); - -@@ -784,6 +787,9 @@ _dl_close_worker (struct link_map *map, bool force) - GL(dl_tls_static_used) = tls_free_start; - } - -+ /* TLS is cleaned up for the unloaded modules. */ -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); -+ - #ifdef SHARED - /* Auditing checkpoint: we have deleted all objects. */ - if (__glibc_unlikely (do_audit)) -diff --git a/elf/dl-load.c b/elf/dl-load.c -index 650e4edc35..0976977fbd 100644 ---- a/elf/dl-load.c -+++ b/elf/dl-load.c -@@ -1130,6 +1130,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, - struct loadcmd loadcmds[l->l_phnum]; - size_t nloadcmds = 0; - bool has_holes = false; -+ bool empty_dynamic = false; - - /* The struct is initialized to zero so this is not necessary: - l->l_ld = 0; -@@ -1142,13 +1143,16 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, - segments are mapped in. We record the addresses it says - verbatim, and later correct for the run-time load address. */ - case PT_DYNAMIC: -- if (ph->p_filesz) -+ if (ph->p_filesz == 0) -+ empty_dynamic = true; /* Usually separate debuginfo. */ -+ else - { - /* Debuginfo only files from "objcopy --only-keep-debug" - contain a PT_DYNAMIC segment with p_filesz == 0. Skip - such a segment to avoid a crash later. */ - l->l_ld = (void *) ph->p_vaddr; - l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); -+ l->l_ld_readonly = (ph->p_flags & PF_W) == 0; - } - break; - -@@ -1264,6 +1268,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, - goto lose; - } - -+ /* This check recognizes most separate debuginfo files. */ -+ if (__glibc_unlikely ((l->l_ld == 0 && type == ET_DYN) || empty_dynamic)) -+ { -+ errstring = N_("object file has no dynamic section"); -+ goto lose; -+ } -+ - /* Length of the sections to be loaded. */ - maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart; - -@@ -1281,18 +1292,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, - } - } - -- if (l->l_ld == 0) -- { -- if (__glibc_unlikely (type == ET_DYN)) -- { -- errstring = N_("object file has no dynamic section"); -- goto lose; -- } -- } -- else -+ if (l->l_ld != 0) - l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr); - -- elf_get_dynamic_info (l, NULL); -+ elf_get_dynamic_info (l); - - /* Make sure we are not dlopen'ing an object that has the - DF_1_NOOPEN flag set, or a PIE object. */ -diff --git a/elf/dl-open.c b/elf/dl-open.c -index ec386626f9..bc68e2c376 100644 ---- a/elf/dl-open.c -+++ b/elf/dl-open.c -@@ -66,6 +66,9 @@ struct dl_open_args - libc_map value in the namespace in case of a dlopen failure. */ - bool libc_already_loaded; - -+ /* Set to true if the end of dl_open_worker_begin was reached. */ -+ bool worker_continue; -+ - /* Original parameters to the program and the current environment. */ - int argc; - char **argv; -@@ -482,7 +485,7 @@ call_dl_init (void *closure) - } - - static void --dl_open_worker (void *a) -+dl_open_worker_begin (void *a) - { - struct dl_open_args *args = a; - const char *file = args->file; -@@ -774,6 +777,36 @@ dl_open_worker (void *a) - _dl_call_libc_early_init (libc_map, false); - } - -+ args->worker_continue = true; -+} -+ -+static void -+dl_open_worker (void *a) -+{ -+ struct dl_open_args *args = a; -+ -+ args->worker_continue = false; -+ -+ { -+ /* Protects global and module specific TLS state. */ -+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); -+ -+ struct dl_exception ex; -+ int err = _dl_catch_exception (&ex, dl_open_worker_begin, args); -+ -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); -+ -+ if (__glibc_unlikely (ex.errstring != NULL)) -+ /* Reraise the error. */ -+ _dl_signal_exception (err, &ex, NULL); -+ } -+ -+ if (!args->worker_continue) -+ return; -+ -+ int mode = args->mode; -+ struct link_map *new = args->map; -+ - /* Run the initializer functions of new objects. Temporarily - disable the exception handler, so that lazy binding failures are - fatal. */ -@@ -886,7 +919,7 @@ no more namespaces available for dlmopen()")); - /* Avoid keeping around a dangling reference to the libc.so link - map in case it has been cached in libc_map. */ - if (!args.libc_already_loaded) -- GL(dl_ns)[nsid].libc_map = NULL; -+ GL(dl_ns)[args.nsid].libc_map = NULL; - - /* Remove the object from memory. It may be in an inconsistent - state if relocation failed, for example. */ -diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c -index d5bd2f31e9..2fb02d7276 100644 ---- a/elf/dl-reloc-static-pie.c -+++ b/elf/dl-reloc-static-pie.c -@@ -40,7 +40,17 @@ _dl_relocate_static_pie (void) - - /* Read our own dynamic section and fill in the info array. */ - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); -- elf_get_dynamic_info (main_map, NULL); -+ -+ const ElfW(Phdr) *ph, *phdr = GL(dl_phdr); -+ size_t phnum = GL(dl_phnum); -+ for (ph = phdr; ph < &phdr[phnum]; ++ph) -+ if (ph->p_type == PT_DYNAMIC) -+ { -+ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0; -+ break; -+ } -+ -+ elf_get_dynamic_info (main_map); - - # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC - ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); -diff --git a/elf/dl-support.c b/elf/dl-support.c -index 0155718175..d8c06ba7eb 100644 ---- a/elf/dl-support.c -+++ b/elf/dl-support.c -@@ -229,6 +229,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock) - list of loaded objects while an object is added to or removed from - that list. */ - __rtld_lock_define_initialized_recursive (, _dl_load_write_lock) -+ /* This lock protects global and module specific TLS related data. -+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), -+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are -+ accessed and when TLS related relocations are processed for a -+ module. It was introduced to keep pthread_create accessing TLS -+ state that is being set up. */ -+__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock) - - - #ifdef HAVE_AUX_VECTOR -diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c -index d47bef1340..2c684c2db2 100644 ---- a/elf/dl-sysdep.c -+++ b/elf/dl-sysdep.c -@@ -317,7 +317,7 @@ _dl_show_auxv (void) - [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex }, - [AT_RANDOM - 2] = { "RANDOM: 0x", hex }, - [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex }, -- [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ ", dec }, -+ [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec }, - [AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec }, - [AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex }, - [AT_L1D_CACHESIZE - 2] = { "L1D_CACHESIZE: ", dec }, -diff --git a/elf/dl-tls.c b/elf/dl-tls.c -index 423e380f7c..40263cf586 100644 ---- a/elf/dl-tls.c -+++ b/elf/dl-tls.c -@@ -532,7 +532,7 @@ _dl_allocate_tls_init (void *result) - size_t maxgen = 0; - - /* Protects global dynamic TLS related state. */ -- __rtld_lock_lock_recursive (GL(dl_load_lock)); -+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); - - /* Check if the current dtv is big enough. */ - if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) -@@ -606,7 +606,7 @@ _dl_allocate_tls_init (void *result) - listp = listp->next; - assert (listp != NULL); - } -- __rtld_lock_unlock_recursive (GL(dl_load_lock)); -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); - - /* The DTV version is up-to-date now. */ - dtv[0].counter = maxgen; -@@ -745,7 +745,7 @@ _dl_update_slotinfo (unsigned long int req_modid) - - Here the dtv needs to be updated to new_gen generation count. - -- This code may be called during TLS access when GL(dl_load_lock) -+ This code may be called during TLS access when GL(dl_load_tls_lock) - is not held. In that case the user code has to synchronize with - dlopen and dlclose calls of relevant modules. A module m is - relevant if the generation of m <= new_gen and dlclose of m is -@@ -867,11 +867,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) - if (__glibc_unlikely (the_map->l_tls_offset - != FORCED_DYNAMIC_TLS_OFFSET)) - { -- __rtld_lock_lock_recursive (GL(dl_load_lock)); -+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); - if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET)) - { - the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET; -- __rtld_lock_unlock_recursive (GL(dl_load_lock)); -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); - } - else if (__glibc_likely (the_map->l_tls_offset - != FORCED_DYNAMIC_TLS_OFFSET)) -@@ -883,7 +883,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) - #else - # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" - #endif -- __rtld_lock_unlock_recursive (GL(dl_load_lock)); -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); - - dtv[GET_ADDR_MODULE].pointer.to_free = NULL; - dtv[GET_ADDR_MODULE].pointer.val = p; -@@ -891,7 +891,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) - return (char *) p + GET_ADDR_OFFSET; - } - else -- __rtld_lock_unlock_recursive (GL(dl_load_lock)); -+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); - } - struct dtv_pointer result = allocate_and_init (the_map); - dtv[GET_ADDR_MODULE].pointer = result; -@@ -962,7 +962,7 @@ _dl_tls_get_addr_soft (struct link_map *l) - return NULL; - - dtv_t *dtv = THREAD_DTV (); -- /* This may be called without holding the GL(dl_load_lock). Reading -+ /* This may be called without holding the GL(dl_load_tls_lock). Reading - arbitrary gen value is fine since this is best effort code. */ - size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); - if (__glibc_unlikely (dtv[0].counter != gen)) -diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h -index d8ec32377d..4aa2058abf 100644 ---- a/elf/get-dynamic-info.h -+++ b/elf/get-dynamic-info.h -@@ -28,7 +28,7 @@ static - auto - #endif - inline void __attribute__ ((unused, always_inline)) --elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) -+elf_get_dynamic_info (struct link_map *l) - { - #if __ELF_NATIVE_CLASS == 32 - typedef Elf32_Word d_tag_utype; -@@ -69,28 +69,15 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) - info[i] = dyn; - } - --#define DL_RO_DYN_TEMP_CNT 8 -- --#ifndef DL_RO_DYN_SECTION - /* Don't adjust .dynamic unnecessarily. */ -- if (l->l_addr != 0) -+ if (l->l_addr != 0 && dl_relocate_ld (l)) - { - ElfW(Addr) l_addr = l->l_addr; -- int cnt = 0; - - # define ADJUST_DYN_INFO(tag) \ - do \ - if (info[tag] != NULL) \ -- { \ -- if (temp) \ -- { \ -- temp[cnt].d_tag = info[tag]->d_tag; \ -- temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \ -- info[tag] = temp + cnt++; \ -- } \ -- else \ -- info[tag]->d_un.d_ptr += l_addr; \ -- } \ -+ info[tag]->d_un.d_ptr += l_addr; \ - while (0) - - ADJUST_DYN_INFO (DT_HASH); -@@ -107,9 +94,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) - ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); - ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH)); - # undef ADJUST_DYN_INFO -- assert (cnt <= DL_RO_DYN_TEMP_CNT); - } --#endif - if (info[DT_PLTREL] != NULL) - { - #if ELF_MACHINE_NO_RELA -diff --git a/elf/ldconfig.c b/elf/ldconfig.c -index 1037e8d0cf..b8893637f8 100644 ---- a/elf/ldconfig.c -+++ b/elf/ldconfig.c -@@ -503,7 +503,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line) - entry->path[--i] = '\0'; - - if (i == 0) -- return; -+ { -+ free (entry->path); -+ free (entry); -+ return; -+ } - - char *path = entry->path; - if (opt_chroot != NULL) -diff --git a/elf/rtld.c b/elf/rtld.c -index d733359eaf..d83ac1bdc4 100644 ---- a/elf/rtld.c -+++ b/elf/rtld.c -@@ -322,6 +322,7 @@ struct rtld_global _rtld_global = - #ifdef _LIBC_REENTRANT - ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, - ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, -+ ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, - #endif - ._dl_nns = 1, - ._dl_ns = -@@ -463,6 +464,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) - #ifndef DONT_USE_BOOTSTRAP_MAP - GL(dl_rtld_map).l_addr = info->l.l_addr; - GL(dl_rtld_map).l_ld = info->l.l_ld; -+ GL(dl_rtld_map).l_ld_readonly = info->l.l_ld_readonly; - memcpy (GL(dl_rtld_map).l_info, info->l.l_info, - sizeof GL(dl_rtld_map).l_info); - GL(dl_rtld_map).l_mach = info->l.l_mach; -@@ -546,7 +548,8 @@ _dl_start (void *arg) - - /* Read our own dynamic section and fill in the info array. */ - bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); -- elf_get_dynamic_info (&bootstrap_map, NULL); -+ bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION; -+ elf_get_dynamic_info (&bootstrap_map); - - #if NO_TLS_OFFSET != 0 - bootstrap_map.l_tls_offset = NO_TLS_OFFSET; -@@ -1468,6 +1471,7 @@ dl_main (const ElfW(Phdr) *phdr, - /* This tells us where to find the dynamic section, - which tells us everything we need to do. */ - main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr; -+ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0; - break; - case PT_INTERP: - /* This "interpreter segment" was used by the program loader to -@@ -1613,7 +1617,7 @@ dl_main (const ElfW(Phdr) *phdr, - if (! rtld_is_main) - { - /* Extract the contents of the dynamic section for easy access. */ -- elf_get_dynamic_info (main_map, NULL); -+ elf_get_dynamic_info (main_map); - - /* If the main map is libc.so, update the base namespace to - refer to this map. If libc.so is loaded later, this happens -diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h -index 86c491e49c..f44748bc98 100644 ---- a/elf/setup-vdso.h -+++ b/elf/setup-vdso.h -@@ -33,8 +33,6 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), - 0, LM_ID_BASE); - if (__glibc_likely (l != NULL)) - { -- static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; -- - l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso) - + GLRO(dl_sysinfo_dso)->e_phoff); - l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum; -@@ -45,6 +43,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), - { - l->l_ld = (void *) ph->p_vaddr; - l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn)); -+ l->l_ld_readonly = (ph->p_flags & PF_W) == 0; - } - else if (ph->p_type == PT_LOAD) - { -@@ -65,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), - l->l_map_end += l->l_addr; - l->l_text_end += l->l_addr; - l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr); -- elf_get_dynamic_info (l, dyn_temp); -+ elf_get_dynamic_info (l); - _dl_setup_hash (l); - l->l_relocated = 1; - -diff --git a/elf/tst-ro-dynamic-mod.c b/elf/tst-ro-dynamic-mod.c -new file mode 100644 -index 0000000000..6d99925964 ---- /dev/null -+++ b/elf/tst-ro-dynamic-mod.c -@@ -0,0 +1,19 @@ -+/* Test case for DSO with readonly dynamic section. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+int foo = -1; -diff --git a/elf/tst-ro-dynamic-mod.map b/elf/tst-ro-dynamic-mod.map -new file mode 100644 -index 0000000000..2fe4a2998c ---- /dev/null -+++ b/elf/tst-ro-dynamic-mod.map -@@ -0,0 +1,16 @@ -+SECTIONS -+{ -+ . = SIZEOF_HEADERS; -+ .dynamic : { *(.dynamic) } :text :dynamic -+ .rodata : { *(.data*) *(.bss*) } :text -+ /DISCARD/ : { -+ *(.note.gnu.property) -+ } -+ .note : { *(.note.*) } :text :note -+} -+PHDRS -+{ -+ text PT_LOAD FLAGS(5) FILEHDR PHDRS; -+ dynamic PT_DYNAMIC FLAGS(4); -+ note PT_NOTE FLAGS(4); -+} -diff --git a/elf/tst-ro-dynamic.c b/elf/tst-ro-dynamic.c -new file mode 100644 -index 0000000000..3a18f8789a ---- /dev/null -+++ b/elf/tst-ro-dynamic.c -@@ -0,0 +1,31 @@ -+/* Test case for DSO with readonly dynamic section. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <support/check.h> -+#include <support/test-driver.h> -+ -+extern int foo; -+ -+static int -+do_test (void) -+{ -+ TEST_COMPARE (foo, -1); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c -index 62bee28769..cc391d8f93 100644 ---- a/iconv/gconv_conf.c -+++ b/iconv/gconv_conf.c -@@ -478,7 +478,7 @@ __gconv_read_conf (void) - __gconv_get_path (); - - for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) -- gconv_parseconfdir (__gconv_path_elem[cnt].name, -+ gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name, - __gconv_path_elem[cnt].len); - #endif - -diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h -index a4153e54c6..a586268abc 100644 ---- a/iconv/gconv_parseconfdir.h -+++ b/iconv/gconv_parseconfdir.h -@@ -39,7 +39,6 @@ - /* Name of the file containing the module information in the directories - along the path. */ - static const char gconv_conf_filename[] = "gconv-modules"; --static const char gconv_conf_dirname[] = "gconv-modules.d"; - - static void add_alias (char *); - static void add_module (char *, const char *, size_t, int); -@@ -110,19 +109,28 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len) - return true; - } - -+/* Prefix DIR (with length DIR_LEN) with PREFIX if the latter is non-NULL and -+ parse configuration in it. */ -+ - static __always_inline bool --gconv_parseconfdir (const char *dir, size_t dir_len) -+gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len) - { -- /* No slash needs to be inserted between dir and gconv_conf_filename; -- dir already ends in a slash. */ -- char *buf = malloc (dir_len + sizeof (gconv_conf_dirname)); -+ /* No slash needs to be inserted between dir and gconv_conf_filename; dir -+ already ends in a slash. The additional 2 is to accommodate the ".d" -+ when looking for configuration files in gconv-modules.d. */ -+ size_t buflen = dir_len + sizeof (gconv_conf_filename) + 2; -+ char *buf = malloc (buflen + (prefix != NULL ? strlen (prefix) : 0)); -+ char *cp = buf; - bool found = false; - - if (buf == NULL) - return false; - -- char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename, -- sizeof (gconv_conf_filename)); -+ if (prefix != NULL) -+ cp = stpcpy (cp, prefix); -+ -+ cp = mempcpy (mempcpy (cp, dir, dir_len), gconv_conf_filename, -+ sizeof (gconv_conf_filename)); - - /* Read the gconv-modules configuration file first. */ - found = read_conf_file (buf, dir, dir_len); -@@ -153,12 +161,11 @@ gconv_parseconfdir (const char *dir, size_t dir_len) - struct stat64 st; - if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) - continue; -- if (ent->d_type == DT_UNKNOWN -- && (lstat64 (conf, &st) == -1 -- || !S_ISREG (st.st_mode))) -- continue; - -- found |= read_conf_file (conf, dir, dir_len); -+ if (ent->d_type != DT_UNKNOWN -+ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode))) -+ found |= read_conf_file (conf, dir, dir_len); -+ - free (conf); - } - } -diff --git a/iconv/iconv_charmap.c b/iconv/iconv_charmap.c -index e2d53fee3c..a8b6b56124 100644 ---- a/iconv/iconv_charmap.c -+++ b/iconv/iconv_charmap.c -@@ -234,6 +234,8 @@ charmap_conversion (const char *from_code, struct charmap_t *from_charmap, - while (++remaining < argc); - - /* All done. */ -+ if (output != stdout) -+ fclose (output); - free_table (cvtbl); - return status; - } -diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c -index 783b2bbdbb..273a71f673 100644 ---- a/iconv/iconvconfig.c -+++ b/iconv/iconvconfig.c -@@ -653,13 +653,21 @@ add_module (char *rp, const char *directory, - static int - handle_dir (const char *dir) - { -+ char *newp = NULL; - size_t dirlen = strlen (dir); - bool found = false; - -- char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "", -- dir, dir[dirlen - 1] != '/' ? "/" : ""); -+ /* End directory path with a '/' if it doesn't already. */ -+ if (dir[dirlen - 1] != '/') -+ { -+ newp = xmalloc (dirlen + 2); -+ memcpy (newp, dir, dirlen); -+ newp[dirlen++] = '/'; -+ newp[dirlen] = '\0'; -+ dir = newp; -+ } - -- found = gconv_parseconfdir (fulldir, strlen (fulldir)); -+ found = gconv_parseconfdir (dir[0] == '/' ? prefix : NULL, dir, dirlen); - - if (!found) - { -@@ -671,7 +679,7 @@ handle_dir (const char *dir) - "configuration files with names ending in .conf."); - } - -- free (fulldir); -+ free (newp); - - return found ? 0 : 1; - } -diff --git a/iconvdata/Makefile b/iconvdata/Makefile -index c216f959df..d5507a048c 100644 ---- a/iconvdata/Makefile -+++ b/iconvdata/Makefile -@@ -1,4 +1,5 @@ - # Copyright (C) 1997-2021 Free Software Foundation, Inc. -+# Copyright (C) The GNU Toolchain Authors. - # This file is part of the GNU C Library. - - # The GNU C Library is free software; you can redistribute it and/or -@@ -74,7 +75,7 @@ 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-iconv13 bug-iconv14 -+ bug-iconv13 bug-iconv14 bug-iconv15 - ifeq ($(have-thread-library),yes) - tests += bug-iconv3 - endif -@@ -327,6 +328,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \ - $(addprefix $(objpfx),$(modules.so)) - $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \ - $(addprefix $(objpfx),$(modules.so)) -+$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ -+ $(addprefix $(objpfx),$(modules.so)) - - $(objpfx)iconv-test.out: run-iconv-test.sh \ - $(addprefix $(objpfx), $(gconv-modules)) \ -diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c -new file mode 100644 -index 0000000000..cc04bd0313 ---- /dev/null -+++ b/iconvdata/bug-iconv15.c -@@ -0,0 +1,60 @@ -+/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv -+ may emit spurious NUL character on state reset. -+ Copyright (C) The GNU Toolchain Authors. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <stddef.h> -+#include <iconv.h> -+#include <support/check.h> -+ -+static int -+do_test (void) -+{ -+ char in[] = "\x1b(I"; -+ char *inbuf = in; -+ size_t inleft = sizeof (in) - 1; -+ char out[1]; -+ char *outbuf = out; -+ size_t outleft = sizeof (out); -+ iconv_t cd; -+ -+ cd = iconv_open ("UTF8", "ISO-2022-JP-3"); -+ TEST_VERIFY_EXIT (cd != (iconv_t) -1); -+ -+ /* First call to iconv should alter internal state. -+ Now, JISX0201_Kana_set is selected and -+ state value != ASCII_set. */ -+ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1); -+ -+ /* No bytes should have been added to -+ the output buffer at this point. */ -+ TEST_VERIFY (outbuf == out); -+ TEST_VERIFY (outleft == sizeof (out)); -+ -+ /* Second call shall emit spurious NUL character in unpatched glibc. */ -+ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1); -+ -+ /* No characters are expected to be produced. */ -+ TEST_VERIFY (outbuf == out); -+ TEST_VERIFY (outleft == sizeof (out)); -+ -+ TEST_VERIFY_EXIT (iconv_close (cd) != -1); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c -index c8ba88cdc9..5fc0c0f739 100644 ---- a/iconvdata/iso-2022-jp-3.c -+++ b/iconvdata/iso-2022-jp-3.c -@@ -1,5 +1,6 @@ - /* Conversion module for ISO-2022-JP-3. - Copyright (C) 1998-2021 Free Software Foundation, Inc. -+ Copyright (C) The GNU Toolchain Authors. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998, - and Bruno Haible <bruno@clisp.org>, 2002. -@@ -81,20 +82,31 @@ enum - the output state to the initial state. This has to be done during the - flushing. */ - #define EMIT_SHIFT_TO_INIT \ -- if (data->__statep->__count != ASCII_set) \ -+ if ((data->__statep->__count & ~7) != ASCII_set) \ - { \ - if (FROM_DIRECTION) \ - { \ -- if (__glibc_likely (outbuf + 4 <= outend)) \ -+ uint32_t ch = data->__statep->__count >> 6; \ -+ \ -+ if (__glibc_unlikely (ch != 0)) \ - { \ -- /* Write out the last character. */ \ -- *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ -- outbuf += sizeof (uint32_t); \ -- data->__statep->__count = ASCII_set; \ -+ if (__glibc_likely (outbuf + 4 <= outend)) \ -+ { \ -+ /* Write out the last character. */ \ -+ put32u (outbuf, ch); \ -+ outbuf += 4; \ -+ data->__statep->__count &= 7; \ -+ data->__statep->__count |= ASCII_set; \ -+ } \ -+ else \ -+ /* We don't have enough room in the output buffer. */ \ -+ status = __GCONV_FULL_OUTPUT; \ - } \ - else \ -- /* We don't have enough room in the output buffer. */ \ -- status = __GCONV_FULL_OUTPUT; \ -+ { \ -+ data->__statep->__count &= 7; \ -+ data->__statep->__count |= ASCII_set; \ -+ } \ - } \ - else \ - { \ -diff --git a/include/link.h b/include/link.h -index 4af16cb596..c46aced9f7 100644 ---- a/include/link.h -+++ b/include/link.h -@@ -205,6 +205,7 @@ struct link_map - unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be - freed, ie. not allocated with - the dummy malloc in ld.so. */ -+ unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly. */ - - /* NODELETE status of the map. Only valid for maps of type - lt_loaded. Lazy binding sets l_nodelete_active directly, -@@ -342,6 +343,8 @@ struct link_map - unsigned long long int l_serial; - }; - -+#include <dl-relocate-ld.h> -+ - /* Information used by audit modules. For most link maps, this data - immediate follows the link map in memory. For the dynamic linker, - it is allocated separately. See link_map_audit_state in -diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h -index 7388356a19..c490561581 100644 ---- a/include/sys/sysinfo.h -+++ b/include/sys/sysinfo.h -@@ -9,10 +9,15 @@ - extern int __get_nprocs_conf (void); - libc_hidden_proto (__get_nprocs_conf) - --/* Return number of available processors. */ -+/* Return number of available processors (not all of them will be -+ available to the caller process). */ - extern int __get_nprocs (void); - libc_hidden_proto (__get_nprocs) - -+/* Return the number of available processors which the process can -+ be scheduled. */ -+extern int __get_nprocs_sched (void) attribute_hidden; -+ - /* Return number of physical pages of memory in the system. */ - extern long int __get_phys_pages (void); - libc_hidden_proto (__get_phys_pages) -diff --git a/io/fcntl.h b/io/fcntl.h -index 8917a73b42..1c96f98f4d 100644 ---- a/io/fcntl.h -+++ b/io/fcntl.h -@@ -187,10 +187,10 @@ extern int fcntl64 (int __fd, int __cmd, ...); - # endif - #else /* __USE_TIME_BITS64 */ - # ifdef __REDIRECT --extern int __REDIRECT (fcntl, (int __fd, int __request, ...), -- __fcntl_time64) __THROW; --extern int __REDIRECT (fcntl64, (int __fd, int __request, ...), -- __fcntl_time64) __THROW; -+extern int __REDIRECT_NTH (fcntl, (int __fd, int __request, ...), -+ __fcntl_time64); -+extern int __REDIRECT_NTH (fcntl64, (int __fd, int __request, ...), -+ __fcntl_time64); - # else - extern int __fcntl_time64 (int __fd, int __request, ...) __THROW; - # define fcntl64 __fcntl_time64 -diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c -index d4c187073c..395ec0d894 100644 ---- a/io/tst-closefrom.c -+++ b/io/tst-closefrom.c -@@ -24,31 +24,22 @@ - #include <support/check.h> - #include <support/descriptors.h> - #include <support/xunistd.h> -+#include <support/support.h> - - #include <array_length.h> - - #define NFDS 100 - --static int --open_multiple_temp_files (void) --{ -- /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); -- for (int i = 1; i <= NFDS; i++) -- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i); -- return lowfd; --} -- - static int - closefrom_test (void) - { - struct support_descriptors *descrs = support_descriptors_list (); - -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - -- const int maximum_fd = lowfd + NFDS; -+ const int maximum_fd = lowfd + NFDS - 1; - const int half_fd = lowfd + NFDS / 2; -- const int gap = maximum_fd / 4; -+ const int gap = lowfd + NFDS / 4; - - /* Close half of the descriptors and check result. */ - closefrom (half_fd); -@@ -58,7 +49,7 @@ closefrom_test (void) - TEST_COMPARE (fcntl (i, F_GETFL), -1); - TEST_COMPARE (errno, EBADF); - } -- for (int i = 0; i < half_fd; i++) -+ for (int i = lowfd; i < half_fd; i++) - TEST_VERIFY (fcntl (i, F_GETFL) > -1); - - /* Create some gaps, close up to a threshold, and check result. */ -@@ -74,7 +65,7 @@ closefrom_test (void) - TEST_COMPARE (fcntl (i, F_GETFL), -1); - TEST_COMPARE (errno, EBADF); - } -- for (int i = 0; i < gap; i++) -+ for (int i = lowfd; i < gap; i++) - TEST_VERIFY (fcntl (i, F_GETFL) > -1); - - /* Close the remmaining but the last one. */ -diff --git a/malloc/arena.c b/malloc/arena.c -index 667484630e..f1f0af8648 100644 ---- a/malloc/arena.c -+++ b/malloc/arena.c -@@ -879,7 +879,7 @@ arena_get2 (size_t size, mstate avoid_arena) - narenas_limit = mp_.arena_max; - else if (narenas > mp_.arena_test) - { -- int n = __get_nprocs (); -+ int n = __get_nprocs_sched (); - - if (n >= 1) - narenas_limit = NARENAS_FROM_NCORES (n); -diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c -index 9922ef5f25..3d7e6d44fd 100644 ---- a/malloc/malloc-debug.c -+++ b/malloc/malloc-debug.c -@@ -1,5 +1,6 @@ - /* Malloc debug DSO. - Copyright (C) 2021 Free Software Foundation, Inc. -+ Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or -@@ -399,17 +400,17 @@ strong_alias (__debug_calloc, calloc) - size_t - malloc_usable_size (void *mem) - { -+ if (mem == NULL) -+ return 0; -+ - if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)) - return mcheck_usable_size (mem); - if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK)) - return malloc_check_get_size (mem); - -- if (mem != NULL) -- { -- mchunkptr p = mem2chunk (mem); -- if (DUMPED_MAIN_ARENA_CHUNK (p)) -- return chunksize (p) - SIZE_SZ; -- } -+ mchunkptr p = mem2chunk (mem); -+ if (DUMPED_MAIN_ARENA_CHUNK (p)) -+ return chunksize (p) - SIZE_SZ; - - return musable (mem); - } -diff --git a/malloc/malloc.c b/malloc/malloc.c -index e065785af7..7882c70f0a 100644 ---- a/malloc/malloc.c -+++ b/malloc/malloc.c -@@ -1,5 +1,6 @@ - /* Malloc implementation for multiple threads without lock contention. - Copyright (C) 1996-2021 Free Software Foundation, Inc. -+ Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - Contributed by Wolfram Gloger <wg@malloc.de> - and Doug Lea <dl@cs.oswego.edu>, 2001. -@@ -5009,20 +5010,13 @@ __malloc_trim (size_t s) - static size_t - musable (void *mem) - { -- mchunkptr p; -- if (mem != 0) -- { -- size_t result = 0; -- -- p = mem2chunk (mem); -+ mchunkptr p = mem2chunk (mem); - -- if (chunk_is_mmapped (p)) -- result = chunksize (p) - CHUNK_HDR_SZ; -- else if (inuse (p)) -- result = memsize (p); -+ if (chunk_is_mmapped (p)) -+ return chunksize (p) - CHUNK_HDR_SZ; -+ else if (inuse (p)) -+ return memsize (p); - -- return result; -- } - return 0; - } - -@@ -5030,10 +5024,9 @@ musable (void *mem) - size_t - __malloc_usable_size (void *m) - { -- size_t result; -- -- result = musable (m); -- return result; -+ if (m == NULL) -+ return 0; -+ return musable (m); - } - #endif - -diff --git a/malloc/tst-malloc-usable.c b/malloc/tst-malloc-usable.c -index a1074b782a..b0d702be10 100644 ---- a/malloc/tst-malloc-usable.c -+++ b/malloc/tst-malloc-usable.c -@@ -2,6 +2,7 @@ - MALLOC_CHECK_ exported to a positive value. - - Copyright (C) 2012-2021 Free Software Foundation, Inc. -+ Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or -@@ -21,29 +22,24 @@ - #include <malloc.h> - #include <string.h> - #include <stdio.h> -+#include <support/support.h> -+#include <support/check.h> - - static int - do_test (void) - { - size_t usable_size; - void *p = malloc (7); -- if (!p) -- { -- printf ("memory allocation failed\n"); -- return 1; -- } - -+ TEST_VERIFY_EXIT (p != NULL); - usable_size = malloc_usable_size (p); -- if (usable_size != 7) -- { -- printf ("malloc_usable_size: expected 7 but got %zu\n", usable_size); -- return 1; -- } -- -+ TEST_COMPARE (usable_size, 7); - memset (p, 0, usable_size); - free (p); -+ -+ TEST_COMPARE (malloc_usable_size (NULL), 0); -+ - return 0; - } - --#define TEST_FUNCTION do_test () --#include "../test-skeleton.c" -+#include "support/test-driver.c" -diff --git a/misc/getsysstats.c b/misc/getsysstats.c -index 0eedface6d..57d93601e2 100644 ---- a/misc/getsysstats.c -+++ b/misc/getsysstats.c -@@ -45,6 +45,12 @@ weak_alias (__get_nprocs, get_nprocs) - link_warning (get_nprocs, "warning: get_nprocs will always return 1") - - -+int -+__get_nprocs_sched (void) -+{ -+ return 1; -+} -+ - long int - __get_phys_pages (void) - { -diff --git a/misc/sys/ioctl.h b/misc/sys/ioctl.h -index 6884d9925f..9945c1e918 100644 ---- a/misc/sys/ioctl.h -+++ b/misc/sys/ioctl.h -@@ -42,8 +42,8 @@ __BEGIN_DECLS - extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; - #else - # ifdef __REDIRECT --extern int __REDIRECT (ioctl, (int __fd, unsigned long int __request, ...), -- __ioctl_time64) __THROW; -+extern int __REDIRECT_NTH (ioctl, (int __fd, unsigned long int __request, ...), -+ __ioctl_time64); - # else - extern int __ioctl_time64 (int __fd, unsigned long int __request, ...) __THROW; - # define ioctl __ioctl_time64 -diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c -index cfe37a3443..50065bc9bd 100644 ---- a/nptl/allocatestack.c -+++ b/nptl/allocatestack.c -@@ -32,6 +32,7 @@ - #include <futex-internal.h> - #include <kernel-features.h> - #include <nptl-stack.h> -+#include <libc-lock.h> - - /* Default alignment of stack. */ - #ifndef STACK_ALIGN -@@ -127,6 +128,8 @@ get_cached_stack (size_t *sizep, void **memp) - /* No pending event. */ - result->nextevent = NULL; - -+ result->exiting = false; -+ __libc_lock_init (result->exit_lock); - result->tls_state = (struct tls_internal_t) { 0 }; - - /* Clear the DTV. */ -diff --git a/nptl/descr.h b/nptl/descr.h -index c85778d449..4de84138fb 100644 ---- a/nptl/descr.h -+++ b/nptl/descr.h -@@ -396,6 +396,12 @@ struct pthread - PTHREAD_CANCEL_ASYNCHRONOUS). */ - unsigned char canceltype; - -+ /* Used in __pthread_kill_internal to detected a thread that has -+ exited or is about to exit. exit_lock must only be acquired -+ after blocking signals. */ -+ bool exiting; -+ int exit_lock; /* A low-level lock (for use with __libc_lock_init etc). */ -+ - /* Used on strsignal. */ - struct tls_internal_t tls_state; - -diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c -index cc25ff21f3..9bac6e3b76 100644 ---- a/nptl/pthread_cancel.c -+++ b/nptl/pthread_cancel.c -@@ -62,10 +62,11 @@ __pthread_cancel (pthread_t th) - { - volatile struct pthread *pd = (volatile struct pthread *) th; - -- /* Make sure the descriptor is valid. */ -- if (INVALID_TD_P (pd)) -- /* Not a valid thread handle. */ -- return ESRCH; -+ if (pd->tid == 0) -+ /* The thread has already exited on the kernel side. Its outcome -+ (regular exit, other cancelation) has already been -+ determined. */ -+ return 0; - - static int init_sigcancel = 0; - if (atomic_load_relaxed (&init_sigcancel) == 0) -diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c -index d8ec299cb1..3db0c9fdf4 100644 ---- a/nptl/pthread_create.c -+++ b/nptl/pthread_create.c -@@ -37,6 +37,7 @@ - #include <sys/single_threaded.h> - #include <version.h> - #include <clone_internal.h> -+#include <futex-internal.h> - - #include <shlib-compat.h> - -@@ -406,8 +407,6 @@ start_thread (void *arg) - unwind_buf.priv.data.prev = NULL; - unwind_buf.priv.data.cleanup = NULL; - -- __libc_signal_restore_set (&pd->sigmask); -- - /* Allow setxid from now onwards. */ - if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2)) - futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE); -@@ -417,6 +416,8 @@ start_thread (void *arg) - /* Store the new cleanup handler info. */ - THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); - -+ __libc_signal_restore_set (&pd->sigmask); -+ - LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg); - - /* Run the code the user provided. */ -@@ -485,6 +486,27 @@ start_thread (void *arg) - /* This was the last thread. */ - exit (0); - -+ /* This prevents sending a signal from this thread to itself during -+ its final stages. This must come after the exit call above -+ because atexit handlers must not run with signals blocked. -+ -+ Do not block SIGSETXID. The setxid handshake below expects the -+ signal to be delivered. (SIGSETXID cannot run application code, -+ nor does it use pthread_kill.) Reuse the pd->sigmask space for -+ computing the signal mask, to save stack space. */ -+ __sigfillset (&pd->sigmask); -+ __sigdelset (&pd->sigmask, SIGSETXID); -+ INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &pd->sigmask, NULL, -+ __NSIG_BYTES); -+ -+ /* Tell __pthread_kill_internal that this thread is about to exit. -+ If there is a __pthread_kill_internal in progress, this delays -+ the thread exit until the signal has been queued by the kernel -+ (so that the TID used to send it remains valid). */ -+ __libc_lock_lock (pd->exit_lock); -+ pd->exiting = true; -+ __libc_lock_unlock (pd->exit_lock); -+ - #ifndef __ASSUME_SET_ROBUST_LIST - /* If this thread has any robust mutexes locked, handle them now. */ - # if __PTHREAD_MUTEX_HAVE_PREV -diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c -index f79a2b26fc..35bf1f973e 100644 ---- a/nptl/pthread_kill.c -+++ b/nptl/pthread_kill.c -@@ -16,39 +16,66 @@ - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -+#include <libc-lock.h> - #include <unistd.h> - #include <pthreadP.h> - #include <shlib-compat.h> - --int --__pthread_kill_internal (pthread_t threadid, int signo) -+/* Sends SIGNO to THREADID. If the thread is about to exit or has -+ already exited on the kernel side, return NO_TID. Otherwise return -+ 0 or an error code. */ -+static int -+__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) - { -- pid_t tid; - struct pthread *pd = (struct pthread *) threadid; -- - if (pd == THREAD_SELF) -- /* It is a special case to handle raise() implementation after a vfork -- call (which does not update the PD tid field). */ -- tid = INLINE_SYSCALL_CALL (gettid); -- else -- /* Force load of pd->tid into local variable or register. Otherwise -- if a thread exits between ESRCH test and tgkill, we might return -- EINVAL, because pd->tid would be cleared by the kernel. */ -- tid = atomic_forced_read (pd->tid); -- -- int val; -- if (__glibc_likely (tid > 0)) - { -- pid_t pid = __getpid (); -- -- val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); -- val = (INTERNAL_SYSCALL_ERROR_P (val) -- ? INTERNAL_SYSCALL_ERRNO (val) : 0); -+ /* Use the actual TID from the kernel, so that it refers to the -+ current thread even if called after vfork. There is no -+ signal blocking in this case, so that the signal is delivered -+ immediately, before __pthread_kill_internal returns: a signal -+ sent to the thread itself needs to be delivered -+ synchronously. (It is unclear if Linux guarantees the -+ delivery of all pending signals after unblocking in the code -+ below. POSIX only guarantees delivery of a single signal, -+ which may not be the right one.) */ -+ pid_t tid = INTERNAL_SYSCALL_CALL (gettid); -+ int ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), tid, signo); -+ return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; - } -+ -+ /* Block all signals, as required by pd->exit_lock. */ -+ sigset_t old_mask; -+ __libc_signal_block_all (&old_mask); -+ __libc_lock_lock (pd->exit_lock); -+ -+ int ret; -+ if (pd->exiting) -+ /* The thread is about to exit (or has exited). Sending the -+ signal is either not observable (the target thread has already -+ blocked signals at this point), or it will fail, or it might be -+ delivered to a new, unrelated thread that has reused the TID. -+ So do not actually send the signal. */ -+ ret = no_tid; - else -- val = ESRCH; -+ { -+ ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo); -+ ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; -+ } -+ -+ __libc_lock_unlock (pd->exit_lock); -+ __libc_signal_restore_set (&old_mask); - -- return val; -+ return ret; -+} -+ -+int -+__pthread_kill_internal (pthread_t threadid, int signo) -+{ -+ /* Do not report an error in the no-tid case because the threadid -+ argument is still valid (the thread ID lifetime has not ended), -+ and ESRCH (for example) would be misleading. */ -+ return __pthread_kill_implementation (threadid, signo, 0); - } - - int -@@ -61,6 +88,7 @@ __pthread_kill (pthread_t threadid, int signo) - - return __pthread_kill_internal (threadid, signo); - } -+ - /* Some architectures (for instance arm) might pull raise through libgcc, so - avoid the symbol version if it ends up being used on ld.so. */ - #if !IS_IN(rtld) -@@ -68,6 +96,17 @@ libc_hidden_def (__pthread_kill) - versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); - - # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) --compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); -+/* Variant which returns ESRCH in the no-TID case, for backwards -+ compatibility. */ -+int -+attribute_compat_text_section -+__pthread_kill_esrch (pthread_t threadid, int signo) -+{ -+ if (__is_internal_signal (signo)) -+ return EINVAL; -+ -+ return __pthread_kill_implementation (threadid, signo, ESRCH); -+} -+compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0); - # endif - #endif -diff --git a/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf -new file mode 100644 -index 0000000000..5b0c6a4199 ---- /dev/null -+++ b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf -@@ -0,0 +1 @@ -+hosts: files -diff --git a/posix/Makefile b/posix/Makefile -index 059efb3cd2..09460a28e8 100644 ---- a/posix/Makefile -+++ b/posix/Makefile -@@ -107,7 +107,8 @@ tests := test-errno tstgetopt testfnm runtests runptests \ - tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ - tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ - bug-regex38 tst-regcomp-truncated tst-spawn-chdir \ -- tst-wordexp-nocmd tst-execveat tst-spawn5 -+ tst-wordexp-nocmd tst-execveat tst-spawn5 \ -+ tst-sched_getaffinity - - # Test for the glob symbol version that was replaced in glibc 2.27. - ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes) -diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h -index f0831386c7..622adeb2b2 100644 ---- a/posix/bits/unistd.h -+++ b/posix/bits/unistd.h -@@ -199,10 +199,9 @@ __NTH (readlinkat (int __fd, const char *__restrict __path, - #endif - - extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen) -- __THROW __wur __attr_access ((__write_only__, 1, 2)); -+ __THROW __wur; - extern char *__REDIRECT_NTH (__getcwd_alias, -- (char *__buf, size_t __size), getcwd) -- __wur __attr_access ((__write_only__, 1, 2)); -+ (char *__buf, size_t __size), getcwd) __wur; - extern char *__REDIRECT_NTH (__getcwd_chk_warn, - (char *__buf, size_t __size, size_t __buflen), - __getcwd_chk) -diff --git a/posix/fork.c b/posix/fork.c -index c471f7b15f..021691b9b7 100644 ---- a/posix/fork.c -+++ b/posix/fork.c -@@ -99,6 +99,9 @@ __libc_fork (void) - /* Reset the lock the dynamic loader uses to protect its data. */ - __rtld_lock_initialize (GL(dl_load_lock)); - -+ /* Reset the lock protecting dynamic TLS related data. */ -+ __rtld_lock_initialize (GL(dl_load_tls_lock)); -+ - reclaim_stacks (); - - /* Run the handlers registered for the child. */ -diff --git a/posix/tst-sched_getaffinity.c b/posix/tst-sched_getaffinity.c -new file mode 100644 -index 0000000000..db9d517a96 ---- /dev/null -+++ b/posix/tst-sched_getaffinity.c -@@ -0,0 +1,48 @@ -+/* Tests for sched_getaffinity with large buffers. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <array_length.h> -+#include <sched.h> -+#include <support/check.h> -+ -+/* NB: this test may fail on system with more than 32k cpus. */ -+ -+static int -+do_test (void) -+{ -+ /* The values are larger than the default cpu_set_t. */ -+ const int bufsize[] = { 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 1<<16, 1<<17 }; -+ int cpucount[array_length (bufsize)]; -+ -+ for (int i = 0; i < array_length (bufsize); i++) -+ { -+ cpu_set_t *cpuset = CPU_ALLOC (bufsize[i]); -+ TEST_VERIFY (cpuset != NULL); -+ size_t size = CPU_ALLOC_SIZE (bufsize[i]); -+ TEST_COMPARE (sched_getaffinity (0, size, cpuset), 0); -+ cpucount[i] = CPU_COUNT_S (size, cpuset); -+ CPU_FREE (cpuset); -+ } -+ -+ for (int i = 0; i < array_length (cpucount) - 1; i++) -+ TEST_COMPARE (cpucount[i], cpucount[i + 1]); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c -index ac66738004..a95199af6b 100644 ---- a/posix/tst-spawn5.c -+++ b/posix/tst-spawn5.c -@@ -47,17 +47,6 @@ static int initial_argv_count; - - #define NFDS 100 - --static int --open_multiple_temp_files (void) --{ -- /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); -- for (int i = 1; i <= NFDS; i++) -- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), -- lowfd + i); -- return lowfd; --} -- - static int - parse_fd (const char *str) - { -@@ -185,7 +174,7 @@ spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd, - static void - do_test_closefrom (void) - { -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - const int half_fd = lowfd + NFDS / 2; - - /* Close half of the descriptors and check result. */ -diff --git a/posix/unistd.h b/posix/unistd.h -index 3dca65732f..8224c5fbc9 100644 ---- a/posix/unistd.h -+++ b/posix/unistd.h -@@ -528,8 +528,7 @@ extern int fchdir (int __fd) __THROW __wur; - an array is allocated with `malloc'; the array is SIZE - bytes long, unless SIZE == 0, in which case it is as - big as necessary. */ --extern char *getcwd (char *__buf, size_t __size) __THROW __wur -- __attr_access ((__write_only__, 1, 2)); -+extern char *getcwd (char *__buf, size_t __size) __THROW __wur; - - #ifdef __USE_GNU - /* Return a malloc'd string containing the current directory name. -diff --git a/rt/Makefile b/rt/Makefile -index 113cea03a5..910e775995 100644 ---- a/rt/Makefile -+++ b/rt/Makefile -@@ -74,6 +74,7 @@ tests := tst-shm tst-timer tst-timer2 \ - tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ - tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ - tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ -+ tst-bz28213 \ - tst-timer3 tst-timer4 tst-timer5 \ - tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ - tst-shm-cancel \ -diff --git a/rt/tst-bz28213.c b/rt/tst-bz28213.c -new file mode 100644 -index 0000000000..0c096b5a0a ---- /dev/null -+++ b/rt/tst-bz28213.c -@@ -0,0 +1,101 @@ -+/* Bug 28213: test for NULL pointer dereference in mq_notify. -+ Copyright (C) The GNU Toolchain Authors. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <errno.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <mqueue.h> -+#include <signal.h> -+#include <stdlib.h> -+#include <string.h> -+#include <support/check.h> -+ -+static mqd_t m = -1; -+static const char msg[] = "hello"; -+ -+static void -+check_bz28213_cb (union sigval sv) -+{ -+ char buf[sizeof (msg)]; -+ -+ (void) sv; -+ -+ TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL) -+ == sizeof (buf)); -+ TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0); -+ -+ exit (0); -+} -+ -+static void -+check_bz28213 (void) -+{ -+ struct sigevent sev; -+ -+ memset (&sev, '\0', sizeof (sev)); -+ sev.sigev_notify = SIGEV_THREAD; -+ sev.sigev_notify_function = check_bz28213_cb; -+ -+ /* Step 1: Register & unregister notifier. -+ Helper thread should receive NOTIFY_REMOVED notification. -+ In a vulnerable version of glibc, NULL pointer dereference follows. */ -+ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); -+ TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0); -+ -+ /* Step 2: Once again, register notification. -+ Try to send one message. -+ Test is considered successful, if the callback does exit (0). */ -+ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); -+ TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0); -+ -+ /* Wait... */ -+ pause (); -+} -+ -+static int -+do_test (void) -+{ -+ static const char m_name[] = "/bz28213_queue"; -+ struct mq_attr m_attr; -+ -+ memset (&m_attr, '\0', sizeof (m_attr)); -+ m_attr.mq_maxmsg = 1; -+ m_attr.mq_msgsize = sizeof (msg); -+ -+ m = mq_open (m_name, -+ O_RDWR | O_CREAT | O_EXCL, -+ 0600, -+ &m_attr); -+ -+ if (m < 0) -+ { -+ if (errno == ENOSYS) -+ FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n"); -+ FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n"); -+ } -+ -+ TEST_VERIFY_EXIT (mq_unlink (m_name) == 0); -+ -+ check_bz28213 (); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py -index 5a77af90a6..86537fa800 100755 ---- a/scripts/build-many-glibcs.py -+++ b/scripts/build-many-glibcs.py -@@ -782,7 +782,7 @@ class Context(object): - 'gcc': 'vcs-11', - 'glibc': 'vcs-mainline', - 'gmp': '6.2.1', -- 'linux': '5.13', -+ 'linux': '5.14', - 'mpc': '1.2.1', - 'mpfr': '4.1.0', - 'mig': 'vcs-mainline', -diff --git a/support/Makefile b/support/Makefile -index a462781718..2a0731796f 100644 ---- a/support/Makefile -+++ b/support/Makefile -@@ -66,6 +66,7 @@ libsupport-routines = \ - support_path_support_time64 \ - support_process_state \ - support_ptrace \ -+ support-open-dev-null-range \ - support_openpty \ - support_paths \ - support_quote_blob \ -@@ -82,9 +83,10 @@ libsupport-routines = \ - support_test_compare_blob \ - support_test_compare_failure \ - support_test_compare_string \ -- support_write_file_string \ - support_test_main \ - support_test_verify_impl \ -+ support_wait_for_thread_exit \ -+ support_write_file_string \ - temp_file \ - timespec \ - timespec-time64 \ -@@ -264,6 +266,7 @@ tests = \ - tst-support_capture_subprocess \ - tst-support_descriptors \ - tst-support_format_dns_packet \ -+ tst-support-open-dev-null-range \ - tst-support-process_state \ - tst-support_quote_blob \ - tst-support_quote_string \ -diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c -new file mode 100644 -index 0000000000..66a8504105 ---- /dev/null -+++ b/support/support-open-dev-null-range.c -@@ -0,0 +1,134 @@ -+/* Return a range of open file descriptors. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <errno.h> -+#include <fcntl.h> -+#include <support/support.h> -+#include <support/check.h> -+#include <support/xunistd.h> -+#include <stdlib.h> -+#include <sys/resource.h> -+ -+static void -+increase_nofile (void) -+{ -+ struct rlimit rl; -+ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) -+ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); -+ -+ rl.rlim_cur += 128; -+ -+ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) -+ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); -+} -+ -+static int -+open_dev_null (int flags, mode_t mode) -+{ -+ int fd = open64 ("/dev/null", flags, mode); -+ if (fd >= 0) -+ return fd; -+ -+ if (fd < 0 && errno != EMFILE) -+ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode); -+ -+ increase_nofile (); -+ -+ return xopen ("/dev/null", flags, mode); -+} -+ -+struct range -+{ -+ int lowfd; -+ size_t len; -+}; -+ -+struct range_list -+{ -+ size_t total; -+ size_t used; -+ struct range *ranges; -+}; -+ -+static void -+range_init (struct range_list *r) -+{ -+ r->total = 8; -+ r->used = 0; -+ r->ranges = xmalloc (r->total * sizeof (struct range)); -+} -+ -+static void -+range_add (struct range_list *r, int lowfd, size_t len) -+{ -+ if (r->used == r->total) -+ { -+ r->total *= 2; -+ r->ranges = xrealloc (r->ranges, r->total * sizeof (struct range)); -+ } -+ r->ranges[r->used].lowfd = lowfd; -+ r->ranges[r->used].len = len; -+ r->used++; -+} -+ -+static void -+range_close (struct range_list *r) -+{ -+ for (size_t i = 0; i < r->used; i++) -+ { -+ int minfd = r->ranges[i].lowfd; -+ int maxfd = r->ranges[i].lowfd + r->ranges[i].len; -+ for (int fd = minfd; fd < maxfd; fd++) -+ xclose (fd); -+ } -+ free (r->ranges); -+} -+ -+int -+support_open_dev_null_range (int num, int flags, mode_t mode) -+{ -+ /* We keep track of the ranges that hit an already opened descriptor, so -+ we close them after we get a working range. */ -+ struct range_list rl; -+ range_init (&rl); -+ -+ int lowfd = open_dev_null (flags, mode); -+ int prevfd = lowfd; -+ while (true) -+ { -+ int i = 1; -+ for (; i < num; i++) -+ { -+ int fd = open_dev_null (flags, mode); -+ if (fd != lowfd + i) -+ { -+ range_add (&rl, lowfd, prevfd - lowfd + 1); -+ -+ prevfd = lowfd = fd; -+ break; -+ } -+ prevfd = fd; -+ } -+ if (i == num) -+ break; -+ } -+ -+ range_close (&rl); -+ -+ return lowfd; -+} -diff --git a/support/support.h b/support/support.h -index 834dba9097..c219e0d9d1 100644 ---- a/support/support.h -+++ b/support/support.h -@@ -174,6 +174,10 @@ timer_t support_create_timer (uint64_t sec, long int nsec, bool repeat, - /* Disable the timer TIMER. */ - void support_delete_timer (timer_t timer); - -+/* Wait until all threads except the current thread have exited (as -+ far as the kernel is concerned). */ -+void support_wait_for_thread_exit (void); -+ - struct support_stack - { - void *stack; -@@ -193,6 +197,14 @@ struct support_stack support_stack_alloc (size_t size); - /* Deallocate the STACK. */ - void support_stack_free (struct support_stack *stack); - -+ -+/* Create a range of NUM opened '/dev/null' file descriptors using FLAGS and -+ MODE. The function takes care of restarting the open range if a file -+ descriptor is found within the specified range and also increases -+ RLIMIT_NOFILE if required. -+ The returned value is the lowest file descriptor number. */ -+int support_open_dev_null_range (int num, int flags, mode_t mode); -+ - __END_DECLS - - #endif /* SUPPORT_H */ -diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c -index 27bfd19c93..0bacf6dbc2 100644 ---- a/support/support_capture_subprocess.c -+++ b/support/support_capture_subprocess.c -@@ -170,6 +170,7 @@ copy_and_spawn_sgid (char *child_id, gid_t gid) - support_subprogram because we only want the program exit status, not the - contents. */ - ret = 0; -+ infd = outfd = -1; - - char * const args[] = {execname, child_id, NULL}; - -diff --git a/support/support_wait_for_thread_exit.c b/support/support_wait_for_thread_exit.c -new file mode 100644 -index 0000000000..5e3be421a7 ---- /dev/null -+++ b/support/support_wait_for_thread_exit.c -@@ -0,0 +1,75 @@ -+/* Wait until all threads except the current thread has exited. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <dirent.h> -+#include <errno.h> -+#include <string.h> -+#include <support/check.h> -+#include <support/support.h> -+#include <unistd.h> -+ -+void -+support_wait_for_thread_exit (void) -+{ -+#ifdef __linux__ -+ DIR *proc_self_task = opendir ("/proc/self/task"); -+ TEST_VERIFY_EXIT (proc_self_task != NULL); -+ -+ while (true) -+ { -+ errno = 0; -+ struct dirent *e = readdir (proc_self_task); -+ if (e == NULL && errno != 0) -+ FAIL_EXIT1 ("readdir: %m"); -+ if (e == NULL) -+ { -+ /* Only the main thread remains. Testing may continue. */ -+ closedir (proc_self_task); -+ return; -+ } -+ -+ /* In some kernels, "0" entries denote a thread that has just -+ exited. */ -+ if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0 -+ || strcmp (e->d_name, "0") == 0) -+ continue; -+ -+ int task_tid = atoi (e->d_name); -+ if (task_tid <= 0) -+ FAIL_EXIT1 ("Invalid /proc/self/task entry: %s", e->d_name); -+ -+ if (task_tid == gettid ()) -+ /* The current thread. Keep scanning for other -+ threads. */ -+ continue; -+ -+ /* task_tid does not refer to this thread here, i.e., there is -+ another running thread. */ -+ -+ /* Small timeout to give the thread a chance to exit. */ -+ usleep (50 * 1000); -+ -+ /* Start scanning the directory from the start. */ -+ rewinddir (proc_self_task); -+ } -+#else -+ /* Use a large timeout because we cannot verify that the thread has -+ exited. */ -+ usleep (5 * 1000 * 1000); -+#endif -+} -diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c -new file mode 100644 -index 0000000000..8e29def1ce ---- /dev/null -+++ b/support/tst-support-open-dev-null-range.c -@@ -0,0 +1,155 @@ -+/* Tests for support_open_dev_null_range. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <errno.h> -+#include <dirent.h> -+#include <fcntl.h> -+#include <limits.h> -+#include <support/check.h> -+#include <support/support.h> -+#include <support/xunistd.h> -+#include <sys/resource.h> -+#include <stdlib.h> -+ -+#ifndef PATH_MAX -+# define PATH_MAX 1024 -+#endif -+ -+#include <stdio.h> -+ -+static void -+check_path (int fd) -+{ -+ char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd); -+ char file_path[PATH_MAX]; -+ ssize_t file_path_length -+ = readlink (proc_fd_path, file_path, sizeof (file_path)); -+ free (proc_fd_path); -+ if (file_path_length < 0) -+ FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path, -+ sizeof (file_path)); -+ file_path[file_path_length] = '\0'; -+ TEST_COMPARE_STRING (file_path, "/dev/null"); -+} -+ -+static int -+number_of_opened_files (void) -+{ -+ DIR *fds = opendir ("/proc/self/fd"); -+ if (fds == NULL) -+ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m"); -+ -+ int r = 0; -+ while (true) -+ { -+ errno = 0; -+ struct dirent64 *e = readdir64 (fds); -+ if (e == NULL) -+ { -+ if (errno != 0) -+ FAIL_EXIT1 ("readdir: %m"); -+ break; -+ } -+ -+ if (e->d_name[0] == '.') -+ continue; -+ -+ char *endptr; -+ long int fd = strtol (e->d_name, &endptr, 10); -+ if (*endptr != '\0' || fd < 0 || fd > INT_MAX) -+ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", -+ e->d_name); -+ -+ /* Skip the descriptor which is used to enumerate the -+ descriptors. */ -+ if (fd == dirfd (fds)) -+ continue; -+ -+ r = r + 1; -+ } -+ -+ closedir (fds); -+ -+ return r; -+} -+ -+static int -+do_test (void) -+{ -+ const int nfds1 = 8; -+ int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600); -+ for (int i = 0; i < nfds1; i++) -+ { -+ TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1); -+ check_path (lowfd + i); -+ } -+ -+ /* create some gaps. */ -+ xclose (lowfd + 1); -+ xclose (lowfd + 5); -+ xclose (lowfd + 6); -+ -+ const int nfds2 = 16; -+ int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600); -+ for (int i = 0; i < nfds2; i++) -+ { -+ TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1); -+ check_path (lowfd2 + i); -+ } -+ -+ /* Decrease the maximum number of files. */ -+ { -+ struct rlimit rl; -+ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) -+ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); -+ -+ rl.rlim_cur = number_of_opened_files (); -+ -+ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) -+ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); -+ } -+ -+ const int nfds3 = 16; -+ int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600); -+ for (int i = 0; i < nfds3; i++) -+ { -+ TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1); -+ check_path (lowfd3 + i); -+ } -+ -+ /* create a lot of gaps to trigger the range extension. */ -+ xclose (lowfd3 + 1); -+ xclose (lowfd3 + 3); -+ xclose (lowfd3 + 5); -+ xclose (lowfd3 + 7); -+ xclose (lowfd3 + 9); -+ xclose (lowfd3 + 11); -+ xclose (lowfd3 + 13); -+ -+ const int nfds4 = 16; -+ int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600); -+ for (int i = 0; i < nfds4; i++) -+ { -+ TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1); -+ check_path (lowfd4 + i); -+ } -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/generic/dl-relocate-ld.h b/sysdeps/generic/dl-relocate-ld.h -new file mode 100644 -index 0000000000..cfb86c2d6a ---- /dev/null -+++ b/sysdeps/generic/dl-relocate-ld.h -@@ -0,0 +1,25 @@ -+/* Check if dynamic section should be relocated. Generic version. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#ifndef _DL_RELOCATE_LD_H -+#define _DL_RELOCATE_LD_H -+ -+/* The dynamic section is writable. */ -+#define DL_RO_DYN_SECTION 0 -+ -+#endif /* _DL_RELOCATE_LD_H */ -diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h -index 9c15259236..fcbbf69748 100644 ---- a/sysdeps/generic/ldsodefs.h -+++ b/sysdeps/generic/ldsodefs.h -@@ -69,17 +69,24 @@ __BEGIN_DECLS - `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ - #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) - -+/* Return true if dynamic section in the shared library L should be -+ relocated. */ -+ -+static inline bool -+dl_relocate_ld (const struct link_map *l) -+{ -+ /* Don't relocate dynamic section if it is readonly */ -+ return !(l->l_ld_readonly || DL_RO_DYN_SECTION); -+} -+ - /* All references to the value of l_info[DT_PLTGOT], - l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA], - l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)] - have to be accessed via the D_PTR macro. The macro is needed since for - most architectures the entry is already relocated - but for some not - and we need to relocate at access time. */ --#ifdef DL_RO_DYN_SECTION --# define D_PTR(map, i) ((map)->i->d_un.d_ptr + (map)->l_addr) --#else --# define D_PTR(map, i) (map)->i->d_un.d_ptr --#endif -+#define D_PTR(map, i) \ -+ ((map)->i->d_un.d_ptr + (dl_relocate_ld (map) ? 0 : (map)->l_addr)) - - /* Result of the lookup functions and how to retrieve the base address. */ - typedef struct link_map *lookup_t; -@@ -372,6 +379,13 @@ struct rtld_global - list of loaded objects while an object is added to or removed - from that list. */ - __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock) -+ /* This lock protects global and module specific TLS related data. -+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), -+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are -+ accessed and when TLS related relocations are processed for a -+ module. It was introduced to keep pthread_create accessing TLS -+ state that is being set up. */ -+ __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock) - - /* Incremented whenever something may have been added to dl_loaded. */ - EXTERN unsigned long long _dl_load_adds; -@@ -1261,7 +1275,7 @@ extern int _dl_scope_free (void *) attribute_hidden; - - /* Add module to slot information data. If DO_ADD is false, only the - required memory is allocated. Must be called with GL -- (dl_load_lock) acquired. If the function has already been called -+ (dl_load_tls_lock) acquired. If the function has already been called - for the link map L with !do_add, then this function will not raise - an exception, otherwise it is possible that it encounters a memory - allocation failure. */ -diff --git a/sysdeps/mach/getsysstats.c b/sysdeps/mach/getsysstats.c -index 1267f39da2..cc8023f979 100644 ---- a/sysdeps/mach/getsysstats.c -+++ b/sysdeps/mach/getsysstats.c -@@ -62,6 +62,12 @@ __get_nprocs (void) - libc_hidden_def (__get_nprocs) - weak_alias (__get_nprocs, get_nprocs) - -+int -+__get_nprocs_sched (void) -+{ -+ return __get_nprocs (); -+} -+ - /* Return the number of physical pages on the system. */ - long int - __get_phys_pages (void) -diff --git a/sysdeps/mips/dl-relocate-ld.h b/sysdeps/mips/dl-relocate-ld.h -new file mode 100644 -index 0000000000..376ad75dd1 ---- /dev/null -+++ b/sysdeps/mips/dl-relocate-ld.h -@@ -0,0 +1,25 @@ -+/* Check if dynamic section should be relocated. MIPS version. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#ifndef _DL_RELOCATE_LD_H -+#define _DL_RELOCATE_LD_H -+ -+/* The dynamic section is readonly. */ -+#define DL_RO_DYN_SECTION 1 -+ -+#endif /* _DL_RELOCATE_LD_H */ -diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h -index 4db7c60e38..36fd09a8bd 100644 ---- a/sysdeps/mips/ldsodefs.h -+++ b/sysdeps/mips/ldsodefs.h -@@ -75,10 +75,6 @@ struct La_mips_64_retval; - struct La_mips_64_retval *, \ - const char *); - --/* The MIPS ABI specifies that the dynamic section has to be read-only. */ -- --#define DL_RO_DYN_SECTION 1 -- - #include_next <ldsodefs.h> - - /* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each -diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h -index f1b7f2bdc6..43146e91c9 100644 ---- a/sysdeps/nptl/pthread.h -+++ b/sysdeps/nptl/pthread.h -@@ -933,7 +933,7 @@ extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr, - # ifdef __USE_GNU - # ifdef __REDIRECT_NTH - extern int __REDIRECT_NTH (pthread_mutexattr_getrobust_np, -- (pthread_mutex_t *, int *), -+ (pthread_mutexattr_t *, int *), - pthread_mutexattr_getrobust) __nonnull ((1)) - __attribute_deprecated_msg__ ("\ - pthread_mutexattr_getrobust_np is deprecated, use pthread_mutexattr_getrobust"); -@@ -949,7 +949,7 @@ extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, - # ifdef __USE_GNU - # ifdef __REDIRECT_NTH - extern int __REDIRECT_NTH (pthread_mutexattr_setrobust_np, -- (pthread_mutex_t *, int), -+ (pthread_mutexattr_t *, int), - pthread_mutexattr_setrobust) __nonnull ((1)) - __attribute_deprecated_msg__ ("\ - pthread_mutexattr_setrobust_np is deprecated, use pthread_mutexattr_setrobust"); -diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c -index 838a68f022..43dfc6739e 100644 ---- a/sysdeps/posix/getaddrinfo.c -+++ b/sysdeps/posix/getaddrinfo.c -@@ -2008,6 +2008,7 @@ gaiconf_init (void) - l = l->next; - } - free_prefixlist (labellist); -+ labellist = NULL; - - /* Sort the entries so that the most specific ones are at - the beginning. */ -@@ -2046,6 +2047,7 @@ gaiconf_init (void) - l = l->next; - } - free_prefixlist (precedencelist); -+ precedencelist = NULL; - - /* Sort the entries so that the most specific ones are at - the beginning. */ -diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h -index 589f7c8d18..cfcfa69f91 100644 ---- a/sysdeps/powerpc/powerpc64/sysdep.h -+++ b/sysdeps/powerpc/powerpc64/sysdep.h -@@ -275,12 +275,14 @@ LT_LABELSUFFIX(name,_name_end): ; \ - /* Allocate frame and save register */ - #define NVOLREG_SAVE \ - stdu r1,-SCV_FRAME_SIZE(r1); \ -+ cfi_adjust_cfa_offset(SCV_FRAME_SIZE); \ - std r31,SCV_FRAME_NVOLREG_SAVE(r1); \ -- cfi_adjust_cfa_offset(SCV_FRAME_SIZE); -+ cfi_rel_offset(r31,SCV_FRAME_NVOLREG_SAVE); - - /* Restore register and destroy frame */ - #define NVOLREG_RESTORE \ - ld r31,SCV_FRAME_NVOLREG_SAVE(r1); \ -+ cfi_restore(r31); \ - addi r1,r1,SCV_FRAME_SIZE; \ - cfi_adjust_cfa_offset(-SCV_FRAME_SIZE); - -@@ -331,13 +333,13 @@ LT_LABELSUFFIX(name,_name_end): ; \ - - #define DO_CALL_SCV \ - mflr r9; \ -- std r9,FRAME_LR_SAVE(r1); \ -- cfi_offset(lr,FRAME_LR_SAVE); \ -+ std r9,SCV_FRAME_SIZE+FRAME_LR_SAVE(r1); \ -+ cfi_rel_offset(lr,SCV_FRAME_SIZE+FRAME_LR_SAVE); \ - .machine "push"; \ - .machine "power9"; \ - scv 0; \ - .machine "pop"; \ -- ld r9,FRAME_LR_SAVE(r1); \ -+ ld r9,SCV_FRAME_SIZE+FRAME_LR_SAVE(r1); \ - mtlr r9; \ - cfi_restore(lr); - -diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile -index 42f9fc5072..c657101696 100644 ---- a/sysdeps/pthread/Makefile -+++ b/sysdeps/pthread/Makefile -@@ -89,7 +89,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ - tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \ - tst-join14 tst-join15 \ - tst-key1 tst-key2 tst-key3 tst-key4 \ -- tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \ -+ tst-kill1 tst-kill2 tst-kill3 tst-kill5 tst-kill6 \ - tst-locale1 tst-locale2 \ - tst-memstream \ - tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \ -@@ -118,6 +118,14 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ - tst-unload \ - tst-unwind-thread \ - tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ -+ tst-pthread-exit-signal \ -+ tst-pthread-setuid-loop \ -+ tst-pthread_cancel-exited \ -+ tst-pthread_cancel-select-loop \ -+ tst-pthread-raise-blocked-self \ -+ tst-pthread_kill-exited \ -+ tst-pthread_kill-exiting \ -+ # tests - - tests-time64 := \ - tst-abstime-time64 \ -@@ -145,15 +153,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \ - tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 - - ifeq ($(build-shared),yes) --tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 -+tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1 - tests-nolibpthread += tst-fini1 - endif - - modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \ -- tst-_res1mod1 tst-_res1mod2 tst-fini1mod -+ tst-_res1mod1 tst-_res1mod2 tst-fini1mod \ -+ tst-create1mod - test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) - - tst-atfork2mod.so-no-z-defs = yes -+tst-create1mod.so-no-z-defs = yes - - ifeq ($(build-shared),yes) - # Build all the modules even when not actually running test programs. -@@ -272,4 +282,8 @@ LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so - - CFLAGS-tst-unwind-thread.c += -funwind-tables - -+LDFLAGS-tst-create1 = -Wl,-export-dynamic -+$(objpfx)tst-create1: $(shared-thread-library) -+$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so -+ - endif -diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c -new file mode 100644 -index 0000000000..763ded8d79 ---- /dev/null -+++ b/sysdeps/pthread/tst-create1.c -@@ -0,0 +1,123 @@ -+/* Verify that pthread_create does not deadlock when ctors take locks. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <stdio.h> -+#include <support/xdlfcn.h> -+#include <support/xthread.h> -+ -+/* -+Check if ctor and pthread_create deadlocks in -+ -+thread 1: dlopen -> ctor -> lock(user_lock) -+thread 2: lock(user_lock) -> pthread_create -+ -+or in -+ -+thread 1: dlclose -> dtor -> lock(user_lock) -+thread 2: lock(user_lock) -> pthread_create -+*/ -+ -+static pthread_barrier_t bar_ctor; -+static pthread_barrier_t bar_ctor_finish; -+static pthread_barrier_t bar_dtor; -+static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER; -+ -+void -+ctor (void) -+{ -+ xpthread_barrier_wait (&bar_ctor); -+ dprintf (1, "thread 1: in ctor: started.\n"); -+ xpthread_mutex_lock (&user_lock); -+ dprintf (1, "thread 1: in ctor: locked user_lock.\n"); -+ xpthread_mutex_unlock (&user_lock); -+ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n"); -+ dprintf (1, "thread 1: in ctor: done.\n"); -+ xpthread_barrier_wait (&bar_ctor_finish); -+} -+ -+void -+dtor (void) -+{ -+ xpthread_barrier_wait (&bar_dtor); -+ dprintf (1, "thread 1: in dtor: started.\n"); -+ xpthread_mutex_lock (&user_lock); -+ dprintf (1, "thread 1: in dtor: locked user_lock.\n"); -+ xpthread_mutex_unlock (&user_lock); -+ dprintf (1, "thread 1: in dtor: unlocked user_lock.\n"); -+ dprintf (1, "thread 1: in dtor: done.\n"); -+} -+ -+static void * -+thread3 (void *a) -+{ -+ dprintf (1, "thread 3: started.\n"); -+ dprintf (1, "thread 3: done.\n"); -+ return 0; -+} -+ -+static void * -+thread2 (void *a) -+{ -+ pthread_t t3; -+ dprintf (1, "thread 2: started.\n"); -+ -+ xpthread_mutex_lock (&user_lock); -+ dprintf (1, "thread 2: locked user_lock.\n"); -+ xpthread_barrier_wait (&bar_ctor); -+ t3 = xpthread_create (0, thread3, 0); -+ xpthread_mutex_unlock (&user_lock); -+ dprintf (1, "thread 2: unlocked user_lock.\n"); -+ xpthread_join (t3); -+ xpthread_barrier_wait (&bar_ctor_finish); -+ -+ xpthread_mutex_lock (&user_lock); -+ dprintf (1, "thread 2: locked user_lock.\n"); -+ xpthread_barrier_wait (&bar_dtor); -+ t3 = xpthread_create (0, thread3, 0); -+ xpthread_mutex_unlock (&user_lock); -+ dprintf (1, "thread 2: unlocked user_lock.\n"); -+ xpthread_join (t3); -+ -+ dprintf (1, "thread 2: done.\n"); -+ return 0; -+} -+ -+static void -+thread1 (void) -+{ -+ dprintf (1, "thread 1: started.\n"); -+ xpthread_barrier_init (&bar_ctor, NULL, 2); -+ xpthread_barrier_init (&bar_ctor_finish, NULL, 2); -+ xpthread_barrier_init (&bar_dtor, NULL, 2); -+ pthread_t t2 = xpthread_create (0, thread2, 0); -+ void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL); -+ dprintf (1, "thread 1: dlopen done.\n"); -+ xdlclose (p); -+ dprintf (1, "thread 1: dlclose done.\n"); -+ xpthread_join (t2); -+ dprintf (1, "thread 1: done.\n"); -+} -+ -+static int -+do_test (void) -+{ -+ thread1 (); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c -new file mode 100644 -index 0000000000..62c9006961 ---- /dev/null -+++ b/sysdeps/pthread/tst-create1mod.c -@@ -0,0 +1,41 @@ -+/* Verify that pthread_create does not deadlock when ctors take locks. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <stdio.h> -+ -+/* Require TLS setup for the module. */ -+__thread int tlsvar; -+ -+void ctor (void); -+void dtor (void); -+ -+static void __attribute__ ((constructor)) -+do_init (void) -+{ -+ dprintf (1, "constructor started: %d.\n", tlsvar++); -+ ctor (); -+ dprintf (1, "constructor done: %d.\n", tlsvar++); -+} -+ -+static void __attribute__ ((destructor)) -+do_end (void) -+{ -+ dprintf (1, "destructor started: %d.\n", tlsvar++); -+ dtor (); -+ dprintf (1, "destructor done: %d.\n", tlsvar++); -+} -diff --git a/sysdeps/pthread/tst-kill4.c b/sysdeps/pthread/tst-kill4.c -deleted file mode 100644 -index 9563939792..0000000000 ---- a/sysdeps/pthread/tst-kill4.c -+++ /dev/null -@@ -1,90 +0,0 @@ --/* Copyright (C) 2003-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. -- -- 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 -- <https://www.gnu.org/licenses/>. */ -- --#include <errno.h> --#include <pthread.h> --#include <signal.h> --#include <stdio.h> --#include <stdlib.h> --#include <unistd.h> -- -- --static void * --tf (void *a) --{ -- return NULL; --} -- -- --int --do_test (void) --{ -- pthread_attr_t at; -- if (pthread_attr_init (&at) != 0) -- { -- puts ("attr_create failed"); -- exit (1); -- } -- -- /* Limit thread stack size, because if it is too large, pthread_join -- will free it immediately rather than put it into stack cache. */ -- if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0) -- { -- puts ("setstacksize failed"); -- exit (1); -- } -- -- pthread_t th; -- if (pthread_create (&th, &at, tf, NULL) != 0) -- { -- puts ("create failed"); -- exit (1); -- } -- -- pthread_attr_destroy (&at); -- -- if (pthread_join (th, NULL) != 0) -- { -- puts ("join failed"); -- exit (1); -- } -- -- /* The following only works because we assume here something about -- the implementation. Namely, that the memory allocated for the -- thread descriptor is not going away, that the TID field is -- cleared and therefore the signal is sent to process 0, and that -- we can savely assume there is no other process with this ID at -- that time. */ -- int e = pthread_kill (th, 0); -- if (e == 0) -- { -- puts ("pthread_kill succeeded"); -- exit (1); -- } -- if (e != ESRCH) -- { -- puts ("pthread_kill didn't return ESRCH"); -- exit (1); -- } -- -- return 0; --} -- -- --#define TEST_FUNCTION do_test () --#include "../test-skeleton.c" -diff --git a/sysdeps/pthread/tst-pthread-exit-signal.c b/sysdeps/pthread/tst-pthread-exit-signal.c -new file mode 100644 -index 0000000000..b4526fe663 ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread-exit-signal.c -@@ -0,0 +1,45 @@ -+/* Test that pending signals are not delivered on thread exit (bug 28607). -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+/* Due to bug 28607, pthread_kill (or pthread_cancel) restored the -+ signal mask during during thread exit, triggering the delivery of a -+ blocked pending signal (SIGUSR1 in this test). */ -+ -+#include <support/xthread.h> -+#include <support/xsignal.h> -+ -+static void * -+threadfunc (void *closure) -+{ -+ sigset_t sigmask; -+ sigfillset (&sigmask); -+ xpthread_sigmask (SIG_SETMASK, &sigmask, NULL); -+ xpthread_kill (pthread_self (), SIGUSR1); -+ pthread_exit (NULL); -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ pthread_t thr = xpthread_create (NULL, threadfunc, NULL); -+ xpthread_join (thr); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread-raise-blocked-self.c b/sysdeps/pthread/tst-pthread-raise-blocked-self.c -new file mode 100644 -index 0000000000..128e1a6071 ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread-raise-blocked-self.c -@@ -0,0 +1,92 @@ -+/* Test that raise sends signal to current thread even if blocked. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <signal.h> -+#include <support/check.h> -+#include <support/xsignal.h> -+#include <support/xthread.h> -+#include <pthread.h> -+#include <unistd.h> -+ -+/* Used to create a dummy thread ID distinct from all other thread -+ IDs. */ -+static void * -+noop (void *ignored) -+{ -+ return NULL; -+} -+ -+static volatile pthread_t signal_thread; -+ -+static void -+signal_handler (int signo) -+{ -+ signal_thread = pthread_self (); -+} -+ -+/* Used to ensure that waiting_thread has launched and can accept -+ signals. */ -+static pthread_barrier_t barrier; -+ -+static void * -+waiting_thread (void *ignored) -+{ -+ xpthread_barrier_wait (&barrier); -+ pause (); -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ xsignal (SIGUSR1, signal_handler); -+ xpthread_barrier_init (&barrier, NULL, 2); -+ -+ /* Distinct thread ID value to */ -+ pthread_t dummy = xpthread_create (NULL, noop, NULL); -+ signal_thread = dummy; -+ -+ pthread_t helper = xpthread_create (NULL, waiting_thread, NULL); -+ -+ /* Make sure that the thread is running. */ -+ xpthread_barrier_wait (&barrier); -+ -+ /* Block signals on this thread. */ -+ sigset_t set; -+ sigfillset (&set); -+ xpthread_sigmask (SIG_BLOCK, &set, NULL); -+ -+ /* Send the signal to this thread. It must not be delivered. */ -+ raise (SIGUSR1); -+ TEST_VERIFY (signal_thread == dummy); -+ -+ /* Wait a bit to give a chance for signal delivery (increases -+ chances of failure with bug 28407). */ -+ usleep (50 * 1000); -+ -+ /* Unblocking should cause synchronous delivery of the signal. */ -+ xpthread_sigmask (SIG_UNBLOCK, &set, NULL); -+ TEST_VERIFY (signal_thread == pthread_self ()); -+ -+ xpthread_cancel (helper); -+ xpthread_join (helper); -+ xpthread_join (dummy); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread-setuid-loop.c b/sysdeps/pthread/tst-pthread-setuid-loop.c -new file mode 100644 -index 0000000000..fda2a49b7f ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread-setuid-loop.c -@@ -0,0 +1,61 @@ -+/* Test that setuid, pthread_create, thread exit do not deadlock (bug 28361). -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <support/check.h> -+#include <support/xthread.h> -+#include <unistd.h> -+ -+/* How many threads to launch during each iteration. */ -+enum { threads = 4 }; -+ -+/* How many iterations to perform. This value seems to reproduce -+ bug 28361 in a bout one in three runs. */ -+enum { iterations = 5000 }; -+ -+/* Cache of the real user ID used by setuid_thread. */ -+static uid_t uid; -+ -+/* Start routine for the threads. */ -+static void * -+setuid_thread (void *closure) -+{ -+ TEST_COMPARE (setuid (uid), 0); -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ /* The setxid machinery is still invoked even if the UID is -+ unchanged. (The kernel might reset other credentials as part of -+ the system call.) */ -+ uid = getuid (); -+ -+ for (int i = 0; i < iterations; ++i) -+ { -+ pthread_t thread_ids[threads]; -+ for (int j = 0; j < threads; ++j) -+ thread_ids[j] = xpthread_create (NULL, setuid_thread, NULL); -+ for (int j = 0; j < threads; ++j) -+ xpthread_join (thread_ids[j]); -+ } -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread_cancel-exited.c b/sysdeps/pthread/tst-pthread_cancel-exited.c -new file mode 100644 -index 0000000000..811c9bee07 ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread_cancel-exited.c -@@ -0,0 +1,45 @@ -+/* Test that pthread_kill succeeds for an exited thread. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This test verifies that pthread_kill returns 0 (and not ESRCH) for -+ a thread that has exited on the kernel side. */ -+ -+#include <stddef.h> -+#include <support/support.h> -+#include <support/xthread.h> -+ -+static void * -+noop_thread (void *closure) -+{ -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ pthread_t thr = xpthread_create (NULL, noop_thread, NULL); -+ -+ support_wait_for_thread_exit (); -+ -+ xpthread_cancel (thr); -+ xpthread_join (thr); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread_cancel-select-loop.c b/sysdeps/pthread/tst-pthread_cancel-select-loop.c -new file mode 100644 -index 0000000000..a62087589c ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread_cancel-select-loop.c -@@ -0,0 +1,87 @@ -+/* Test that pthread_cancel succeeds during thread exit. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This test tries to trigger an internal race condition in -+ pthread_cancel, where the cancellation signal is sent after the -+ thread has begun the cancellation process. This can result in a -+ spurious ESRCH error. For the original bug 12889, the window is -+ quite small, so the bug was not reproduced in every run. */ -+ -+#include <stdbool.h> -+#include <stddef.h> -+#include <support/check.h> -+#include <support/xthread.h> -+#include <support/xunistd.h> -+#include <sys/select.h> -+#include <unistd.h> -+ -+/* Set to true by timeout_thread_function when the test should -+ terminate. */ -+static bool timeout; -+ -+static void * -+timeout_thread_function (void *unused) -+{ -+ usleep (5 * 1000 * 1000); -+ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED); -+ return NULL; -+} -+ -+/* Used for blocking the select function below. */ -+static int pipe_fds[2]; -+ -+static void * -+canceled_thread_function (void *unused) -+{ -+ while (true) -+ { -+ fd_set rfs; -+ fd_set wfs; -+ fd_set efs; -+ FD_ZERO (&rfs); -+ FD_ZERO (&wfs); -+ FD_ZERO (&efs); -+ FD_SET (pipe_fds[0], &rfs); -+ -+ /* If the cancellation request is recognized early, the thread -+ begins exiting while the cancellation signal arrives. */ -+ select (FD_SETSIZE, &rfs, &wfs, &efs, NULL); -+ } -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ xpipe (pipe_fds); -+ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL); -+ -+ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED)) -+ { -+ pthread_t thr = xpthread_create (NULL, canceled_thread_function, NULL); -+ xpthread_cancel (thr); -+ TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED); -+ } -+ -+ xpthread_join (thr_timeout); -+ xclose (pipe_fds[0]); -+ xclose (pipe_fds[1]); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c -new file mode 100644 -index 0000000000..a2fddad526 ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread_kill-exited.c -@@ -0,0 +1,63 @@ -+/* Test that pthread_kill succeeds for an exited thread. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This test verifies that the default pthread_kill returns 0 (and not -+ ESRCH) for a thread that has exited on the kernel side. */ -+ -+#include <errno.h> -+#include <pthread.h> -+#include <shlib-compat.h> -+#include <signal.h> -+#include <stddef.h> -+#include <support/check.h> -+#include <support/support.h> -+#include <support/xthread.h> -+ -+static void * -+noop_thread (void *closure) -+{ -+ return NULL; -+} -+ -+#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC -+extern __typeof (pthread_kill) compat_pthread_kill; -+compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill, -+ GLIBC_2_0); -+#endif -+ -+static int -+do_test (void) -+{ -+ pthread_t thr = xpthread_create (NULL, noop_thread, NULL); -+ -+ support_wait_for_thread_exit (); -+ -+ /* NB: Always uses the default symbol due to separate compilation. */ -+ xpthread_kill (thr, SIGUSR1); -+ -+#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC -+ /* Old binaries need the non-conforming ESRCH error code. */ -+ TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH); -+#endif -+ -+ xpthread_join (thr); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/pthread/tst-pthread_kill-exiting.c b/sysdeps/pthread/tst-pthread_kill-exiting.c -new file mode 100644 -index 0000000000..f803e94f11 ---- /dev/null -+++ b/sysdeps/pthread/tst-pthread_kill-exiting.c -@@ -0,0 +1,123 @@ -+/* Test that pthread_kill succeeds during thread exit. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This test verifies that pthread_kill for a thread that is exiting -+ succeeds (with or without actually delivering the signal). */ -+ -+#include <array_length.h> -+#include <stdbool.h> -+#include <stddef.h> -+#include <support/xsignal.h> -+#include <support/xthread.h> -+#include <unistd.h> -+ -+/* Set to true by timeout_thread_function when the test should -+ terminate. */ -+static bool timeout; -+ -+static void * -+timeout_thread_function (void *unused) -+{ -+ usleep (1000 * 1000); -+ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED); -+ return NULL; -+} -+ -+/* Used to synchronize the sending threads with the target thread and -+ main thread. */ -+static pthread_barrier_t barrier_1; -+static pthread_barrier_t barrier_2; -+ -+/* The target thread to which signals are to be sent. */ -+static pthread_t target_thread; -+ -+/* Set by the main thread to true after timeout has been set to -+ true. */ -+static bool exiting; -+ -+static void * -+sender_thread_function (void *unused) -+{ -+ while (true) -+ { -+ /* Wait until target_thread has been initialized. The target -+ thread and main thread participate in this barrier. */ -+ xpthread_barrier_wait (&barrier_1); -+ -+ if (exiting) -+ break; -+ -+ xpthread_kill (target_thread, SIGUSR1); -+ -+ /* Communicate that the signal has been sent. The main thread -+ participates in this barrier. */ -+ xpthread_barrier_wait (&barrier_2); -+ } -+ return NULL; -+} -+ -+static void * -+target_thread_function (void *unused) -+{ -+ target_thread = pthread_self (); -+ xpthread_barrier_wait (&barrier_1); -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ xsignal (SIGUSR1, SIG_IGN); -+ -+ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL); -+ -+ pthread_t threads[4]; -+ xpthread_barrier_init (&barrier_1, NULL, array_length (threads) + 2); -+ xpthread_barrier_init (&barrier_2, NULL, array_length (threads) + 1); -+ -+ for (int i = 0; i < array_length (threads); ++i) -+ threads[i] = xpthread_create (NULL, sender_thread_function, NULL); -+ -+ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED)) -+ { -+ xpthread_create (NULL, target_thread_function, NULL); -+ -+ /* Wait for the target thread to be set up and signal sending to -+ start. */ -+ xpthread_barrier_wait (&barrier_1); -+ -+ /* Wait for signal sending to complete. */ -+ xpthread_barrier_wait (&barrier_2); -+ -+ xpthread_join (target_thread); -+ } -+ -+ exiting = true; -+ -+ /* Signal the sending threads to exit. */ -+ xpthread_create (NULL, target_thread_function, NULL); -+ xpthread_barrier_wait (&barrier_1); -+ -+ for (int i = 0; i < array_length (threads); ++i) -+ xpthread_join (threads[i]); -+ xpthread_join (thr_timeout); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/riscv/dl-relocate-ld.h b/sysdeps/riscv/dl-relocate-ld.h -new file mode 100644 -index 0000000000..2ab2b8ac6c ---- /dev/null -+++ b/sysdeps/riscv/dl-relocate-ld.h -@@ -0,0 +1,25 @@ -+/* Check if dynamic section should be relocated. RISC-V version. -+ 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 -+ <https://www.gnu.org/licenses/>. */ -+ -+#ifndef _DL_RELOCATE_LD_H -+#define _DL_RELOCATE_LD_H -+ -+/* The dynamic section is readonly for ABI compatibility. */ -+#define DL_RO_DYN_SECTION 1 -+ -+#endif /* _DL_RELOCATE_LD_H */ -diff --git a/sysdeps/riscv/ldsodefs.h b/sysdeps/riscv/ldsodefs.h -index 0c696714a7..8947ffe4b5 100644 ---- a/sysdeps/riscv/ldsodefs.h -+++ b/sysdeps/riscv/ldsodefs.h -@@ -38,11 +38,6 @@ struct La_riscv_retval; - struct La_riscv_retval *, \ - const char *); - --/* Although the RISC-V ABI does not specify that the dynamic section has -- to be read-only, it needs to be kept for ABI compatibility. */ -- --#define DL_RO_DYN_SECTION 1 -- - #include_next <ldsodefs.h> - - #endif -diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c -index c174e27b35..155f0bd99e 100644 ---- a/sysdeps/s390/dl-procinfo.c -+++ b/sysdeps/s390/dl-procinfo.c -@@ -46,13 +46,13 @@ - #if !defined PROCINFO_DECL && defined SHARED - ._dl_s390_cap_flags - #else --PROCINFO_CLASS const char _dl_s390_cap_flags[21][9] -+PROCINFO_CLASS const char _dl_s390_cap_flags[23][9] - #endif - #ifndef PROCINFO_DECL - = { - "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", - "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt", -- "vxp2", "nnpa" -+ "vxp2", "nnpa", "pcimio", "sie" - } - #endif - #if !defined SHARED || defined PROCINFO_DECL -diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h -index 2d9c305808..e4e3e334a5 100644 ---- a/sysdeps/s390/dl-procinfo.h -+++ b/sysdeps/s390/dl-procinfo.h -@@ -21,7 +21,7 @@ - #define _DL_PROCINFO_H 1 - #include <ldsodefs.h> - --#define _DL_HWCAP_COUNT 21 -+#define _DL_HWCAP_COUNT 23 - - #define _DL_PLATFORMS_COUNT 10 - -@@ -63,6 +63,8 @@ enum - HWCAP_S390_DFLT = 1 << 18, - HWCAP_S390_VXRS_PDE2 = 1 << 19, - HWCAP_S390_NNPA = 1 << 20, -+ HWCAP_S390_PCI_MIO = 1 << 21, -+ HWCAP_S390_SIE = 1 << 22, - }; - - #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ -diff --git a/sysdeps/s390/memmem-arch13.S b/sysdeps/s390/memmem-arch13.S -index c5c8d8c97e..58df8cdb14 100644 ---- a/sysdeps/s390/memmem-arch13.S -+++ b/sysdeps/s390/memmem-arch13.S -@@ -41,7 +41,7 @@ ENTRY(MEMMEM_ARCH13) - # error The arch13 variant of memmem needs the z13 variant of memmem! - # endif - clgfi %r5,9 -- jh MEMMEM_Z13 -+ jgh MEMMEM_Z13 - - aghik %r0,%r5,-1 /* vll needs highest index. */ - bc 4,0(%r14) /* cc==1: return if needle-len == 0. */ -diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S -index c7183e627c..222a6de91a 100644 ---- a/sysdeps/s390/strstr-arch13.S -+++ b/sysdeps/s390/strstr-arch13.S -@@ -49,7 +49,7 @@ ENTRY(STRSTR_ARCH13) - # error The arch13 variant of strstr needs the z13 variant of strstr! - # endif - clgfi %r4,9 -- jh STRSTR_Z13 -+ jgh STRSTR_Z13 - - /* In case of a partial match, the vstrs instruction returns the index - of the partial match in a vector-register. Then we have to -diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h -index e9eb707d0a..bedab1abba 100644 ---- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h -@@ -126,6 +126,7 @@ - #define __NR_mbind 235 - #define __NR_membarrier 283 - #define __NR_memfd_create 279 -+#define __NR_memfd_secret 447 - #define __NR_migrate_pages 238 - #define __NR_mincore 232 - #define __NR_mkdirat 34 -@@ -187,6 +188,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h -index bd6b7d4003..91354ed9e2 100644 ---- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h -@@ -337,6 +337,7 @@ - #define __NR_pwritev2 521 - #define __NR_query_module 347 - #define __NR_quotactl 148 -+#define __NR_quotactl_fd 553 - #define __NR_read 3 - #define __NR_readahead 379 - #define __NR_readlink 58 -diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h -index 10650549c1..ff5c7eb36d 100644 ---- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h -@@ -190,6 +190,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h -index 85c9b236ce..5772333cee 100644 ---- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h -@@ -244,6 +244,7 @@ - #define __NR_pwritev 362 - #define __NR_pwritev2 393 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 225 - #define __NR_readlink 85 -diff --git a/sysdeps/unix/sysv/linux/bits/mman-linux.h b/sysdeps/unix/sysv/linux/bits/mman-linux.h -index 3b1ae418e0..31451c28d9 100644 ---- a/sysdeps/unix/sysv/linux/bits/mman-linux.h -+++ b/sysdeps/unix/sysv/linux/bits/mman-linux.h -@@ -89,6 +89,10 @@ - # define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK. */ - # define MADV_COLD 20 /* Deactivate these pages. */ - # define MADV_PAGEOUT 21 /* Reclaim these pages. */ -+# define MADV_POPULATE_READ 22 /* Populate (prefault) page tables -+ readable. */ -+# define MADV_POPULATE_WRITE 23 /* Populate (prefault) page tables -+ writable. */ - # define MADV_HWPOISON 100 /* Poison a page for testing. */ - #endif - -diff --git a/sysdeps/unix/sysv/linux/bits/timex.h b/sysdeps/unix/sysv/linux/bits/timex.h -index ee37694e8f..4a5db6deca 100644 ---- a/sysdeps/unix/sysv/linux/bits/timex.h -+++ b/sysdeps/unix/sysv/linux/bits/timex.h -@@ -25,7 +25,7 @@ - - struct timex - { --# ifdef __USE_TIME_BITS64 -+# if defined __USE_TIME_BITS64 || (__TIMESIZE == 64 && __WORDSIZE == 32) - unsigned int modes; /* mode selector */ - int :32; /* pad */ - long long offset; /* time offset (usec) */ -diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h -index 24b0d1f94e..4af6d6202f 100644 ---- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h -@@ -199,6 +199,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c -index 1391e360b8..7fc6521942 100644 ---- a/sysdeps/unix/sysv/linux/getsysstats.c -+++ b/sysdeps/unix/sysv/linux/getsysstats.c -@@ -18,6 +18,8 @@ - <https://www.gnu.org/licenses/>. */ - - #include <array_length.h> -+#include <assert.h> -+#include <ctype.h> - #include <dirent.h> - #include <errno.h> - #include <ldsodefs.h> -@@ -29,61 +31,170 @@ - #include <sys/sysinfo.h> - #include <sysdep.h> - --/* Compute the population count of the entire array. */ --static int --__get_nprocs_count (const unsigned long int *array, size_t length) -+int -+__get_nprocs_sched (void) - { -- int count = 0; -- for (size_t i = 0; i < length; ++i) -- if (__builtin_add_overflow (count, __builtin_popcountl (array[i]), -- &count)) -- return INT_MAX; -- return count; -+ enum -+ { -+ max_num_cpus = 32768, -+ cpu_bits_size = CPU_ALLOC_SIZE (32768) -+ }; -+ -+ /* This cannot use malloc because it is used on malloc initialization. */ -+ __cpu_mask cpu_bits[cpu_bits_size / sizeof (__cpu_mask)]; -+ int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size, -+ cpu_bits); -+ if (r > 0) -+ return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits); -+ else if (r == -EINVAL) -+ /* The input buffer is still not enough to store the number of cpus. This -+ is an arbitrary values assuming such systems should be rare and there -+ is no offline cpus. */ -+ return max_num_cpus; -+ /* Some other error. 2 is conservative (not a uniprocessor system, so -+ atomics are needed). */ -+ return 2; -+} -+ -+static char * -+next_line (int fd, char *const buffer, char **cp, char **re, -+ char *const buffer_end) -+{ -+ char *res = *cp; -+ char *nl = memchr (*cp, '\n', *re - *cp); -+ if (nl == NULL) -+ { -+ if (*cp != buffer) -+ { -+ if (*re == buffer_end) -+ { -+ memmove (buffer, *cp, *re - *cp); -+ *re = buffer + (*re - *cp); -+ *cp = buffer; -+ -+ ssize_t n = __read_nocancel (fd, *re, buffer_end - *re); -+ if (n < 0) -+ return NULL; -+ -+ *re += n; -+ -+ nl = memchr (*cp, '\n', *re - *cp); -+ while (nl == NULL && *re == buffer_end) -+ { -+ /* Truncate too long lines. */ -+ *re = buffer + 3 * (buffer_end - buffer) / 4; -+ n = __read_nocancel (fd, *re, buffer_end - *re); -+ if (n < 0) -+ return NULL; -+ -+ nl = memchr (*re, '\n', n); -+ **re = '\n'; -+ *re += n; -+ } -+ } -+ else -+ nl = memchr (*cp, '\n', *re - *cp); -+ -+ res = *cp; -+ } -+ -+ if (nl == NULL) -+ nl = *re - 1; -+ } -+ -+ *cp = nl + 1; -+ assert (*cp <= *re); -+ -+ return res == *re ? NULL : res; - } - --/* __get_nprocs with a large buffer. */ - static int --__get_nprocs_large (void) -+get_nproc_stat (char *buffer, size_t buffer_size) - { -- /* This code cannot use scratch_buffer because it is used during -- malloc initialization. */ -- size_t pagesize = GLRO (dl_pagesize); -- unsigned long int *page = __mmap (0, pagesize, PROT_READ | PROT_WRITE, -- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); -- if (page == MAP_FAILED) -- return 2; -- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, pagesize, page); -- int count; -- if (r > 0) -- count = __get_nprocs_count (page, pagesize / sizeof (unsigned long int)); -- else if (r == -EINVAL) -- /* One page is still not enough to store the bits. A more-or-less -- arbitrary value. This assumes t hat such large systems never -- happen in practice. */ -- count = GLRO (dl_pagesize) * CHAR_BIT; -- else -- count = 2; -- __munmap (page, GLRO (dl_pagesize)); -- return count; -+ char *buffer_end = buffer + buffer_size; -+ char *cp = buffer_end; -+ char *re = buffer_end; -+ -+ /* Default to an SMP system in case we cannot obtain an accurate -+ number. */ -+ int result = 2; -+ -+ const int flags = O_RDONLY | O_CLOEXEC; -+ int fd = __open_nocancel ("/proc/stat", flags); -+ if (fd != -1) -+ { -+ result = 0; -+ -+ char *l; -+ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) -+ /* The current format of /proc/stat has all the cpu* entries -+ at the front. We assume here that stays this way. */ -+ if (strncmp (l, "cpu", 3) != 0) -+ break; -+ else if (isdigit (l[3])) -+ ++result; -+ -+ __close_nocancel_nostatus (fd); -+ } -+ -+ return result; - } - - int - __get_nprocs (void) - { -- /* Fast path for most systems. The kernel expects a buffer size -- that is a multiple of 8. */ -- unsigned long int small_buffer[1024 / CHAR_BIT / sizeof (unsigned long int)]; -- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, -- sizeof (small_buffer), small_buffer); -- if (r > 0) -- return __get_nprocs_count (small_buffer, r / sizeof (unsigned long int)); -- else if (r == -EINVAL) -- /* The kernel requests a larger buffer to store the data. */ -- return __get_nprocs_large (); -- else -- /* Some other error. 2 is conservative (not a uniprocessor -- system, so atomics are needed). */ -- return 2; -+ enum { buffer_size = 1024 }; -+ char buffer[buffer_size]; -+ char *buffer_end = buffer + buffer_size; -+ char *cp = buffer_end; -+ char *re = buffer_end; -+ -+ const int flags = O_RDONLY | O_CLOEXEC; -+ /* This file contains comma-separated ranges. */ -+ int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags); -+ char *l; -+ int result = 0; -+ if (fd != -1) -+ { -+ l = next_line (fd, buffer, &cp, &re, buffer_end); -+ if (l != NULL) -+ do -+ { -+ char *endp; -+ unsigned long int n = strtoul (l, &endp, 10); -+ if (l == endp) -+ { -+ result = 0; -+ break; -+ } -+ -+ unsigned long int m = n; -+ if (*endp == '-') -+ { -+ l = endp + 1; -+ m = strtoul (l, &endp, 10); -+ if (l == endp) -+ { -+ result = 0; -+ break; -+ } -+ } -+ -+ result += m - n + 1; -+ -+ l = endp; -+ if (l < re && *l == ',') -+ ++l; -+ } -+ while (l < re && *l != '\n'); -+ -+ __close_nocancel_nostatus (fd); -+ -+ if (result > 0) -+ return result; -+ } -+ -+ return get_nproc_stat (buffer, buffer_size); - } - libc_hidden_def (__get_nprocs) - weak_alias (__get_nprocs, get_nprocs) -@@ -117,7 +228,9 @@ __get_nprocs_conf (void) - return count; - } - -- return 1; -+ enum { buffer_size = 1024 }; -+ char buffer[buffer_size]; -+ return get_nproc_stat (buffer, buffer_size); - } - libc_hidden_def (__get_nprocs_conf) - weak_alias (__get_nprocs_conf, get_nprocs_conf) -diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h -index feb70abc3e..b07fc8549d 100644 ---- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h -@@ -231,6 +231,7 @@ - #define __NR_pwritev 316 - #define __NR_pwritev2 348 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 207 - #define __NR_readlink 85 -diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h -index 3b1894a79b..6e4264698b 100644 ---- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h -@@ -183,6 +183,7 @@ - #define __NR_mbind 274 - #define __NR_membarrier 375 - #define __NR_memfd_create 356 -+#define __NR_memfd_secret 447 - #define __NR_migrate_pages 294 - #define __NR_mincore 218 - #define __NR_mkdir 39 -@@ -266,6 +267,7 @@ - #define __NR_pwritev2 379 - #define __NR_query_module 167 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 225 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h -index fb388a5fa4..1ca706d721 100644 ---- a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h -@@ -218,6 +218,7 @@ - #define __NR_pwritev 1320 - #define __NR_pwritev2 1349 - #define __NR_quotactl 1137 -+#define __NR_quotactl_fd 1467 - #define __NR_read 1026 - #define __NR_readahead 1216 - #define __NR_readlink 1092 -diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h -index 7bc8c4af92..2f10f71f90 100644 ---- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h -@@ -254,6 +254,7 @@ - #define __NR_pwritev2 378 - #define __NR_query_module 167 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 240 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h -index cf560d3af4..0607a4dfa6 100644 ---- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h -@@ -266,6 +266,7 @@ - #define __NR_pwritev2 394 - #define __NR_query_module 167 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 225 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/mips/fxstat.c b/sysdeps/unix/sysv/linux/mips/fxstat.c -index 11511d30b3..4a6016ff12 100644 ---- a/sysdeps/unix/sysv/linux/mips/fxstat.c -+++ b/sysdeps/unix/sysv/linux/mips/fxstat.c -@@ -35,7 +35,9 @@ __fxstat (int vers, int fd, struct stat *buf) - { - struct kernel_stat kbuf; - int r = INTERNAL_SYSCALL_CALL (fstat, fd, &kbuf); -- return r ?: __xstat_conv (vers, &kbuf, buf); -+ if (r == 0) -+ return __xstat_conv (vers, &kbuf, buf); -+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r); - } - } - } -diff --git a/sysdeps/unix/sysv/linux/mips/lxstat.c b/sysdeps/unix/sysv/linux/mips/lxstat.c -index 871fb6c6c5..54f990a250 100644 ---- a/sysdeps/unix/sysv/linux/mips/lxstat.c -+++ b/sysdeps/unix/sysv/linux/mips/lxstat.c -@@ -35,7 +35,9 @@ __lxstat (int vers, const char *name, struct stat *buf) - { - struct kernel_stat kbuf; - int r = INTERNAL_SYSCALL_CALL (lstat, name, &kbuf); -- return r ?: __xstat_conv (vers, &kbuf, buf); -+ if (r == 0) -+ return __xstat_conv (vers, &kbuf, buf); -+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r); - } - } - } -diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h -index f346460f48..0055eec0b1 100644 ---- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h -@@ -251,6 +251,7 @@ - #define __NR_pwritev2 4362 - #define __NR_query_module 4187 - #define __NR_quotactl 4131 -+#define __NR_quotactl_fd 4443 - #define __NR_read 4003 - #define __NR_readahead 4223 - #define __NR_readdir 4089 -diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h -index 38ed84997a..8e8e9f91cc 100644 ---- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h -@@ -232,6 +232,7 @@ - #define __NR_pwritev2 6326 - #define __NR_query_module 6171 - #define __NR_quotactl 6172 -+#define __NR_quotactl_fd 6443 - #define __NR_read 6000 - #define __NR_readahead 6179 - #define __NR_readlink 6087 -diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h -index e6a10c8421..ebd1545f80 100644 ---- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h -@@ -219,6 +219,7 @@ - #define __NR_pwritev2 5322 - #define __NR_query_module 5171 - #define __NR_quotactl 5172 -+#define __NR_quotactl_fd 5443 - #define __NR_read 5000 - #define __NR_readahead 5179 - #define __NR_readlink 5087 -diff --git a/sysdeps/unix/sysv/linux/mips/xstat.c b/sysdeps/unix/sysv/linux/mips/xstat.c -index 9d810b6f65..86f4dc31a8 100644 ---- a/sysdeps/unix/sysv/linux/mips/xstat.c -+++ b/sysdeps/unix/sysv/linux/mips/xstat.c -@@ -35,7 +35,9 @@ __xstat (int vers, const char *name, struct stat *buf) - { - struct kernel_stat kbuf; - int r = INTERNAL_SYSCALL_CALL (stat, name, &kbuf); -- return r ?: __xstat_conv (vers, &kbuf, buf); -+ if (r == 0) -+ return __xstat_conv (vers, &kbuf, buf); -+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r); - } - } - } -diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c -index 9799dcdaa4..eccae2e4c6 100644 ---- a/sysdeps/unix/sysv/linux/mq_notify.c -+++ b/sysdeps/unix/sysv/linux/mq_notify.c -@@ -131,7 +131,7 @@ helper_thread (void *arg) - to wait until it is done with it. */ - (void) __pthread_barrier_wait (¬ify_barrier); - } -- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) -+ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) - { - /* The only state we keep is the copy of the thread attributes. */ - __pthread_attr_destroy (data.attr); -diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h -index 5314890289..2b530b1f88 100644 ---- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h -@@ -198,6 +198,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h -index b5b0758532..a32984a9c1 100644 ---- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h -@@ -260,6 +260,7 @@ - #define __NR_pwritev2 381 - #define __NR_query_module 166 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 191 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h -index c77435ca61..b01e464fb9 100644 ---- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h -@@ -243,6 +243,7 @@ - #define __NR_pwritev2 381 - #define __NR_query_module 166 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 191 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h -index 70854bb9e3..24d0a2c455 100644 ---- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h -@@ -179,6 +179,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h -index 83b9f31aba..e526c89ae7 100644 ---- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h -@@ -187,6 +187,7 @@ - #define __NR_pwritev 70 - #define __NR_pwritev2 287 - #define __NR_quotactl 60 -+#define __NR_quotactl_fd 443 - #define __NR_read 63 - #define __NR_readahead 213 - #define __NR_readlinkat 78 -diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h -index e9bd3684db..00e73a3e3b 100644 ---- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h -+++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h -@@ -22,6 +22,11 @@ - - /* - * The following must match the kernels asm/elf.h. -+ * Note: The kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e -+ * "s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros -+ * from "HWCAP_S390_" to "HWCAP_". For compatibility reasons, we do not -+ * change the prefix in public glibc header file. -+ * - * Note that these are *not* the same as the STORE FACILITY LIST bits. - */ - #define HWCAP_S390_ESAN3 1 -@@ -48,3 +53,5 @@ - #define HWCAP_S390_DFLT 262144 - #define HWCAP_S390_VXRS_PDE2 524288 - #define HWCAP_S390_NNPA 1048576 -+#define HWCAP_S390_PCI_MIO 2097152 -+#define HWCAP_S390_SIE 4194304 -diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h -index b224c4aad4..d4c7b101b6 100644 ---- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h -@@ -251,6 +251,7 @@ - #define __NR_pwritev2 377 - #define __NR_query_module 167 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 222 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h -index 59864af125..bd8c78d705 100644 ---- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h -@@ -221,6 +221,7 @@ - #define __NR_pwritev2 377 - #define __NR_query_module 167 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 222 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h -index 23612c9092..3b6ac3d084 100644 ---- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h -@@ -246,6 +246,7 @@ - #define __NR_pwritev 334 - #define __NR_pwritev2 382 - #define __NR_quotactl 131 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 225 - #define __NR_readdir 89 -diff --git a/sysdeps/unix/sysv/linux/sparc/bits/struct_stat.h b/sysdeps/unix/sysv/linux/sparc/bits/struct_stat.h -index b481b4f9f8..45db6b6ffb 100644 ---- a/sysdeps/unix/sysv/linux/sparc/bits/struct_stat.h -+++ b/sysdeps/unix/sysv/linux/sparc/bits/struct_stat.h -@@ -28,32 +28,35 @@ - - struct stat - { -+#ifdef __USE_TIME_BITS64 -+# include <bits/struct_stat_time64_helper.h> -+#else - __dev_t st_dev; /* Device. */ --#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 -+# if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 - unsigned short int __pad1; - __ino_t st_ino; /* File serial number. */ --#else -+# else - __ino64_t st_ino; /* File serial number. */ --#endif -+# endif - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - unsigned short int __pad2; --#ifndef __USE_FILE_OFFSET64 -+# ifndef __USE_FILE_OFFSET64 - __off_t st_size; /* Size of file, in bytes. */ --#else -+# else - __off64_t st_size; /* Size of file, in bytes. */ --#endif -+# endif - __blksize_t st_blksize; /* Optimal block size for I/O. */ - --#ifndef __USE_FILE_OFFSET64 -+# ifndef __USE_FILE_OFFSET64 - __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ --#else -+# else - __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ --#endif --#ifdef __USE_XOPEN2K8 -+# endif -+# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the -@@ -63,28 +66,32 @@ struct stat - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ --# define st_atime st_atim.tv_sec /* Backward compatibility. */ --# define st_mtime st_mtim.tv_sec --# define st_ctime st_ctim.tv_sec --#else -+# define st_atime st_atim.tv_sec /* Backward compatibility. */ -+# define st_mtime st_mtim.tv_sec -+# define st_ctime st_ctim.tv_sec -+# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ --#endif -+# endif - unsigned long int __glibc_reserved4; - unsigned long int __glibc_reserved5; -+#endif /* __USE_TIME_BITS64 */ - }; - - #ifdef __USE_LARGEFILE64 - struct stat64 - { -+# ifdef __USE_TIME_BITS64 -+# include <bits/struct_stat_time64_helper.h> -+# else - __dev_t st_dev; /* Device. */ --# if __WORDSIZE == 64 -+# if __WORDSIZE == 64 - unsigned short int __pad1; --# endif -+# endif - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ -@@ -96,7 +103,7 @@ struct stat64 - __blksize_t st_blksize; /* Optimal block size for I/O. */ - - __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ --# ifdef __USE_XOPEN2K8 -+# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the -@@ -106,19 +113,20 @@ struct stat64 - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ --# define st_atime st_atim.tv_sec /* Backward compatibility. */ --# define st_mtime st_mtim.tv_sec --# define st_ctime st_ctim.tv_sec --# else -+# define st_atime st_atim.tv_sec /* Backward compatibility. */ -+# define st_mtime st_mtim.tv_sec -+# define st_ctime st_ctim.tv_sec -+# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ --# endif -+# endif - unsigned long int __glibc_reserved4; - unsigned long int __glibc_reserved5; -+# endif /* __USE_TIME_BITS64 */ - }; - #endif - -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h -index 380cddb2d8..35221a707e 100644 ---- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h -@@ -252,6 +252,7 @@ - #define __NR_pwritev2 359 - #define __NR_query_module 184 - #define __NR_quotactl 165 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 205 - #define __NR_readdir 204 -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h -index 2175eeb6ed..5ba2b20509 100644 ---- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h -@@ -231,6 +231,7 @@ - #define __NR_pwritev2 359 - #define __NR_query_module 184 - #define __NR_quotactl 165 -+#define __NR_quotactl_fd 443 - #define __NR_read 3 - #define __NR_readahead 205 - #define __NR_readdir 204 -diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h -index db88938b3a..f0e0d2f27f 100644 ---- a/sysdeps/unix/sysv/linux/sys/prctl.h -+++ b/sysdeps/unix/sysv/linux/sys/prctl.h -@@ -42,7 +42,7 @@ __BEGIN_DECLS - extern int prctl (int __option, ...) __THROW; - #else - # ifdef __REDIRECT --extern int __REDIRECT (prctl, (int __option, ...), __prctl_time64) __THROW; -+extern int __REDIRECT_NTH (prctl, (int __option, ...), __prctl_time64); - # else - extern int __prctl_time64 (int __option,d ...) __THROW; - # define ioctl __prctl_time64 -diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list -index 89c5895b9b..fd98893b0e 100644 ---- a/sysdeps/unix/sysv/linux/syscall-names.list -+++ b/sysdeps/unix/sysv/linux/syscall-names.list -@@ -21,8 +21,8 @@ - # This file can list all potential system calls. The names are only - # used if the installed kernel headers also provide them. - --# The list of system calls is current as of Linux 5.13. --kernel 5.13 -+# The list of system calls is current as of Linux 5.14. -+kernel 5.14 - - FAST_atomic_update - FAST_cmpxchg -@@ -247,6 +247,7 @@ madvise - mbind - membarrier - memfd_create -+memfd_secret - memory_ordering - migrate_pages - mincore -@@ -452,6 +453,7 @@ pwritev - pwritev2 - query_module - quotactl -+quotactl_fd - read - readahead - readdir -diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c -index dccb6189c5..f5069d1b8a 100644 ---- a/sysdeps/unix/sysv/linux/tst-close_range.c -+++ b/sysdeps/unix/sysv/linux/tst-close_range.c -@@ -36,23 +36,12 @@ - - #define NFDS 100 - --static int --open_multiple_temp_files (void) --{ -- /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); -- for (int i = 1; i <= NFDS; i++) -- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), -- lowfd + i); -- return lowfd; --} -- - static void - close_range_test_max_upper_limit (void) - { - struct support_descriptors *descrs = support_descriptors_list (); - -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - - { - int r = close_range (lowfd, ~0U, 0); -@@ -68,7 +57,7 @@ close_range_test_max_upper_limit (void) - static void - close_range_test_common (int lowfd, unsigned int flags) - { -- const int maximum_fd = lowfd + NFDS; -+ const int maximum_fd = lowfd + NFDS - 1; - const int half_fd = lowfd + NFDS / 2; - const int gap_1 = maximum_fd - 8; - -@@ -121,7 +110,7 @@ close_range_test (void) - struct support_descriptors *descrs = support_descriptors_list (); - - /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - - close_range_test_common (lowfd, 0); - -@@ -146,7 +135,7 @@ close_range_test_subprocess (void) - struct support_descriptors *descrs = support_descriptors_list (); - - /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - - struct support_stack stack = support_stack_alloc (4096); - -@@ -184,7 +173,7 @@ close_range_unshare_test (void) - struct support_descriptors *descrs1 = support_descriptors_list (); - - /* Check if the temporary file descriptor has no no gaps. */ -- int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - - struct support_descriptors *descrs2 = support_descriptors_list (); - -@@ -200,7 +189,7 @@ close_range_unshare_test (void) - - support_stack_free (&stack); - -- for (int i = 0; i < NFDS; i++) -+ for (int i = lowfd; i < lowfd + NFDS; i++) - TEST_VERIFY (fcntl (i, F_GETFL) > -1); - - support_descriptors_check (descrs2); -@@ -226,9 +215,9 @@ static void - close_range_cloexec_test (void) - { - /* Check if the temporary file descriptor has no no gaps. */ -- const int lowfd = open_multiple_temp_files (); -+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); - -- const int maximum_fd = lowfd + NFDS; -+ const int maximum_fd = lowfd + NFDS - 1; - const int half_fd = lowfd + NFDS / 2; - const int gap_1 = maximum_fd - 8; - -@@ -251,13 +240,13 @@ close_range_cloexec_test (void) - /* Create some gaps, close up to a threshold, and check result. */ - static int gap_close[] = { 57, 78, 81, 82, 84, 90 }; - for (int i = 0; i < array_length (gap_close); i++) -- xclose (gap_close[i]); -+ xclose (lowfd + gap_close[i]); - - TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0); - for (int i = half_fd + 1; i < gap_1; i++) - { - int flags = fcntl (i, F_GETFD); -- if (is_in_array (gap_close, array_length (gap_close), i)) -+ if (is_in_array (gap_close, array_length (gap_close), i - lowfd)) - TEST_COMPARE (flags, -1); - else - { -diff --git a/sysdeps/unix/sysv/linux/tst-mman-consts.py b/sysdeps/unix/sysv/linux/tst-mman-consts.py -index ee5b13ee12..810433c238 100644 ---- a/sysdeps/unix/sysv/linux/tst-mman-consts.py -+++ b/sysdeps/unix/sysv/linux/tst-mman-consts.py -@@ -33,7 +33,7 @@ def main(): - help='C compiler (including options) to use') - args = parser.parse_args() - linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) -- linux_version_glibc = (5, 13) -+ linux_version_glibc = (5, 14) - sys.exit(glibcextract.compare_macro_consts( - '#define _GNU_SOURCE 1\n' - '#include <sys/mman.h>\n', -diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h -index 8e028eb62b..26d6ac68a6 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h -@@ -154,6 +154,7 @@ - #define __NR_mbind 237 - #define __NR_membarrier 324 - #define __NR_memfd_create 319 -+#define __NR_memfd_secret 447 - #define __NR_migrate_pages 256 - #define __NR_mincore 27 - #define __NR_mkdir 83 -@@ -224,6 +225,7 @@ - #define __NR_pwritev2 328 - #define __NR_query_module 178 - #define __NR_quotactl 179 -+#define __NR_quotactl_fd 443 - #define __NR_read 0 - #define __NR_readahead 187 - #define __NR_readlink 89 -diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h -index 004feb53f1..36847783f6 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h -+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h -@@ -148,6 +148,7 @@ - #define __NR_mbind 1073742061 - #define __NR_membarrier 1073742148 - #define __NR_memfd_create 1073742143 -+#define __NR_memfd_secret 1073742271 - #define __NR_migrate_pages 1073742080 - #define __NR_mincore 1073741851 - #define __NR_mkdir 1073741907 -@@ -216,6 +217,7 @@ - #define __NR_pwritev 1073742359 - #define __NR_pwritev2 1073742371 - #define __NR_quotactl 1073742003 -+#define __NR_quotactl_fd 1073742267 - #define __NR_read 1073741824 - #define __NR_readahead 1073742011 - #define __NR_readlink 1073741913 -diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S -index 9f02624375..abde8438d4 100644 ---- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S -+++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S -@@ -325,7 +325,7 @@ L(movsb): - /* Avoid slow backward REP MOVSB. */ - jb L(more_8x_vec_backward) - # if AVOID_SHORT_DISTANCE_REP_MOVSB -- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) -+ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) - jz 3f - movq %rdi, %rcx - subq %rsi, %rcx -@@ -333,7 +333,7 @@ L(movsb): - # endif - 1: - # if AVOID_SHORT_DISTANCE_REP_MOVSB -- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) -+ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip) - jz 3f - movq %rsi, %rcx - subq %rdi, %rcx -diff -pruN glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/64/configure glibc-2.32/sysdeps/unix/sysv/linux/x86_64/64/configure ---- glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/64/configure 2021-09-18 21:02:32.741186019 +1000 -+++ glibc-2.32/sysdeps/unix/sysv/linux/x86_64/64/configure 2021-09-18 21:03:05.314302356 +1000 -@@ -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 -pruN glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h glibc-2.32/sysdeps/unix/sysv/linux/x86_64/ldconfig.h ---- glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2021-09-18 21:02:32.742186053 +1000 -+++ glibc-2.32/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2021-09-18 21:03:05.314302356 +1000 -@@ -18,9 +18,9 @@ - #include <sysdeps/generic/ldconfig.h> - - #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/glibc-32/glibc-2.35-1.patch b/glibc-32/glibc-2.35-1.patch new file mode 100644 index 00000000..ce52a6e0 --- /dev/null +++ b/glibc-32/glibc-2.35-1.patch @@ -0,0 +1,230 @@ +diff --git a/NEWS b/NEWS +index faa7ec1871..6b8db4e947 100644 +--- a/NEWS ++++ b/NEWS +@@ -4,6 +4,17 @@ See the end for copying conditions. + + Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> + using `glibc' in the "product" field. ++ ++Version 2.35.1 ++ ++The following bugs are resolved with this release: ++ ++ [28850] linux: __get_nprocs_sched reads uninitialized memory from the stack ++ [28853] libc: tst-spawn6 changes current foreground process group ++ (breaks test isolation) ++ [28860] build: --enable-kernel=5.1.0 build fails because of missing ++ __convert_scm_timestamps ++ + + Version 2.35 + +diff --git a/configure b/configure +index 00dc638388..8e5bee775a 100755 +--- a/configure ++++ b/configure +@@ -730,7 +730,6 @@ infodir + docdir + oldincludedir + includedir +-runstatedir + localstatedir + sharedstatedir + sysconfdir +@@ -845,7 +844,6 @@ datadir='${datarootdir}' + sysconfdir='${prefix}/etc' + sharedstatedir='${prefix}/com' + localstatedir='${prefix}/var' +-runstatedir='${localstatedir}/run' + includedir='${prefix}/include' + oldincludedir='/usr/include' + docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +@@ -1098,15 +1096,6 @@ do + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + +- -runstatedir | --runstatedir | --runstatedi | --runstated \ +- | --runstate | --runstat | --runsta | --runst | --runs \ +- | --run | --ru | --r) +- ac_prev=runstatedir ;; +- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ +- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ +- | --run=* | --ru=* | --r=*) +- runstatedir=$ac_optarg ;; +- + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ +@@ -1244,7 +1233,7 @@ fi + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ +- libdir localedir mandir runstatedir ++ libdir localedir mandir + do + eval ac_val=\$$ac_var + # Remove trailing slashes. +@@ -1397,7 +1386,6 @@ Fine tuning of the installation directories: + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] +- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] +diff --git a/posix/tst-spawn6.c b/posix/tst-spawn6.c +index 911e90a461..044abd8535 100644 +--- a/posix/tst-spawn6.c ++++ b/posix/tst-spawn6.c +@@ -29,7 +29,14 @@ + #include <support/check.h> + #include <support/xunistd.h> + #include <sys/wait.h> ++#include <sys/ioctl.h> + #include <stdlib.h> ++#include <termios.h> ++ ++#ifndef PATH_MAX ++# define PATH_MAX 1024 ++#endif ++static char ptmxpath[PATH_MAX]; + + static int + handle_restart (const char *argv1, const char *argv2) +@@ -115,7 +122,7 @@ run_subprogram (int argc, char *argv[], const posix_spawnattr_t *attr, + } + + static int +-do_test (int argc, char *argv[]) ++run_test (int argc, char *argv[]) + { + /* We must have either: + - four parameters left if called initially: +@@ -127,16 +134,7 @@ do_test (int argc, char *argv[]) + + --setgrpr optional + */ + +- if (restart) +- return handle_restart (argv[1], argv[2]); +- +- int tcfd = open64 (_PATH_TTY, O_RDONLY, 0600); +- if (tcfd == -1) +- { +- if (errno == ENXIO) +- FAIL_UNSUPPORTED ("terminal not available, skipping test"); +- FAIL_EXIT1 ("open64 (\"%s\", 0x%x, 0600): %m", _PATH_TTY, O_RDONLY); +- } ++ int tcfd = xopen (ptmxpath, O_RDONLY, 0600); + + /* Check setting the controlling terminal without changing the group. */ + { +@@ -198,5 +196,47 @@ do_test (int argc, char *argv[]) + return 0; + } + ++static int ++do_test (int argc, char *argv[]) ++{ ++ if (restart) ++ return handle_restart (argv[1], argv[2]); ++ ++ pid_t pid = xfork (); ++ if (pid == 0) ++ { ++ /* Create a pseudo-terminal to avoid interfering with the one using by ++ test itself, creates a new session (so there is no controlling ++ terminal), and set the pseudo-terminal as the controlling one. */ ++ int ptmx = posix_openpt (0); ++ if (ptmx == -1) ++ { ++ if (errno == ENXIO) ++ FAIL_UNSUPPORTED ("terminal not available, skipping test"); ++ FAIL_EXIT1 ("posix_openpt (0): %m"); ++ } ++ TEST_VERIFY_EXIT (grantpt (ptmx) == 0); ++ TEST_VERIFY_EXIT (unlockpt (ptmx) == 0); ++ ++ TEST_VERIFY_EXIT (setsid () != -1); ++ TEST_VERIFY_EXIT (ioctl (ptmx, TIOCSCTTY, NULL) == 0); ++ while (dup2 (ptmx, STDIN_FILENO) == -1 && errno == EBUSY) ++ ; ++ while (dup2 (ptmx, STDOUT_FILENO) == -1 && errno == EBUSY) ++ ; ++ while (dup2 (ptmx, STDERR_FILENO) == -1 && errno == EBUSY) ++ ; ++ TEST_VERIFY_EXIT (ptsname_r (ptmx, ptmxpath, sizeof ptmxpath) == 0); ++ xclose (ptmx); ++ ++ run_test (argc, argv); ++ _exit (0); ++ } ++ int status; ++ xwaitpid (pid, &status, 0); ++ TEST_VERIFY (WIFEXITED (status)); ++ exit (0); ++} ++ + #define TEST_FUNCTION_ARGV do_test + #include <support/test-driver.c> +diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +index 82171bf325..dfc8c2beff 100644 +--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c ++++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +@@ -16,9 +16,9 @@ + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +-#include <kernel-features.h> ++#include <bits/timesize.h> + +-#ifndef __ASSUME_TIME64_SYSCALLS ++#if __TIMESIZE != 64 + # include <stdint.h> + # include <string.h> + # include <sys/socket.h> +diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c +index 4798cc337e..c98c8ce3d4 100644 +--- a/sysdeps/unix/sysv/linux/getsysstats.c ++++ b/sysdeps/unix/sysv/linux/getsysstats.c +@@ -44,7 +44,7 @@ __get_nprocs_sched (void) + int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size, + cpu_bits); + if (r > 0) +- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits); ++ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits); + else if (r == -EINVAL) + /* The input buffer is still not enough to store the number of cpus. This + is an arbitrary values assuming such systems should be rare and there +diff -pruN glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/64/configure glibc-2.32/sysdeps/unix/sysv/linux/x86_64/64/configure +--- glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/64/configure 2021-09-18 21:02:32.741186019 +1000 ++++ glibc-2.32/sysdeps/unix/sysv/linux/x86_64/64/configure 2021-09-18 21:03:05.314302356 +1000 +@@ -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 -pruN glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h glibc-2.32/sysdeps/unix/sysv/linux/x86_64/ldconfig.h +--- glibc-2.32.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2021-09-18 21:02:32.742186053 +1000 ++++ glibc-2.32/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2021-09-18 21:03:05.314302356 +1000 +@@ -18,9 +18,9 @@ + #include <sysdeps/generic/ldconfig.h> + + #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 }, |