4420 lines
145 KiB
Diff
4420 lines
145 KiB
Diff
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 },
|