diff options
Diffstat (limited to 'meta/recipes-core/glibc/glibc')
19 files changed, 2694 insertions, 338 deletions
diff --git a/meta/recipes-core/glibc/glibc/0016-Add-unused-attribute.patch b/meta/recipes-core/glibc/glibc/0016-Add-unused-attribute.patch deleted file mode 100644 index 574e7c3503..0000000000 --- a/meta/recipes-core/glibc/glibc/0016-Add-unused-attribute.patch +++ /dev/null @@ -1,31 +0,0 @@ -From c323125744020a29f79e50dc4d024b55c482eafc Mon Sep 17 00:00:00 2001 -From: Khem Raj <raj.khem@gmail.com> -Date: Wed, 18 Mar 2015 00:28:41 +0000 -Subject: [PATCH] Add unused attribute - -Helps in avoiding gcc warning when header is is included in -a source file which does not use both functions - - * iconv/gconv_charset.h (strip): - Add unused attribute. - -Signed-off-by: Khem Raj <raj.khem@gmail.com> - -Upstream-Status: Pending ---- - iconv/gconv_charset.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h -index 348acc089b..fa92465d89 100644 ---- a/iconv/gconv_charset.h -+++ b/iconv/gconv_charset.h -@@ -21,7 +21,7 @@ - #include <locale.h> - - --static void -+static void __attribute__ ((unused)) - strip (char *wp, const char *s) - { - int slash_count = 0; diff --git a/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch b/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch new file mode 100644 index 0000000000..dba491f4dc --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch @@ -0,0 +1,66 @@ +From c0669ae1a629e16b536bf11cdd0865e0dbcf4bee Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 30 Dec 2020 21:52:38 +0000 +Subject: [PATCH] elf: Refactor _dl_update_slotinfo to avoid use after free + +map is not valid to access here because it can be freed by a concurrent +dlclose: during tls access (via __tls_get_addr) _dl_update_slotinfo is +called without holding dlopen locks. So don't check the modid of map. + +The map == 0 and map != 0 code paths can be shared (avoiding the dtv +resize in case of map == 0 is just an optimization: larger dtv than +necessary would be fine too). + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + elf/dl-tls.c | 21 +++++---------------- + 1 file changed, 5 insertions(+), 16 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=c0669ae1a629e16b536bf11cdd0865e0dbcf4bee] +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 24d00c14ef..f8b32b3ecb 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -743,6 +743,8 @@ _dl_update_slotinfo (unsigned long int req_modid) + { + for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { ++ size_t modid = total + cnt; ++ + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) +@@ -758,25 +760,12 @@ _dl_update_slotinfo (unsigned long int req_modid) + + /* If there is no map this means the entry is empty. */ + struct link_map *map = listp->slotinfo[cnt].map; +- if (map == NULL) +- { +- if (dtv[-1].counter >= total + cnt) +- { +- /* If this modid was used at some point the memory +- might still be allocated. */ +- free (dtv[total + cnt].pointer.to_free); +- dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; +- dtv[total + cnt].pointer.to_free = NULL; +- } +- +- continue; +- } +- + /* Check whether the current dtv array is large enough. */ +- size_t modid = map->l_tls_modid; +- assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { ++ if (map == NULL) ++ continue; ++ + /* Resize the dtv. */ + dtv = _dl_resize_dtv (dtv); + +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch new file mode 100644 index 0000000000..25beee1d50 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch @@ -0,0 +1,191 @@ +From 1387ad6225c2222f027790e3f460e31aa5dd2c54 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 30 Dec 2020 19:19:37 +0000 +Subject: [PATCH] elf: Fix data races in pthread_create and TLS access [BZ + #19329] + +DTV setup at thread creation (_dl_allocate_tls_init) is changed +to take the dlopen lock, GL(dl_load_lock). Avoiding data races +here without locks would require design changes: the map that is +accessed for static TLS initialization here may be concurrently +freed by dlclose. That use after free may be solved by only +locking around static TLS setup or by ensuring dlclose does not +free modules with static TLS, however currently every link map +with TLS has to be accessed at least to see if it needs static +TLS. And even if that's solved, still a lot of atomics would be +needed to synchronize DTV related globals without a lock. So fix +both bug 19329 and bug 27111 with a lock that prevents DTV setup +running concurrently with dlopen or dlclose. + +_dl_update_slotinfo at TLS access still does not use any locks +so CONCURRENCY NOTES are added to explain the synchronization. +The early exit from the slotinfo walk when max_modid is reached +is not strictly necessary, but does not hurt either. + +An incorrect acquire load was removed from _dl_resize_dtv: it +did not synchronize with any release store or fence and +synchronization is now handled separately at thread creation +and TLS access time. + +There are still a number of racy read accesses to globals that +will be changed to relaxed MO atomics in a followup patch. This +should not introduce regressions compared to existing behaviour +and avoid cluttering the main part of the fix. + +Not all TLS access related data races got fixed here: there are +additional races at lazy tlsdesc relocations see bug 27137. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + elf/dl-tls.c | 63 +++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 47 insertions(+), 16 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=1387ad6225c2222f027790e3f460e31aa5dd2c54] +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 6baff0c1ea..94f3cdbae0 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -475,14 +475,11 @@ extern dtv_t _dl_static_dtv[]; + #endif + + static dtv_t * +-_dl_resize_dtv (dtv_t *dtv) ++_dl_resize_dtv (dtv_t *dtv, size_t max_modid) + { + /* Resize the dtv. */ + dtv_t *newp; +- /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by +- other threads concurrently. */ +- size_t newsize +- = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS; ++ size_t newsize = max_modid + DTV_SURPLUS; + size_t oldsize = dtv[-1].counter; + + if (dtv == GL(dl_initial_dtv)) +@@ -528,11 +525,14 @@ _dl_allocate_tls_init (void *result) + size_t total = 0; + size_t maxgen = 0; + ++ /* Protects global dynamic TLS related state. */ ++ __rtld_lock_lock_recursive (GL(dl_load_lock)); ++ + /* Check if the current dtv is big enough. */ + if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) + { + /* Resize the dtv. */ +- dtv = _dl_resize_dtv (dtv); ++ dtv = _dl_resize_dtv (dtv, GL(dl_tls_max_dtv_idx)); + + /* Install this new dtv in the thread data structures. */ + INSTALL_DTV (result, &dtv[-1]); +@@ -600,6 +600,7 @@ _dl_allocate_tls_init (void *result) + listp = listp->next; + assert (listp != NULL); + } ++ __rtld_lock_unlock_recursive (GL(dl_load_lock)); + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; +@@ -734,12 +735,29 @@ _dl_update_slotinfo (unsigned long int req_modid) + + if (dtv[0].counter < listp->slotinfo[idx].gen) + { +- /* The generation counter for the slot is higher than what the +- current dtv implements. We have to update the whole dtv but +- only those entries with a generation counter <= the one for +- the entry we need. */ ++ /* CONCURRENCY NOTES: ++ ++ 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) ++ 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 ++ synchronized: a memory access here happens after the dlopen and ++ before the dlclose of relevant modules. The dtv entries for ++ relevant modules need to be updated, other entries can be ++ arbitrary. ++ ++ This e.g. means that the first part of the slotinfo list can be ++ accessed race free, but the tail may be concurrently extended. ++ Similarly relevant slotinfo entries can be read race free, but ++ other entries are racy. However updating a non-relevant dtv ++ entry does not affect correctness. For a relevant module m, ++ max_modid >= modid of m. */ + size_t new_gen = listp->slotinfo[idx].gen; + size_t total = 0; ++ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx)); ++ assert (max_modid >= req_modid); + + /* We have to look through the entire dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); +@@ -749,12 +767,14 @@ _dl_update_slotinfo (unsigned long int req_modid) + { + size_t modid = total + cnt; + ++ /* Later entries are not relevant. */ ++ if (modid > max_modid) ++ break; ++ + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) +- /* This is a slot for a generation younger than the +- one we are handling now. It might be incompletely +- set up so ignore it. */ ++ /* Not relevant. */ + continue; + + /* If the entry is older than the current dtv layout we +@@ -771,7 +791,7 @@ _dl_update_slotinfo (unsigned long int req_modid) + continue; + + /* Resize the dtv. */ +- dtv = _dl_resize_dtv (dtv); ++ dtv = _dl_resize_dtv (dtv, max_modid); + + assert (modid <= dtv[-1].counter); + +@@ -793,8 +813,17 @@ _dl_update_slotinfo (unsigned long int req_modid) + } + + total += listp->len; ++ if (total > max_modid) ++ break; ++ ++ /* Synchronize with _dl_add_to_slotinfo. Ideally this would ++ be consume MO since we only need to order the accesses to ++ the next node after the read of the address and on most ++ hardware (other than alpha) a normal load would do that ++ because of the address dependency. */ ++ listp = atomic_load_acquire (&listp->next); + } +- while ((listp = listp->next) != NULL); ++ while (listp != NULL); + + /* This will be the new maximum generation counter. */ + dtv[0].counter = new_gen; +@@ -986,7 +1015,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add) + the first slot. */ + assert (idx == 0); + +- listp = prevp->next = (struct dtv_slotinfo_list *) ++ listp = (struct dtv_slotinfo_list *) + malloc (sizeof (struct dtv_slotinfo_list) + + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + if (listp == NULL) +@@ -1000,6 +1029,8 @@ cannot create TLS data structures")); + listp->next = NULL; + memset (listp->slotinfo, '\0', + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); ++ /* Synchronize with _dl_update_slotinfo. */ ++ atomic_store_release (&prevp->next, listp); + } + + /* Add the information into the slotinfo data structure. */ +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch new file mode 100644 index 0000000000..eb8ef3161c --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch @@ -0,0 +1,206 @@ +From f4f8f4d4e0f92488431b268c8cd9555730b9afe9 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 30 Dec 2020 19:19:37 +0000 +Subject: [PATCH] elf: Use relaxed atomics for racy accesses [BZ #19329] + +This is a follow up patch to the fix for bug 19329. This adds relaxed +MO atomics to accesses that were previously data races but are now +race conditions, and where relaxed MO is sufficient. + +The race conditions all follow the pattern that the write is behind the +dlopen lock, but a read can happen concurrently (e.g. during tls access) +without holding the lock. For slotinfo entries the read value only +matters if it reads from a synchronized write in dlopen or dlclose, +otherwise the related dtv entry is not valid to access so it is fine +to leave it in an inconsistent state. The same applies for +GL(dl_tls_max_dtv_idx) and GL(dl_tls_generation), but there the +algorithm relies on the fact that the read of the last synchronized +write is an increasing value. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + elf/dl-close.c | 20 +++++++++++++------- + elf/dl-open.c | 5 ++++- + elf/dl-tls.c | 31 +++++++++++++++++++++++-------- + sysdeps/x86_64/dl-tls.c | 3 ++- + 4 files changed, 42 insertions(+), 17 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=f4f8f4d4e0f92488431b268c8cd9555730b9afe9] +Comment: Hunks from elf/dl-open.c and elf/dl-tls.c are refreshed due to offset change. +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/dl-close.c b/elf/dl-close.c +index c51becd06b..3720e47dd1 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + { + assert (old_map->l_tls_modid == idx); + +- /* Mark the entry as unused. */ +- listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1; +- listp->slotinfo[idx - disp].map = NULL; ++ /* Mark the entry as unused. These can be read concurrently. */ ++ atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, ++ GL(dl_tls_generation) + 1); ++ atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL); + } + + /* If this is not the last currently used entry no need to look +@@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + + if (listp->slotinfo[idx - disp].map != NULL) + { +- /* Found a new last used index. */ +- GL(dl_tls_max_dtv_idx) = idx; ++ /* Found a new last used index. This can be read concurrently. */ ++ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx); + return true; + } + } +@@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force) + GL(dl_tls_dtv_slotinfo_list), 0, + imap->l_init_called)) + /* All dynamically loaded modules with TLS are unloaded. */ +- GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem); ++ /* Can be read concurrently. */ ++ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), ++ GL(dl_tls_static_nelem)); + + if (imap->l_tls_offset != NO_TLS_OFFSET + && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET) +@@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force) + /* If we removed any object which uses TLS bump the generation counter. */ + if (any_tls) + { +- if (__glibc_unlikely (++GL(dl_tls_generation) == 0)) ++ size_t newgen = GL(dl_tls_generation) + 1; ++ if (__glibc_unlikely (newgen == 0)) + _dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n"); ++ /* Can be read concurrently. */ ++ atomic_store_relaxed (&GL(dl_tls_generation), newgen); + + if (tls_free_end == GL(dl_tls_static_used)) + GL(dl_tls_static_used) = tls_free_start; +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 09f0df7d38..bb79ef00f1 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -387,9 +387,12 @@ + } + } + +- if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) ++ size_t newgen = GL(dl_tls_generation) + 1; ++ if (__glibc_unlikely (newgen == 0)) + _dl_fatal_printf (N_("\ + TLS generation counter wrapped! Please report this.")); ++ /* Can be read concurrently. */ ++ atomic_store_relaxed (&GL(dl_tls_generation), newgen); + + /* We need a second pass for static tls data, because + _dl_update_slotinfo must not be run while calls to +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 94f3cdbae0..dc69cd984e 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -96,7 +96,9 @@ + /* No gaps, allocate a new entry. */ + nogaps: + +- result = ++GL(dl_tls_max_dtv_idx); ++ result = GL(dl_tls_max_dtv_idx) + 1; ++ /* Can be read concurrently. */ ++ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); + } + + return result; +@@ -279,10 +281,12 @@ + dtv_t *dtv; + size_t dtv_length; + ++ /* Relaxed MO, because the dtv size is later rechecked, not relied on. */ ++ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx)); + /* We allocate a few more elements in the dtv than are needed for the + initial set of modules. This should avoid in most cases expansions + of the dtv. */ +- dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; ++ dtv_length = max_modid + DTV_SURPLUS; + dtv = calloc (dtv_length + 2, sizeof (dtv_t)); + if (dtv != NULL) + { +@@ -687,7 +691,7 @@ + if (modid > max_modid) + break; + +- size_t gen = listp->slotinfo[cnt].gen; ++ size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen); + + if (gen > new_gen) + /* Not relevant. */ +@@ -699,7 +703,8 @@ + continue; + + /* If there is no map this means the entry is empty. */ +- struct link_map *map = listp->slotinfo[cnt].map; ++ struct link_map *map ++ = atomic_load_relaxed (&listp->slotinfo[cnt].map); + /* Check whether the current dtv array is large enough. */ + if (dtv[-1].counter < modid) + { +@@ -843,7 +848,12 @@ + { + dtv_t *dtv = THREAD_DTV (); + +- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) ++ /* Update is needed if dtv[0].counter < the generation of the accessed ++ module. The global generation counter is used here as it is easier ++ to check. Synchronization for the relaxed MO access is guaranteed ++ by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */ ++ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); ++ if (__glibc_unlikely (dtv[0].counter != gen)) + return update_get_addr (GET_ADDR_PARAM); + + void *p = dtv[GET_ADDR_MODULE].pointer.val; +@@ -866,7 +876,10 @@ + return NULL; + + dtv_t *dtv = THREAD_DTV (); +- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) ++ /* This may be called without holding the GL(dl_load_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)) + { + /* This thread's DTV is not completely current, + but it might already cover this module. */ +@@ -961,7 +974,9 @@ + /* Add the information into the slotinfo data structure. */ + if (do_add) + { +- listp->slotinfo[idx].map = l; +- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; ++ /* Can be read concurrently. See _dl_update_slotinfo. */ ++ atomic_store_relaxed (&listp->slotinfo[idx].map, l); ++ atomic_store_relaxed (&listp->slotinfo[idx].gen, ++ GL(dl_tls_generation) + 1); + } + } + +diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c +index 6595f6615b..24ef560b71 100644 +--- a/sysdeps/x86_64/dl-tls.c ++++ b/sysdeps/x86_64/dl-tls.c +@@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS) + { + dtv_t *dtv = THREAD_DTV (); + +- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) ++ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); ++ if (__glibc_unlikely (dtv[0].counter != gen)) + return update_get_addr (GET_ADDR_PARAM); + + return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch new file mode 100644 index 0000000000..f22e52ea99 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch @@ -0,0 +1,144 @@ +From 9d0e30329c23b5ad736fda3f174208c25970dbce Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Tue, 13 Dec 2016 12:28:41 +0000 +Subject: [PATCH] elf: Add test case for [BZ #19329] + +Test concurrent dlopen and pthread_create when the loaded modules have +TLS. This triggers dl-tls assertion failures more reliably than the +nptl/tst-stack4 test. + +The dlopened module has 100 DT_NEEDED dependencies with TLS, they were +reused from an existing TLS test. The number of created threads during +dlopen depends on filesystem speed and hardware, but at most 3 threads +are alive at a time to limit resource usage. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + elf/Makefile | 9 ++++-- + elf/tst-tls21.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ + elf/tst-tls21mod.c | 1 + + 3 files changed, 76 insertions(+), 2 deletions(-) + create mode 100644 elf/tst-tls21.c + create mode 100644 elf/tst-tls21mod.c +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=9d0e30329c23b5ad736fda3f174208c25970dbce] +Comment: Hunks from elf/Makefile are refreshed as per glibc 2.31 codebase. +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/Makefile b/elf/Makefile +index d3e909637a..3241cb6046 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -201,7 +201,7 @@ + tst-unwind-ctor tst-unwind-main tst-audit13 \ + tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \ + tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ +- tst-dlopenfail-2 ++ tst-dlopenfail-2 tst-tls21 + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -312,7 +312,7 @@ + tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +- tst-dlopenfailmod3 tst-ldconfig-ld-mod ++ tst-dlopenfailmod3 tst-ldconfig-ld-mod tst-tls21mod + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. + modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\ +@@ -1697,5 +1697,10 @@ + $(objpfx)tst-dlopen-nodelete-reloc-mod16.so + LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed + ++# Reuses tst-tls-many-dynamic-modules ++$(objpfx)tst-tls21: $(libdl) $(shared-thread-library) ++$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so ++$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) ++ + $(objpfx)tst-ldconfig-ld_so_conf-update.out: $(objpfx)tst-ldconfig-ld-mod.so + $(objpfx)tst-ldconfig-ld_so_conf-update: $(libdl) +diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c +new file mode 100644 +index 0000000000..560bf5813a +--- /dev/null ++++ b/elf/tst-tls21.c +@@ -0,0 +1,68 @@ ++/* Test concurrent dlopen and pthread_create: BZ 19329. ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <dlfcn.h> ++#include <pthread.h> ++#include <stdio.h> ++#include <stdatomic.h> ++#include <support/xdlfcn.h> ++#include <support/xthread.h> ++ ++#define THREADS 10000 ++ ++static atomic_int done; ++ ++static void * ++start (void *a) ++{ ++ /* Load a module with many dependencies that each have TLS. */ ++ xdlopen ("tst-tls21mod.so", RTLD_LAZY); ++ atomic_store_explicit (&done, 1, memory_order_release); ++ return 0; ++} ++ ++static void * ++nop (void *a) ++{ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t t1, t2; ++ int i; ++ ++ /* Load a module with lots of dependencies and TLS. */ ++ t1 = xpthread_create (0, start, 0); ++ ++ /* Concurrently create lots of threads until dlopen is observably done. */ ++ for (i = 0; i < THREADS; i++) ++ { ++ if (atomic_load_explicit (&done, memory_order_acquire) != 0) ++ break; ++ t2 = xpthread_create (0, nop, 0); ++ xpthread_join (t2); ++ } ++ ++ xpthread_join (t1); ++ printf ("threads created during dlopen: %d\n", i); ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c +new file mode 100644 +index 0000000000..206ece4fb3 +--- /dev/null ++++ b/elf/tst-tls21mod.c +@@ -0,0 +1 @@ ++int __thread x; +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch b/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch new file mode 100644 index 0000000000..a87afe3230 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch @@ -0,0 +1,180 @@ +From ba33937be210da5d07f7f01709323743f66011ce Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Date: Fri, 25 Jun 2021 10:54:12 -0300 +Subject: [PATCH] elf: Fix DTV gap reuse logic (BZ #27135) + +This is updated version of the 572bd547d57a (reverted by 40ebfd016ad2) +that fixes the _dl_next_tls_modid issues. + +This issue with 572bd547d57a patch is the DTV entry will be only +update on dl_open_worker() with the update_tls_slotinfo() call after +all dependencies are being processed by _dl_map_object_deps(). However +_dl_map_object_deps() itself might call _dl_next_tls_modid(), and since +the _dl_tls_dtv_slotinfo_list::map is not yet set the entry will be +wrongly reused. + +This patch fixes by renaming the _dl_next_tls_modid() function to +_dl_assign_tls_modid() and by passing the link_map so it can set +the slotinfo value so a subsequente _dl_next_tls_modid() call will +see the entry as allocated. + +The intermediary value is cleared up on remove_slotinfo() for the case +a library fails to load with RTLD_NOW. + +This patch fixes BZ #27135. + +Checked on x86_64-linux-gnu. + +Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> +--- + elf/dl-close.c | 8 +- + elf/dl-load.c | 2 +- + elf/dl-open.c | 10 -- + elf/dl-tls.c | 17 +-- + elf/rtld.c | 2 +- + sysdeps/generic/ldsodefs.h | 4 +- + 6 files changed, 349 insertions(+), 33 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ba33937be210da5d07f7f01709323743f66011ce] +Comment: Removed hunks those were related to test. Hunk from elf/rtld.c is refreshed. +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 3720e47dd1..f39001cab9 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -77,8 +77,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + object that wasn't fully set up. */ + if (__glibc_likely (old_map != NULL)) + { +- assert (old_map->l_tls_modid == idx); +- + /* Mark the entry as unused. These can be read concurrently. */ + atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, + GL(dl_tls_generation) + 1); +@@ -88,7 +86,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + /* If this is not the last currently used entry no need to look + further. */ + if (idx != GL(dl_tls_max_dtv_idx)) +- return true; ++ { ++ /* There is an unused dtv entry in the middle. */ ++ GL(dl_tls_dtv_gaps) = true; ++ return true; ++ } + } + + while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) +diff --git a/elf/dl-load.c b/elf/dl-load.c +index a08df001af..650e4edc35 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1498,7 +1498,7 @@ cannot enable executable stack as shared object requires"); + not set up TLS data structures, so don't use them now. */ + || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))) + /* Assign the next available module ID. */ +- l->l_tls_modid = _dl_next_tls_modid (); ++ _dl_assign_tls_modid (l); + + #ifdef DL_AFTER_LOAD + DL_AFTER_LOAD (l); +diff --git a/elf/dl-open.c b/elf/dl-open.c +index a066f39bd0..d2240d8747 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -899,16 +899,6 @@ no more namespaces available for dlmopen()")); + state if relocation failed, for example. */ + if (args.map) + { +- /* Maybe some of the modules which were loaded use TLS. +- Since it will be removed in the following _dl_close call +- we have to mark the dtv array as having gaps to fill the +- holes. This is a pessimistic assumption which won't hurt +- if not true. There is no need to do this when we are +- loading the auditing DSOs since TLS has not yet been set +- up. */ +- if ((mode & __RTLD_AUDIT) == 0) +- GL(dl_tls_dtv_gaps) = true; +- + _dl_close_worker (args.map, true); + + /* All l_nodelete_pending objects should have been deleted +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 2b5161d10a..423e380f7c 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -126,8 +126,8 @@ oom (void) + } + + +-size_t +-_dl_next_tls_modid (void) ++void ++_dl_assign_tls_modid (struct link_map *l) + { + size_t result; + +@@ -157,7 +157,11 @@ _dl_next_tls_modid (void) + } + + if (result - disp < runp->len) +- break; ++ { ++ /* Mark the entry as used, so any dependency see it. */ ++ atomic_store_relaxed (&runp->slotinfo[result - disp].map, l); ++ break; ++ } + + disp += runp->len; + } +@@ -184,17 +188,14 @@ _dl_next_tls_modid (void) + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); + } + +- return result; ++ l->l_tls_modid = result; + } + + + size_t + _dl_count_modids (void) + { +- /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where +- we fail to load a module and unload it leaving a gap. If we don't +- have gaps then the number of modids is the current maximum so +- return that. */ ++ /* The count is the max unless dlclose or failed dlopen created gaps. */ + if (__glibc_likely (!GL(dl_tls_dtv_gaps))) + return GL(dl_tls_max_dtv_idx); + +diff --git a/elf/rtld.c b/elf/rtld.c +index e3fb2a5b2a..d733359eaf 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1612,7 +1612,7 @@ + /* Add the dynamic linker to the TLS list if it also uses TLS. */ + if (GL(dl_rtld_map).l_tls_blocksize != 0) + /* Assign a module ID. Do this before loading any audit modules. */ +- GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); ++ _dl_assign_tls_modid (&GL(dl_rtld_map)); + + /* If we have auditing DSOs to load, do it now. */ + bool need_security_init = true; +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 176394de4d..9c15259236 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1171,8 +1171,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr, + extern void _dl_sysdep_start_cleanup (void) attribute_hidden; + + +-/* Determine next available module ID. */ +-extern size_t _dl_next_tls_modid (void) attribute_hidden; ++/* Determine next available module ID and set the L l_tls_modid. */ ++extern void _dl_assign_tls_modid (struct link_map *l) attribute_hidden; + + /* Count the modules with TLS segments. */ + extern size_t _dl_count_modids (void) attribute_hidden; +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch b/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch new file mode 100644 index 0000000000..899111b118 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch @@ -0,0 +1,56 @@ +From 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 11 Feb 2021 11:29:23 +0000 +Subject: [PATCH] x86_64: Avoid lazy relocation of tlsdesc [BZ #27137] + +Lazy tlsdesc relocation is racy because the static tls optimization and +tlsdesc management operations are done without holding the dlopen lock. + +This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 +for aarch64, but it fixes a different race: bug 27137. + +Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to +relocate tlsdesc lazily, but that does not work in a BIND_NOW module +due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at +load time fixes this bug 27721 too. +--- + sysdeps/x86_64/dl-machine.h | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86] +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index 103eee6c3f..9a876a371e 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -570,12 +570,21 @@ elf_machine_lazy_rel (struct link_map *map, + } + else if (__glibc_likely (r_type == R_X86_64_TLSDESC)) + { +- struct tlsdesc volatile * __attribute__((__unused__)) td = +- (struct tlsdesc volatile *)reloc_addr; ++ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); ++ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); ++ const ElfW (Sym) *sym = &symtab[symndx]; ++ const struct r_found_version *version = NULL; + +- td->arg = (void*)reloc; +- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) +- + map->l_addr); ++ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) ++ { ++ const ElfW (Half) *vernum = ++ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); ++ version = &map->l_versions[vernum[symndx] & 0x7fff]; ++ } ++ ++ /* Always initialize TLS descriptors completely at load time, in ++ case static TLS is allocated for it that requires locking. */ ++ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); + } + else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE)) + { +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch b/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch new file mode 100644 index 0000000000..ad0a1147aa --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch @@ -0,0 +1,124 @@ +From ddcacd91cc10ff92d6201eda87047d029c14158d Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 11 Feb 2021 11:40:11 +0000 +Subject: [PATCH] i386: Avoid lazy relocation of tlsdesc [BZ #27137] + +Lazy tlsdesc relocation is racy because the static tls optimization and +tlsdesc management operations are done without holding the dlopen lock. + +This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 +for aarch64, but it fixes a different race: bug 27137. + +On i386 the code is a bit more complicated than on x86_64 because both +rel and rela relocs are supported. +--- + sysdeps/i386/dl-machine.h | 76 ++++++++++++++++++--------------------- + 1 file changed, 34 insertions(+), 42 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ddcacd91cc10ff92d6201eda87047d029c14158d] +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 23e9cc3bfb..590b41d8d7 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -688,50 +688,32 @@ elf_machine_lazy_rel (struct link_map *map, + } + else if (__glibc_likely (r_type == R_386_TLS_DESC)) + { +- struct tlsdesc volatile * __attribute__((__unused__)) td = +- (struct tlsdesc volatile *)reloc_addr; +- +- /* Handle relocations that reference the local *ABS* in a simple +- way, so as to preserve a potential addend. */ +- if (ELF32_R_SYM (reloc->r_info) == 0) +- td->entry = _dl_tlsdesc_resolve_abs_plus_addend; +- /* Given a known-zero addend, we can store a pointer to the +- reloc in the arg position. */ +- else if (td->arg == 0) +- { +- td->arg = (void*)reloc; +- td->entry = _dl_tlsdesc_resolve_rel; +- } +- else +- { +- /* We could handle non-*ABS* relocations with non-zero addends +- by allocating dynamically an arg to hold a pointer to the +- reloc, but that sounds pointless. */ +- const Elf32_Rel *const r = reloc; +- /* The code below was borrowed from elf_dynamic_do_rel(). */ +- const ElfW(Sym) *const symtab = +- (const void *) D_PTR (map, l_info[DT_SYMTAB]); ++ const Elf32_Rel *const r = reloc; ++ /* The code below was borrowed from elf_dynamic_do_rel(). */ ++ const ElfW(Sym) *const symtab = ++ (const void *) D_PTR (map, l_info[DT_SYMTAB]); + ++ /* Always initialize TLS descriptors completely at load time, in ++ case static TLS is allocated for it that requires locking. */ + # ifdef RTLD_BOOTSTRAP +- /* The dynamic linker always uses versioning. */ +- assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); ++ /* The dynamic linker always uses versioning. */ ++ assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); + # else +- if (map->l_info[VERSYMIDX (DT_VERSYM)]) ++ if (map->l_info[VERSYMIDX (DT_VERSYM)]) + # endif +- { +- const ElfW(Half) *const version = +- (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); +- ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], +- &map->l_versions[ndx], +- (void *) (l_addr + r->r_offset), skip_ifunc); +- } ++ { ++ const ElfW(Half) *const version = ++ (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); ++ ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; ++ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], ++ &map->l_versions[ndx], ++ (void *) (l_addr + r->r_offset), skip_ifunc); ++ } + # ifndef RTLD_BOOTSTRAP +- else +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, +- (void *) (l_addr + r->r_offset), skip_ifunc); ++ else ++ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, ++ (void *) (l_addr + r->r_offset), skip_ifunc); + # endif +- } + } + else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) + { +@@ -758,11 +740,21 @@ elf_machine_lazy_rela (struct link_map *map, + ; + else if (__glibc_likely (r_type == R_386_TLS_DESC)) + { +- struct tlsdesc volatile * __attribute__((__unused__)) td = +- (struct tlsdesc volatile *)reloc_addr; ++ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); ++ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); ++ const ElfW (Sym) *sym = &symtab[symndx]; ++ const struct r_found_version *version = NULL; ++ ++ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) ++ { ++ const ElfW (Half) *vernum = ++ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); ++ version = &map->l_versions[vernum[symndx] & 0x7fff]; ++ } + +- td->arg = (void*)reloc; +- td->entry = _dl_tlsdesc_resolve_rela; ++ /* Always initialize TLS descriptors completely at load time, in ++ case static TLS is allocated for it that requires locking. */ ++ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); + } + else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) + { +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch b/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch new file mode 100644 index 0000000000..7a10131bad --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch @@ -0,0 +1,276 @@ +From 83b5323261bb72313bffcf37476c1b8f0847c736 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 15 Sep 2021 15:16:19 +0100 +Subject: [PATCH] elf: Avoid deadlock between pthread_create and ctors [BZ + #28357] + +The fix for bug 19329 caused a regression such that pthread_create can +deadlock when concurrent ctors from dlopen are waiting for it to finish. +Use a new GL(dl_load_tls_lock) in pthread_create that is not taken +around ctors in dlopen. + +The new lock is also used in __tls_get_addr instead of GL(dl_load_lock). + +The new lock is held in _dl_open_worker and _dl_close_worker around +most of the logic before/after the init/fini routines. When init/fini +routines are running then TLS is in a consistent, usable state. +In _dl_open_worker the new lock requires catching and reraising dlopen +failures that happen in the critical section. + +The new lock is reinitialized in a fork child, to keep the existing +behaviour and it is kept recursive in case malloc interposition or TLS +access from signal handlers can retake it. It is not obvious if this +is necessary or helps, but avoids changing the preexisting behaviour. + +The new lock may be more appropriate for dl_iterate_phdr too than +GL(dl_load_write_lock), since TLS state of an incompletely loaded +module may be accessed. If the new lock can replace the old one, +that can be a separate change. + +Fixes bug 28357. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + elf/dl-close.c | 6 ++ + elf/dl-open.c | 35 ++++++++- + elf/dl-support.c | 7 ++ + elf/dl-tls.c | 16 ++--- + elf/rtld.c | 1 + + sysdeps/nptl/fork.c | 3 + + sysdeps/generic/ldsodefs.h | 9 ++- + 10 files changed, 235 insertions(+), 12 deletions(-) +--- +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=024a7640ab9ecea80e527f4e4d7f7a1868e952c5] +Comment: This patch is refreshed for glibc 2.31. In upstream glibc 2.34 multiple src files are shuffled, updated this patch as per the code present in glibc 2.31. Removed test case. +Signed-off-by: Akash Hadke <akash.hadke@kpit.com> +Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> +--- +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 93ff5c96e9..cfe0f1c0c9 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -551,6 +551,9 @@ + 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)); + +@@ -786,6 +789,9 @@ + 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-open.c b/elf/dl-open.c +index 5295e931b0..6ea5dd2457 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -57,6 +57,9 @@ + (non-negative). */ + unsigned int original_global_scope_pending_adds; + ++ /* 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; +@@ -473,7 +473,7 @@ + } + + static void +-dl_open_worker (void *a) ++dl_open_worker_begin (void *a) + { + struct dl_open_args *args = a; + const char *file = args->file; +@@ -747,6 +747,36 @@ + if (mode & RTLD_GLOBAL) + add_to_global_resize (new); + ++ 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. */ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 02e2ed72f5..d99c1f1d62 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -219,6 +219,13 @@ + 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-tls.c b/elf/dl-tls.c +index d554ae4497..9260d2d696 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -443,7 +443,7 @@ + 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)) +@@ -517,7 +517,7 @@ + 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; +@@ -656,7 +656,7 @@ + + 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 +@@ -778,11 +778,11 @@ + 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)) +@@ -794,7 +794,7 @@ + #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; +@@ -802,7 +802,7 @@ + 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; +@@ -873,7 +873,7 @@ + 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/rtld.c b/elf/rtld.c +index 8d2bba3d43..9642eb9c92 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -283,6 +283,7 @@ + #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 = +diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index c471f7b15f..021691b9b7 100644 +--- a/sysdeps/nptl/fork.c ++++ b/sysdeps/nptl/fork.c +@@ -125,6 +125,9 @@ + /* 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)); ++ + /* Run the handlers registered for the child. */ + __run_fork_handlers (atfork_run_child, multiple_threads); + } +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index d49529da0d..9ec1511bb0 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -369,6 +369,13 @@ + 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; +@@ -1153,7 +1160,7 @@ + + /* 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. */ +-- +2.27.0 diff --git a/meta/recipes-core/glibc/glibc/CVE-2020-29573.patch b/meta/recipes-core/glibc/glibc/CVE-2020-29573.patch new file mode 100644 index 0000000000..1e75f2d29d --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2020-29573.patch @@ -0,0 +1,128 @@ +From 681900d29683722b1cb0a8e565a0585846ec5a61 Mon Sep 17 00:00:00 2001 +From: Florian Weimer <fweimer@redhat.com> +Date: Tue, 22 Sep 2020 19:07:48 +0200 +Subject: [PATCH] x86: Harden printf against non-normal long double values (bug + 26649) + +The behavior of isnan/__builtin_isnan on bit patterns that do not +correspond to something that the CPU would produce from valid inputs +is currently under-defined in the toolchain. (The GCC built-in and +glibc disagree.) + +The isnan check in PRINTF_FP_FETCH in stdio-common/printf_fp.c +assumes the GCC behavior that returns true for non-normal numbers +which are not specified as NaN. (The glibc implementation returns +false for such numbers.) + +At present, passing non-normal numbers to __mpn_extract_long_double +causes this function to produce irregularly shaped multi-precision +integers, triggering undefined behavior in __printf_fp_l. + +With GCC 10 and glibc 2.32, this behavior is not visible because +__builtin_isnan is used, which avoids calling +__mpn_extract_long_double in this case. This commit updates the +implementation of __mpn_extract_long_double so that regularly shaped +multi-precision integers are produced in this case, avoiding +undefined behavior in __printf_fp_l. + +Upstream-Status: Backport [git://sourceware.org/git/glibc.git] +CVE: CVE-2020-29573 +Signed-off-By: Armin Kuster <akuster@mvista.com> + +--- + sysdeps/x86/Makefile | 4 ++ + sysdeps/x86/ldbl2mpn.c | 8 ++++ + sysdeps/x86/tst-ldbl-nonnormal-printf.c | 52 +++++++++++++++++++++++++ + 3 files changed, 64 insertions(+) + create mode 100644 sysdeps/x86/tst-ldbl-nonnormal-printf.c + +Index: git/sysdeps/x86/Makefile +=================================================================== +--- git.orig/sysdeps/x86/Makefile ++++ git/sysdeps/x86/Makefile +@@ -9,6 +9,10 @@ tests += tst-get-cpu-features tst-get-cp + tests-static += tst-get-cpu-features-static + endif + ++ifeq ($(subdir),math) ++tests += tst-ldbl-nonnormal-printf ++endif # $(subdir) == math ++ + ifeq ($(subdir),setjmp) + gen-as-const-headers += jmp_buf-ssp.sym + sysdep_routines += __longjmp_cancel +Index: git/sysdeps/x86/tst-ldbl-nonnormal-printf.c +=================================================================== +--- /dev/null ++++ git/sysdeps/x86/tst-ldbl-nonnormal-printf.c +@@ -0,0 +1,52 @@ ++/* Test printf with x86-specific non-normal long double value. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <string.h> ++#include <support/check.h> ++ ++/* Fill the stack with non-zero values. This makes a crash in ++ snprintf more likely. */ ++static void __attribute__ ((noinline, noclone)) ++fill_stack (void) ++{ ++ char buffer[65536]; ++ memset (buffer, 0xc0, sizeof (buffer)); ++ asm ("" ::: "memory"); ++} ++ ++static int ++do_test (void) ++{ ++ fill_stack (); ++ ++ long double value; ++ memcpy (&value, "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x04", 10); ++ ++ char buf[30]; ++ int ret = snprintf (buf, sizeof (buf), "%Lg", value); ++ TEST_COMPARE (ret, strlen (buf)); ++ if (strcmp (buf, "nan") != 0) ++ /* If snprintf does not recognize the non-normal number as a NaN, ++ it has added the missing explicit MSB. */ ++ TEST_COMPARE_STRING (buf, "3.02201e-4624"); ++ return 0; ++} ++ ++#include <support/test-driver.c> +Index: git/sysdeps/i386/ldbl2mpn.c +=================================================================== +--- git.orig/sysdeps/i386/ldbl2mpn.c ++++ git/sysdeps/i386/ldbl2mpn.c +@@ -115,6 +115,12 @@ __mpn_extract_long_double (mp_ptr res_pt + && res_ptr[N - 1] == 0) + /* Pseudo zero. */ + *expt = 0; +- ++ else ++ /* The sign bit is explicit, but add it in case it is missing in ++ the input. Otherwise, callers will not be able to produce the ++ expected multi-precision integer layout by shifting the sign ++ bit into the MSB. */ ++ res_ptr[N - 1] |= (mp_limb_t) 1 << (LDBL_MANT_DIG - 1 ++ - ((N - 1) * BITS_PER_MP_LIMB)); + return N; + } diff --git a/meta/recipes-core/glibc/glibc/CVE-2020-6096.patch b/meta/recipes-core/glibc/glibc/CVE-2020-6096.patch deleted file mode 100644 index 9c26f76432..0000000000 --- a/meta/recipes-core/glibc/glibc/CVE-2020-6096.patch +++ /dev/null @@ -1,112 +0,0 @@ -From beea361050728138b82c57dda0c4810402d342b9 Mon Sep 17 00:00:00 2001 -From: Alexander Anisimov <a.anisimov@omprussia.ru> -Date: Wed, 8 Jul 2020 14:18:31 +0200 -Subject: [PATCH] arm: CVE-2020-6096: Fix multiarch memcpy for negative length - [BZ #25620] - -Unsigned branch instructions could be used for r2 to fix the wrong -behavior when a negative length is passed to memcpy. -This commit fixes the armv7 version. - -Upstream-Status: Backport -CVE: CVE-2020-6096 patch #1 -Signed-off-by: Armin Kuster <akuster@mvista.com> - ---- - sysdeps/arm/armv7/multiarch/memcpy_impl.S | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/sysdeps/arm/armv7/multiarch/memcpy_impl.S b/sysdeps/arm/armv7/multiarch/memcpy_impl.S -index bf4ac7077f..379bb56fc9 100644 ---- a/sysdeps/arm/armv7/multiarch/memcpy_impl.S -+++ b/sysdeps/arm/armv7/multiarch/memcpy_impl.S -@@ -268,7 +268,7 @@ ENTRY(memcpy) - - mov dst, dstin /* Preserve dstin, we need to return it. */ - cmp count, #64 -- bge .Lcpy_not_short -+ bhs .Lcpy_not_short - /* Deal with small copies quickly by dropping straight into the - exit block. */ - -@@ -351,10 +351,10 @@ ENTRY(memcpy) - - 1: - subs tmp2, count, #64 /* Use tmp2 for count. */ -- blt .Ltail63aligned -+ blo .Ltail63aligned - - cmp tmp2, #512 -- bge .Lcpy_body_long -+ bhs .Lcpy_body_long - - .Lcpy_body_medium: /* Count in tmp2. */ - #ifdef USE_VFP -@@ -378,7 +378,7 @@ ENTRY(memcpy) - add src, src, #64 - vstr d1, [dst, #56] - add dst, dst, #64 -- bge 1b -+ bhs 1b - tst tmp2, #0x3f - beq .Ldone - -@@ -412,7 +412,7 @@ ENTRY(memcpy) - ldrd A_l, A_h, [src, #64]! - strd A_l, A_h, [dst, #64]! - subs tmp2, tmp2, #64 -- bge 1b -+ bhs 1b - tst tmp2, #0x3f - bne 1f - ldr tmp2,[sp], #FRAME_SIZE -@@ -482,7 +482,7 @@ ENTRY(memcpy) - add src, src, #32 - - subs tmp2, tmp2, #prefetch_lines * 64 * 2 -- blt 2f -+ blo 2f - 1: - cpy_line_vfp d3, 0 - cpy_line_vfp d4, 64 -@@ -494,7 +494,7 @@ ENTRY(memcpy) - add dst, dst, #2 * 64 - add src, src, #2 * 64 - subs tmp2, tmp2, #prefetch_lines * 64 -- bge 1b -+ bhs 1b - - 2: - cpy_tail_vfp d3, 0 -@@ -615,8 +615,8 @@ ENTRY(memcpy) - 1: - pld [src, #(3 * 64)] - subs count, count, #64 -- ldrmi tmp2, [sp], #FRAME_SIZE -- bmi .Ltail63unaligned -+ ldrlo tmp2, [sp], #FRAME_SIZE -+ blo .Ltail63unaligned - pld [src, #(4 * 64)] - - #ifdef USE_NEON -@@ -633,7 +633,7 @@ ENTRY(memcpy) - neon_load_multi d0-d3, src - neon_load_multi d4-d7, src - subs count, count, #64 -- bmi 2f -+ blo 2f - 1: - pld [src, #(4 * 64)] - neon_store_multi d0-d3, dst -@@ -641,7 +641,7 @@ ENTRY(memcpy) - neon_store_multi d4-d7, dst - neon_load_multi d4-d7, src - subs count, count, #64 -- bpl 1b -+ bhs 1b - 2: - neon_store_multi d0-d3, dst - neon_store_multi d4-d7, dst --- -2.17.1 - diff --git a/meta/recipes-core/glibc/glibc/CVE-2020-6096_2.patch b/meta/recipes-core/glibc/glibc/CVE-2020-6096_2.patch deleted file mode 100644 index 905e44c8e3..0000000000 --- a/meta/recipes-core/glibc/glibc/CVE-2020-6096_2.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 79a4fa341b8a89cb03f84564fd72abaa1a2db394 Mon Sep 17 00:00:00 2001 -From: Evgeny Eremin <e.eremin@omprussia.ru> -Date: Wed, 8 Jul 2020 14:18:19 +0200 -Subject: [PATCH] arm: CVE-2020-6096: fix memcpy and memmove for negative - length [BZ #25620] - -Unsigned branch instructions could be used for r2 to fix the wrong -behavior when a negative length is passed to memcpy and memmove. -This commit fixes the generic arm implementation of memcpy amd memmove. - -Upstream-Status: Backport -CVE: CVE-2020-6096 patch #2 -Signed-off-by: Armin Kuster <akuster@mvista.com> - ---- - sysdeps/arm/memcpy.S | 24 ++++++++++-------------- - sysdeps/arm/memmove.S | 24 ++++++++++-------------- - 2 files changed, 20 insertions(+), 28 deletions(-) - -diff --git a/sysdeps/arm/memcpy.S b/sysdeps/arm/memcpy.S -index 510e8adaf2..bcfbc51d99 100644 ---- a/sysdeps/arm/memcpy.S -+++ b/sysdeps/arm/memcpy.S -@@ -68,7 +68,7 @@ ENTRY(memcpy) - cfi_remember_state - - subs r2, r2, #4 -- blt 8f -+ blo 8f - ands ip, r0, #3 - PLD( pld [r1, #0] ) - bne 9f -@@ -82,7 +82,7 @@ ENTRY(memcpy) - cfi_rel_offset (r6, 4) - cfi_rel_offset (r7, 8) - cfi_rel_offset (r8, 12) -- blt 5f -+ blo 5f - - CALGN( ands ip, r1, #31 ) - CALGN( rsb r3, ip, #32 ) -@@ -98,9 +98,9 @@ ENTRY(memcpy) - #endif - - PLD( pld [r1, #0] ) --2: PLD( subs r2, r2, #96 ) -+2: PLD( cmp r2, #96 ) - PLD( pld [r1, #28] ) -- PLD( blt 4f ) -+ PLD( blo 4f ) - PLD( pld [r1, #60] ) - PLD( pld [r1, #92] ) - -@@ -108,9 +108,7 @@ ENTRY(memcpy) - 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} - subs r2, r2, #32 - stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} -- bge 3b -- PLD( cmn r2, #96 ) -- PLD( bge 4b ) -+ bhs 3b - - 5: ands ip, r2, #28 - rsb ip, ip, #32 -@@ -222,7 +220,7 @@ ENTRY(memcpy) - strbge r4, [r0], #1 - subs r2, r2, ip - strb lr, [r0], #1 -- blt 8b -+ blo 8b - ands ip, r1, #3 - beq 1b - -@@ -236,7 +234,7 @@ ENTRY(memcpy) - .macro forward_copy_shift pull push - - subs r2, r2, #28 -- blt 14f -+ blo 14f - - CALGN( ands ip, r1, #31 ) - CALGN( rsb ip, ip, #32 ) -@@ -253,9 +251,9 @@ ENTRY(memcpy) - cfi_rel_offset (r10, 16) - - PLD( pld [r1, #0] ) -- PLD( subs r2, r2, #96 ) -+ PLD( cmp r2, #96 ) - PLD( pld [r1, #28] ) -- PLD( blt 13f ) -+ PLD( blo 13f ) - PLD( pld [r1, #60] ) - PLD( pld [r1, #92] ) - -@@ -280,9 +278,7 @@ ENTRY(memcpy) - mov ip, ip, PULL #\pull - orr ip, ip, lr, PUSH #\push - stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip} -- bge 12b -- PLD( cmn r2, #96 ) -- PLD( bge 13b ) -+ bhs 12b - - pop {r5 - r8, r10} - cfi_adjust_cfa_offset (-20) -diff --git a/sysdeps/arm/memmove.S b/sysdeps/arm/memmove.S -index 954037ef3a..0d07b76ee6 100644 ---- a/sysdeps/arm/memmove.S -+++ b/sysdeps/arm/memmove.S -@@ -85,7 +85,7 @@ ENTRY(memmove) - add r1, r1, r2 - add r0, r0, r2 - subs r2, r2, #4 -- blt 8f -+ blo 8f - ands ip, r0, #3 - PLD( pld [r1, #-4] ) - bne 9f -@@ -99,7 +99,7 @@ ENTRY(memmove) - cfi_rel_offset (r6, 4) - cfi_rel_offset (r7, 8) - cfi_rel_offset (r8, 12) -- blt 5f -+ blo 5f - - CALGN( ands ip, r1, #31 ) - CALGN( sbcsne r4, ip, r2 ) @ C is always set here -@@ -114,9 +114,9 @@ ENTRY(memmove) - #endif - - PLD( pld [r1, #-4] ) --2: PLD( subs r2, r2, #96 ) -+2: PLD( cmp r2, #96 ) - PLD( pld [r1, #-32] ) -- PLD( blt 4f ) -+ PLD( blo 4f ) - PLD( pld [r1, #-64] ) - PLD( pld [r1, #-96] ) - -@@ -124,9 +124,7 @@ ENTRY(memmove) - 4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} - subs r2, r2, #32 - stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} -- bge 3b -- PLD( cmn r2, #96 ) -- PLD( bge 4b ) -+ bhs 3b - - 5: ands ip, r2, #28 - rsb ip, ip, #32 -@@ -237,7 +235,7 @@ ENTRY(memmove) - strbge r4, [r0, #-1]! - subs r2, r2, ip - strb lr, [r0, #-1]! -- blt 8b -+ blo 8b - ands ip, r1, #3 - beq 1b - -@@ -251,7 +249,7 @@ ENTRY(memmove) - .macro backward_copy_shift push pull - - subs r2, r2, #28 -- blt 14f -+ blo 14f - - CALGN( ands ip, r1, #31 ) - CALGN( rsb ip, ip, #32 ) -@@ -268,9 +266,9 @@ ENTRY(memmove) - cfi_rel_offset (r10, 16) - - PLD( pld [r1, #-4] ) -- PLD( subs r2, r2, #96 ) -+ PLD( cmp r2, #96 ) - PLD( pld [r1, #-32] ) -- PLD( blt 13f ) -+ PLD( blo 13f ) - PLD( pld [r1, #-64] ) - PLD( pld [r1, #-96] ) - -@@ -295,9 +293,7 @@ ENTRY(memmove) - mov r4, r4, PUSH #\push - orr r4, r4, r3, PULL #\pull - stmdb r0!, {r4 - r8, r10, ip, lr} -- bge 12b -- PLD( cmn r2, #96 ) -- PLD( bge 13b ) -+ bhs 12b - - pop {r5 - r8, r10} - cfi_adjust_cfa_offset (-20) --- -2.17.1 - diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch b/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch new file mode 100644 index 0000000000..7561e87121 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch @@ -0,0 +1,68 @@ +From 42d359350510506b87101cf77202fefcbfc790cb Mon Sep 17 00:00:00 2001 +From: Andreas Schwab <schwab@linux-m68k.org> +Date: Thu, 27 May 2021 12:49:47 +0200 +Subject: [PATCH] Use __pthread_attr_copy in mq_notify (bug 27896) + +Make a deep copy of the pthread attribute object to remove a potential +use-after-free issue. + +Upstream-Status: Backport +CVE: CVE-2021-33574 patch#1 +Signed-off-by: Armin Kuster <akuster@mvista.com> + +--- +diff --git a/NEWS b/NEWS +index 8a20d3c4e3..be489243ac 100644 +--- a/NEWS ++++ b/NEWS +@@ -7,6 +7,10 @@ using `glibc' in the "product" field. + + Version 2.31.1 + ++ CVE-2021-33574: The mq_notify function has a potential use-after-free ++ issue when using a notification type of SIGEV_THREAD and a thread ++ attribute with a non-default affinity mask. ++ + The following bugs are resolved with this release: + [14231] stdio-common tests memory requirements + [19519] iconv(1) with -c option hangs on illegal multi-byte sequences +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index f288bac477..dd47f0b777 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -135,8 +135,11 @@ helper_thread (void *arg) + (void) __pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) +- /* The only state we keep is the copy of the thread attributes. */ +- free (data.attr); ++ { ++ /* The only state we keep is the copy of the thread attributes. */ ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + } + return NULL; + } +@@ -257,8 +260,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + if (data.attr == NULL) + return -1; + +- memcpy (data.attr, notification->sigev_notify_attributes, +- sizeof (pthread_attr_t)); ++ __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); + } + + /* Construct the new request. */ +@@ -272,7 +274,10 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + + /* If it failed, free the allocated memory. */ + if (__glibc_unlikely (retval != 0)) +- free (data.attr); ++ { ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + + return retval; + } diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch b/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch new file mode 100644 index 0000000000..396cd7fc0e --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch @@ -0,0 +1,73 @@ +From 217b6dc298156bdb0d6aea9ea93e7e394a5ff091 Mon Sep 17 00:00:00 2001 +From: Florian Weimer <fweimer@redhat.com> +Date: Tue, 1 Jun 2021 17:51:41 +0200 +Subject: [PATCH] Fix use of __pthread_attr_copy in mq_notify (bug 27896) + +__pthread_attr_copy can fail and does not initialize the attribute +structure in that case. + +If __pthread_attr_copy is never called and there is no allocated +attribute, pthread_attr_destroy should not be called, otherwise +there is a null pointer dereference in rt/tst-mqueue6. + +Fixes commit 42d359350510506b87101cf77202fefcbfc790cb +("Use __pthread_attr_copy in mq_notify (bug 27896)"). + +Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> + +https://sourceware.org/bugzilla/attachment.cgi?id=13497 + +Upstream-Status: Backport +CVE: CVE-2021-33574 patch#2 +Signed-off-by: Armin Kuster <akuster@mvista.com> + +--- +Index: git/sysdeps/unix/sysv/linux/mq_notify.c +=================================================================== +--- git.orig/sysdeps/unix/sysv/linux/mq_notify.c ++++ git/sysdeps/unix/sysv/linux/mq_notify.c +@@ -260,7 +260,34 @@ mq_notify (mqd_t mqdes, const struct sig + if (data.attr == NULL) + return -1; + +- __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); ++ memcpy (data.attr, notification->sigev_notify_attributes, ++ sizeof (pthread_attr_t)); ++ ++ struct pthread_attr *source = ++ (struct pthread_attr *) (notification->sigev_notify_attributes); ++ struct pthread_attr *target = (struct pthread_attr *) (data.attr); ++ cpu_set_t *newp; ++ cpu_set_t *cpuset = source->cpuset; ++ size_t cpusetsize = source->cpusetsize; ++ ++ /* alloc a new memory for cpuset to avoid use after free */ ++ if (cpuset != NULL && cpusetsize > 0) ++ { ++ newp = (cpu_set_t *) malloc (cpusetsize); ++ if (newp == NULL) ++ { ++ free(data.attr); ++ return -1; ++ } ++ ++ memcpy (newp, cpuset, cpusetsize); ++ target->cpuset = newp; ++ } ++ else ++ { ++ target->cpuset = NULL; ++ target->cpusetsize = 0; ++ } + } + + /* Construct the new request. */ +@@ -273,7 +300,7 @@ mq_notify (mqd_t mqdes, const struct sig + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ +- if (__glibc_unlikely (retval != 0)) ++ if (retval != 0 && data.attr != NULL) + { + pthread_attr_destroy (data.attr); + free (data.attr); diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch b/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch new file mode 100644 index 0000000000..36fd4a61b2 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch @@ -0,0 +1,41 @@ +From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <npv1310@gmail.com> +Date: Mon, 9 Aug 2021 20:17:34 +0530 +Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213) + +Helper thread frees copied attribute on NOTIFY_REMOVED message +received from the OS kernel. Unfortunately, it fails to check whether +copied attribute actually exists (data.attr != NULL). This worked +earlier because free() checks passed pointer before actually +attempting to release corresponding memory. But +__pthread_attr_destroy assumes pointer is not NULL. + +So passing NULL pointer to __pthread_attr_destroy will result in +segmentation fault. This scenario is possible if +notification->sigev_notify_attributes == NULL (which means default +thread attributes should be used). + +Signed-off-by: Nikita Popov <npv1310@gmail.com> +Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> + +Upstream-Status: Backport +CVE: CVE-2021-38604 +Signed-off-by: Armin Kuser <akuster@mvista.com> + +--- + sysdeps/unix/sysv/linux/mq_notify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: git/sysdeps/unix/sysv/linux/mq_notify.c +=================================================================== +--- git.orig/sysdeps/unix/sysv/linux/mq_notify.c ++++ git/sysdeps/unix/sysv/linux/mq_notify.c +@@ -134,7 +134,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/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch b/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch new file mode 100644 index 0000000000..10c7e5666d --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch @@ -0,0 +1,82 @@ +From 952aff5c00ad7c6b83c3f310f2643939538827f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= + =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru> +Date: Sat, 4 Feb 2023 14:41:38 +0300 +Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The `__monstartup()` allocates a buffer used to store all the data +accumulated by the monitor. + +The size of this buffer depends on the size of the internal structures +used and the address range for which the monitor is activated, as well +as on the maximum density of call instructions and/or callable functions +that could be potentially on a segment of executable code. + +In particular a hash table of arcs is placed at the end of this buffer. +The size of this hash table is calculated in bytes as + p->fromssize = p->textsize / HASHFRACTION; + +but actually should be + p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + +This results in writing beyond the end of the allocated buffer when an +added arc corresponds to a call near from the end of the monitored +address range, since `_mcount()` check the incoming caller address for +monitored range but not the intermediate result hash-like index that +uses to write into the table. + +It should be noted that when the results are output to `gmon.out`, the +table is read to the last element calculated from the allocated size in +bytes, so the arcs stored outside the buffer boundary did not fall into +`gprof` for analysis. Thus this "feature" help me to found this bug +during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438 + +Just in case, I will explicitly note that the problem breaks the +`make test t=gmon/tst-gmon-dso` added for Bug 29438. +There, the arc of the `f3()` call disappears from the output, since in +the DSO case, the call to `f3` is located close to the end of the +monitored range. + +Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru> + +Another minor error seems a related typo in the calculation of +`kcountsize`, but since kcounts are smaller than froms, this is +actually to align the p->froms data. + +Co-authored-by: DJ Delorie <dj@redhat.com> +Reviewed-by: Carlos O'Donell <carlos@redhat.com> + +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=801af9fafd4689337ebf27260aa115335a0cb2bc] +CVE: CVE-2023-0687 +Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> +--- + gmon/gmon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gmon/gmon.c b/gmon/gmon.c +index dee6480..bf76358 100644 +--- a/gmon/gmon.c ++++ b/gmon/gmon.c +@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc) + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; ++ /* This looks like a typo, but it's here to align the p->froms ++ section. */ + p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; +@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc) + instead of integer division. Precompute shift amount. */ + p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; + } +- p->fromssize = p->textsize / HASHFRACTION; ++ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; +-- +2.7.4 diff --git a/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch b/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch new file mode 100644 index 0000000000..c7db4038c2 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch @@ -0,0 +1,986 @@ +From 1c37b8022e8763fedbb3f79c02e05c6acfe5a215 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@sourceware.org> +Date: Thu, 17 Mar 2022 11:44:34 +0530 +Subject: [PATCH] Simplify allocations and fix merge and continue actions [BZ + #28931] + +Allocations for address tuples is currently a bit confusing because of +the pointer chasing through PAT, making it hard to observe the sequence +in which allocations have been made. Narrow scope of the pointer +chasing through PAT so that it is only used where necessary. + +This also tightens actions behaviour with the hosts database in +getaddrinfo to comply with the manual text. The "continue" action +discards previous results and the "merge" action results in an immedate +lookup failure. Consequently, chaining of allocations across modules is +no longer necessary, thus opening up cleanup opportunities. + +A test has been added that checks some combinations to ensure that they +work correctly. + +Resolves: BZ #28931 + +CVE: CVE-2023-4813 +Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=1c37b8022e8763fedbb3f79c02e05c6acfe5a215] +Comments: Hunks refreshed + +Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +Reviewed-by: DJ Delorie <dj@redhat.com> +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + nss/Makefile | 1 + + nss/tst-nss-gai-actions.c | 149 ++++++ + nss/tst-nss-gai-actions.root/etc/host.conf | 1 + + nss/tst-nss-gai-actions.root/etc/hosts | 508 +++++++++++++++++++++ + sysdeps/posix/getaddrinfo.c | 143 +++--- + 5 files changed, 750 insertions(+), 52 deletions(-) + create mode 100644 nss/tst-nss-gai-actions.c + create mode 100644 nss/tst-nss-gai-actions.root/etc/host.conf + create mode 100644 nss/tst-nss-gai-actions.root/etc/hosts + +diff --git a/nss/Makefile b/nss/Makefile +index 42a59535cb..d8b06b44fb 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -61,6 +61,7 @@ + + tests-container = \ + tst-nss-test3 \ ++ tst-nss-gai-actions \ + tst-nss-files-hosts-long \ + tst-nss-db-endpwent \ + tst-nss-db-endgrent +diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c +new file mode 100644 +index 0000000000..efca6cd183 +--- /dev/null ++++ b/nss/tst-nss-gai-actions.c +@@ -0,0 +1,149 @@ ++/* Test continue and merge NSS actions for getaddrinfo. ++ 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 ++ 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 <dlfcn.h> ++#include <gnu/lib-names.h> ++#include <nss.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#include <support/check.h> ++#include <support/format_nss.h> ++#include <support/support.h> ++#include <support/xstdio.h> ++#include <support/xunistd.h> ++ ++enum ++{ ++ ACTION_MERGE = 0, ++ ACTION_CONTINUE, ++}; ++ ++static const char * ++family_str (int family) ++{ ++ switch (family) ++ { ++ case AF_UNSPEC: ++ return "AF_UNSPEC"; ++ case AF_INET: ++ return "AF_INET"; ++ default: ++ __builtin_unreachable (); ++ } ++} ++ ++static const char * ++action_str (int action) ++{ ++ switch (action) ++ { ++ case ACTION_MERGE: ++ return "merge"; ++ case ACTION_CONTINUE: ++ return "continue"; ++ default: ++ __builtin_unreachable (); ++ } ++} ++ ++static void ++do_one_test (int action, int family, bool canon) ++{ ++ struct addrinfo hints = ++ { ++ .ai_family = family, ++ }; ++ ++ struct addrinfo *ai; ++ ++ if (canon) ++ hints.ai_flags = AI_CANONNAME; ++ ++ printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n", ++ action_str (action), family_str (family), ++ canon ? "AI_CANONNAME" : ""); ++ ++ int ret = getaddrinfo ("example.org", "80", &hints, &ai); ++ ++ switch (action) ++ { ++ case ACTION_MERGE: ++ if (ret == 0) ++ { ++ char *formatted = support_format_addrinfo (ai, ret); ++ ++ printf ("merge unexpectedly succeeded:\n %s\n", formatted); ++ support_record_failure (); ++ free (formatted); ++ } ++ else ++ return; ++ case ACTION_CONTINUE: ++ { ++ char *formatted = support_format_addrinfo (ai, ret); ++ ++ /* Verify that the result appears exactly once. */ ++ const char *expected = "address: STREAM/TCP 192.0.0.1 80\n" ++ "address: DGRAM/UDP 192.0.0.1 80\n" ++ "address: RAW/IP 192.0.0.1 80\n"; ++ ++ const char *contains = strstr (formatted, expected); ++ const char *contains2 = NULL; ++ ++ if (contains != NULL) ++ contains2 = strstr (contains + strlen (expected), expected); ++ ++ if (contains == NULL || contains2 != NULL) ++ { ++ printf ("continue failed:\n%s\n", formatted); ++ support_record_failure (); ++ } ++ ++ free (formatted); ++ break; ++ } ++ default: ++ __builtin_unreachable (); ++ } ++} ++ ++static void ++do_one_test_set (int action) ++{ ++ char buf[32]; ++ ++ snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files", ++ action_str (action)); ++ __nss_configure_lookup ("hosts", buf); ++ ++ do_one_test (action, AF_UNSPEC, false); ++ do_one_test (action, AF_INET, false); ++ do_one_test (action, AF_INET, true); ++} ++ ++static int ++do_test (void) ++{ ++ do_one_test_set (ACTION_CONTINUE); ++ do_one_test_set (ACTION_MERGE); ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/nss/tst-nss-gai-actions.root/etc/host.conf b/nss/tst-nss-gai-actions.root/etc/host.conf +new file mode 100644 +index 0000000000..d1a59f73a9 +--- /dev/null ++++ b/nss/tst-nss-gai-actions.root/etc/host.conf +@@ -0,0 +1 @@ ++multi on +diff --git a/nss/tst-nss-gai-actions.root/etc/hosts b/nss/tst-nss-gai-actions.root/etc/hosts +new file mode 100644 +index 0000000000..50ce9774dc +--- /dev/null ++++ b/nss/tst-nss-gai-actions.root/etc/hosts +@@ -0,0 +1,508 @@ ++192.0.0.1 example.org ++192.0.0.2 example.org ++192.0.0.3 example.org ++192.0.0.4 example.org ++192.0.0.5 example.org ++192.0.0.6 example.org ++192.0.0.7 example.org ++192.0.0.8 example.org ++192.0.0.9 example.org ++192.0.0.10 example.org ++192.0.0.11 example.org ++192.0.0.12 example.org ++192.0.0.13 example.org ++192.0.0.14 example.org ++192.0.0.15 example.org ++192.0.0.16 example.org ++192.0.0.17 example.org ++192.0.0.18 example.org ++192.0.0.19 example.org ++192.0.0.20 example.org ++192.0.0.21 example.org ++192.0.0.22 example.org ++192.0.0.23 example.org ++192.0.0.24 example.org ++192.0.0.25 example.org ++192.0.0.26 example.org ++192.0.0.27 example.org ++192.0.0.28 example.org ++192.0.0.29 example.org ++192.0.0.30 example.org ++192.0.0.31 example.org ++192.0.0.32 example.org ++192.0.0.33 example.org ++192.0.0.34 example.org ++192.0.0.35 example.org ++192.0.0.36 example.org ++192.0.0.37 example.org ++192.0.0.38 example.org ++192.0.0.39 example.org ++192.0.0.40 example.org ++192.0.0.41 example.org ++192.0.0.42 example.org ++192.0.0.43 example.org ++192.0.0.44 example.org ++192.0.0.45 example.org ++192.0.0.46 example.org ++192.0.0.47 example.org ++192.0.0.48 example.org ++192.0.0.49 example.org ++192.0.0.50 example.org ++192.0.0.51 example.org ++192.0.0.52 example.org ++192.0.0.53 example.org ++192.0.0.54 example.org ++192.0.0.55 example.org ++192.0.0.56 example.org ++192.0.0.57 example.org ++192.0.0.58 example.org ++192.0.0.59 example.org ++192.0.0.60 example.org ++192.0.0.61 example.org ++192.0.0.62 example.org ++192.0.0.63 example.org ++192.0.0.64 example.org ++192.0.0.65 example.org ++192.0.0.66 example.org ++192.0.0.67 example.org ++192.0.0.68 example.org ++192.0.0.69 example.org ++192.0.0.70 example.org ++192.0.0.71 example.org ++192.0.0.72 example.org ++192.0.0.73 example.org ++192.0.0.74 example.org ++192.0.0.75 example.org ++192.0.0.76 example.org ++192.0.0.77 example.org ++192.0.0.78 example.org ++192.0.0.79 example.org ++192.0.0.80 example.org ++192.0.0.81 example.org ++192.0.0.82 example.org ++192.0.0.83 example.org ++192.0.0.84 example.org ++192.0.0.85 example.org ++192.0.0.86 example.org ++192.0.0.87 example.org ++192.0.0.88 example.org ++192.0.0.89 example.org ++192.0.0.90 example.org ++192.0.0.91 example.org ++192.0.0.92 example.org ++192.0.0.93 example.org ++192.0.0.94 example.org ++192.0.0.95 example.org ++192.0.0.96 example.org ++192.0.0.97 example.org ++192.0.0.98 example.org ++192.0.0.99 example.org ++192.0.0.100 example.org ++192.0.0.101 example.org ++192.0.0.102 example.org ++192.0.0.103 example.org ++192.0.0.104 example.org ++192.0.0.105 example.org ++192.0.0.106 example.org ++192.0.0.107 example.org ++192.0.0.108 example.org ++192.0.0.109 example.org ++192.0.0.110 example.org ++192.0.0.111 example.org ++192.0.0.112 example.org ++192.0.0.113 example.org ++192.0.0.114 example.org ++192.0.0.115 example.org ++192.0.0.116 example.org ++192.0.0.117 example.org ++192.0.0.118 example.org ++192.0.0.119 example.org ++192.0.0.120 example.org ++192.0.0.121 example.org ++192.0.0.122 example.org ++192.0.0.123 example.org ++192.0.0.124 example.org ++192.0.0.125 example.org ++192.0.0.126 example.org ++192.0.0.127 example.org ++192.0.0.128 example.org ++192.0.0.129 example.org ++192.0.0.130 example.org ++192.0.0.131 example.org ++192.0.0.132 example.org ++192.0.0.133 example.org ++192.0.0.134 example.org ++192.0.0.135 example.org ++192.0.0.136 example.org ++192.0.0.137 example.org ++192.0.0.138 example.org ++192.0.0.139 example.org ++192.0.0.140 example.org ++192.0.0.141 example.org ++192.0.0.142 example.org ++192.0.0.143 example.org ++192.0.0.144 example.org ++192.0.0.145 example.org ++192.0.0.146 example.org ++192.0.0.147 example.org ++192.0.0.148 example.org ++192.0.0.149 example.org ++192.0.0.150 example.org ++192.0.0.151 example.org ++192.0.0.152 example.org ++192.0.0.153 example.org ++192.0.0.154 example.org ++192.0.0.155 example.org ++192.0.0.156 example.org ++192.0.0.157 example.org ++192.0.0.158 example.org ++192.0.0.159 example.org ++192.0.0.160 example.org ++192.0.0.161 example.org ++192.0.0.162 example.org ++192.0.0.163 example.org ++192.0.0.164 example.org ++192.0.0.165 example.org ++192.0.0.166 example.org ++192.0.0.167 example.org ++192.0.0.168 example.org ++192.0.0.169 example.org ++192.0.0.170 example.org ++192.0.0.171 example.org ++192.0.0.172 example.org ++192.0.0.173 example.org ++192.0.0.174 example.org ++192.0.0.175 example.org ++192.0.0.176 example.org ++192.0.0.177 example.org ++192.0.0.178 example.org ++192.0.0.179 example.org ++192.0.0.180 example.org ++192.0.0.181 example.org ++192.0.0.182 example.org ++192.0.0.183 example.org ++192.0.0.184 example.org ++192.0.0.185 example.org ++192.0.0.186 example.org ++192.0.0.187 example.org ++192.0.0.188 example.org ++192.0.0.189 example.org ++192.0.0.190 example.org ++192.0.0.191 example.org ++192.0.0.192 example.org ++192.0.0.193 example.org ++192.0.0.194 example.org ++192.0.0.195 example.org ++192.0.0.196 example.org ++192.0.0.197 example.org ++192.0.0.198 example.org ++192.0.0.199 example.org ++192.0.0.200 example.org ++192.0.0.201 example.org ++192.0.0.202 example.org ++192.0.0.203 example.org ++192.0.0.204 example.org ++192.0.0.205 example.org ++192.0.0.206 example.org ++192.0.0.207 example.org ++192.0.0.208 example.org ++192.0.0.209 example.org ++192.0.0.210 example.org ++192.0.0.211 example.org ++192.0.0.212 example.org ++192.0.0.213 example.org ++192.0.0.214 example.org ++192.0.0.215 example.org ++192.0.0.216 example.org ++192.0.0.217 example.org ++192.0.0.218 example.org ++192.0.0.219 example.org ++192.0.0.220 example.org ++192.0.0.221 example.org ++192.0.0.222 example.org ++192.0.0.223 example.org ++192.0.0.224 example.org ++192.0.0.225 example.org ++192.0.0.226 example.org ++192.0.0.227 example.org ++192.0.0.228 example.org ++192.0.0.229 example.org ++192.0.0.230 example.org ++192.0.0.231 example.org ++192.0.0.232 example.org ++192.0.0.233 example.org ++192.0.0.234 example.org ++192.0.0.235 example.org ++192.0.0.236 example.org ++192.0.0.237 example.org ++192.0.0.238 example.org ++192.0.0.239 example.org ++192.0.0.240 example.org ++192.0.0.241 example.org ++192.0.0.242 example.org ++192.0.0.243 example.org ++192.0.0.244 example.org ++192.0.0.245 example.org ++192.0.0.246 example.org ++192.0.0.247 example.org ++192.0.0.248 example.org ++192.0.0.249 example.org ++192.0.0.250 example.org ++192.0.0.251 example.org ++192.0.0.252 example.org ++192.0.0.253 example.org ++192.0.0.254 example.org ++192.0.1.1 example.org ++192.0.1.2 example.org ++192.0.1.3 example.org ++192.0.1.4 example.org ++192.0.1.5 example.org ++192.0.1.6 example.org ++192.0.1.7 example.org ++192.0.1.8 example.org ++192.0.1.9 example.org ++192.0.1.10 example.org ++192.0.1.11 example.org ++192.0.1.12 example.org ++192.0.1.13 example.org ++192.0.1.14 example.org ++192.0.1.15 example.org ++192.0.1.16 example.org ++192.0.1.17 example.org ++192.0.1.18 example.org ++192.0.1.19 example.org ++192.0.1.20 example.org ++192.0.1.21 example.org ++192.0.1.22 example.org ++192.0.1.23 example.org ++192.0.1.24 example.org ++192.0.1.25 example.org ++192.0.1.26 example.org ++192.0.1.27 example.org ++192.0.1.28 example.org ++192.0.1.29 example.org ++192.0.1.30 example.org ++192.0.1.31 example.org ++192.0.1.32 example.org ++192.0.1.33 example.org ++192.0.1.34 example.org ++192.0.1.35 example.org ++192.0.1.36 example.org ++192.0.1.37 example.org ++192.0.1.38 example.org ++192.0.1.39 example.org ++192.0.1.40 example.org ++192.0.1.41 example.org ++192.0.1.42 example.org ++192.0.1.43 example.org ++192.0.1.44 example.org ++192.0.1.45 example.org ++192.0.1.46 example.org ++192.0.1.47 example.org ++192.0.1.48 example.org ++192.0.1.49 example.org ++192.0.1.50 example.org ++192.0.1.51 example.org ++192.0.1.52 example.org ++192.0.1.53 example.org ++192.0.1.54 example.org ++192.0.1.55 example.org ++192.0.1.56 example.org ++192.0.1.57 example.org ++192.0.1.58 example.org ++192.0.1.59 example.org ++192.0.1.60 example.org ++192.0.1.61 example.org ++192.0.1.62 example.org ++192.0.1.63 example.org ++192.0.1.64 example.org ++192.0.1.65 example.org ++192.0.1.66 example.org ++192.0.1.67 example.org ++192.0.1.68 example.org ++192.0.1.69 example.org ++192.0.1.70 example.org ++192.0.1.71 example.org ++192.0.1.72 example.org ++192.0.1.73 example.org ++192.0.1.74 example.org ++192.0.1.75 example.org ++192.0.1.76 example.org ++192.0.1.77 example.org ++192.0.1.78 example.org ++192.0.1.79 example.org ++192.0.1.80 example.org ++192.0.1.81 example.org ++192.0.1.82 example.org ++192.0.1.83 example.org ++192.0.1.84 example.org ++192.0.1.85 example.org ++192.0.1.86 example.org ++192.0.1.87 example.org ++192.0.1.88 example.org ++192.0.1.89 example.org ++192.0.1.90 example.org ++192.0.1.91 example.org ++192.0.1.92 example.org ++192.0.1.93 example.org ++192.0.1.94 example.org ++192.0.1.95 example.org ++192.0.1.96 example.org ++192.0.1.97 example.org ++192.0.1.98 example.org ++192.0.1.99 example.org ++192.0.1.100 example.org ++192.0.1.101 example.org ++192.0.1.102 example.org ++192.0.1.103 example.org ++192.0.1.104 example.org ++192.0.1.105 example.org ++192.0.1.106 example.org ++192.0.1.107 example.org ++192.0.1.108 example.org ++192.0.1.109 example.org ++192.0.1.110 example.org ++192.0.1.111 example.org ++192.0.1.112 example.org ++192.0.1.113 example.org ++192.0.1.114 example.org ++192.0.1.115 example.org ++192.0.1.116 example.org ++192.0.1.117 example.org ++192.0.1.118 example.org ++192.0.1.119 example.org ++192.0.1.120 example.org ++192.0.1.121 example.org ++192.0.1.122 example.org ++192.0.1.123 example.org ++192.0.1.124 example.org ++192.0.1.125 example.org ++192.0.1.126 example.org ++192.0.1.127 example.org ++192.0.1.128 example.org ++192.0.1.129 example.org ++192.0.1.130 example.org ++192.0.1.131 example.org ++192.0.1.132 example.org ++192.0.1.133 example.org ++192.0.1.134 example.org ++192.0.1.135 example.org ++192.0.1.136 example.org ++192.0.1.137 example.org ++192.0.1.138 example.org ++192.0.1.139 example.org ++192.0.1.140 example.org ++192.0.1.141 example.org ++192.0.1.142 example.org ++192.0.1.143 example.org ++192.0.1.144 example.org ++192.0.1.145 example.org ++192.0.1.146 example.org ++192.0.1.147 example.org ++192.0.1.148 example.org ++192.0.1.149 example.org ++192.0.1.150 example.org ++192.0.1.151 example.org ++192.0.1.152 example.org ++192.0.1.153 example.org ++192.0.1.154 example.org ++192.0.1.155 example.org ++192.0.1.156 example.org ++192.0.1.157 example.org ++192.0.1.158 example.org ++192.0.1.159 example.org ++192.0.1.160 example.org ++192.0.1.161 example.org ++192.0.1.162 example.org ++192.0.1.163 example.org ++192.0.1.164 example.org ++192.0.1.165 example.org ++192.0.1.166 example.org ++192.0.1.167 example.org ++192.0.1.168 example.org ++192.0.1.169 example.org ++192.0.1.170 example.org ++192.0.1.171 example.org ++192.0.1.172 example.org ++192.0.1.173 example.org ++192.0.1.174 example.org ++192.0.1.175 example.org ++192.0.1.176 example.org ++192.0.1.177 example.org ++192.0.1.178 example.org ++192.0.1.179 example.org ++192.0.1.180 example.org ++192.0.1.181 example.org ++192.0.1.182 example.org ++192.0.1.183 example.org ++192.0.1.184 example.org ++192.0.1.185 example.org ++192.0.1.186 example.org ++192.0.1.187 example.org ++192.0.1.188 example.org ++192.0.1.189 example.org ++192.0.1.190 example.org ++192.0.1.191 example.org ++192.0.1.192 example.org ++192.0.1.193 example.org ++192.0.1.194 example.org ++192.0.1.195 example.org ++192.0.1.196 example.org ++192.0.1.197 example.org ++192.0.1.198 example.org ++192.0.1.199 example.org ++192.0.1.200 example.org ++192.0.1.201 example.org ++192.0.1.202 example.org ++192.0.1.203 example.org ++192.0.1.204 example.org ++192.0.1.205 example.org ++192.0.1.206 example.org ++192.0.1.207 example.org ++192.0.1.208 example.org ++192.0.1.209 example.org ++192.0.1.210 example.org ++192.0.1.211 example.org ++192.0.1.212 example.org ++192.0.1.213 example.org ++192.0.1.214 example.org ++192.0.1.215 example.org ++192.0.1.216 example.org ++192.0.1.217 example.org ++192.0.1.218 example.org ++192.0.1.219 example.org ++192.0.1.220 example.org ++192.0.1.221 example.org ++192.0.1.222 example.org ++192.0.1.223 example.org ++192.0.1.224 example.org ++192.0.1.225 example.org ++192.0.1.226 example.org ++192.0.1.227 example.org ++192.0.1.228 example.org ++192.0.1.229 example.org ++192.0.1.230 example.org ++192.0.1.231 example.org ++192.0.1.232 example.org ++192.0.1.233 example.org ++192.0.1.234 example.org ++192.0.1.235 example.org ++192.0.1.236 example.org ++192.0.1.237 example.org ++192.0.1.238 example.org ++192.0.1.239 example.org ++192.0.1.240 example.org ++192.0.1.241 example.org ++192.0.1.242 example.org ++192.0.1.243 example.org ++192.0.1.244 example.org ++192.0.1.245 example.org ++192.0.1.246 example.org ++192.0.1.247 example.org ++192.0.1.248 example.org ++192.0.1.249 example.org ++192.0.1.250 example.org ++192.0.1.251 example.org ++192.0.1.252 example.org ++192.0.1.253 example.org ++192.0.1.254 example.org +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 18dccd5924..3d9bea60c6 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -458,11 +458,6 @@ gaih_inet (const char *name, const struct gaih_service *service, + + if (name != NULL) + { +- at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); +- at->family = AF_UNSPEC; +- at->scopeid = 0; +- at->next = NULL; +- + if (req->ai_flags & AI_IDN) + { + char *out; +@@ -473,13 +468,21 @@ gaih_inet (const char *name, const struct gaih_service *service, + malloc_name = true; + } + +- if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) ++ uint32_t addr[4]; ++ if (__inet_aton_exact (name, (struct in_addr *) addr) != 0) + { ++ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); ++ at->scopeid = 0; ++ at->next = NULL; ++ + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) +- at->family = AF_INET; ++ { ++ memcpy (at->addr, addr, sizeof (at->addr)); ++ at->family = AF_INET; ++ } + else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED)) + { +- at->addr[3] = at->addr[0]; ++ at->addr[3] = addr[0]; + at->addr[2] = htonl (0xffff); + at->addr[1] = 0; + at->addr[0] = 0; +@@ -505,49 +505,62 @@ + + if (req->ai_flags & AI_CANONNAME) + canon = name; ++ ++ goto process_list; + } +- else if (at->family == AF_UNSPEC) ++ ++ char *scope_delim = strchr (name, SCOPE_DELIMITER); ++ int e; ++ ++ if (scope_delim == NULL) ++ e = inet_pton (AF_INET6, name, addr); ++ else ++ e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr); ++ ++ if (e > 0) + { +- char *scope_delim = strchr (name, SCOPE_DELIMITER); +- int e; +- if (scope_delim == NULL) +- e = inet_pton (AF_INET6, name, at->addr); ++ at = alloca_account (sizeof (struct gaih_addrtuple), ++ alloca_used); ++ at->scopeid = 0; ++ at->next = NULL; ++ ++ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) ++ { ++ memcpy (at->addr, addr, sizeof (at->addr)); ++ at->family = AF_INET6; ++ } ++ else if (req->ai_family == AF_INET ++ && IN6_IS_ADDR_V4MAPPED (addr)) ++ { ++ at->addr[0] = addr[3]; ++ at->addr[1] = addr[1]; ++ at->addr[2] = addr[2]; ++ at->addr[3] = addr[3]; ++ at->family = AF_INET; ++ } + else +- e = __inet_pton_length (AF_INET6, name, scope_delim - name, +- at->addr); +- if (e > 0) + { +- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) +- at->family = AF_INET6; +- else if (req->ai_family == AF_INET +- && IN6_IS_ADDR_V4MAPPED (at->addr)) +- { +- at->addr[0] = at->addr[3]; +- at->family = AF_INET; +- } +- else +- { +- result = -EAI_ADDRFAMILY; +- goto free_and_return; +- } +- +- if (scope_delim != NULL +- && __inet6_scopeid_pton ((struct in6_addr *) at->addr, +- scope_delim + 1, +- &at->scopeid) != 0) +- { +- result = -EAI_NONAME; +- goto free_and_return; +- } ++ result = -EAI_ADDRFAMILY; ++ goto free_and_return; ++ } + +- if (req->ai_flags & AI_CANONNAME) +- canon = name; ++ if (scope_delim != NULL ++ && __inet6_scopeid_pton ((struct in6_addr *) at->addr, ++ scope_delim + 1, ++ &at->scopeid) != 0) ++ { ++ result = -EAI_NONAME; ++ goto free_and_return; + } ++ ++ if (req->ai_flags & AI_CANONNAME) ++ canon = name; ++ ++ goto process_list; + } + +- if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) ++ if ((req->ai_flags & AI_NUMERICHOST) == 0) + { +- struct gaih_addrtuple **pat = &at; + int no_data = 0; + int no_inet6_data = 0; + service_user *nip; +@@ -543,6 +559,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + struct resolv_context *res_ctx = NULL; ++ bool do_merge = false; + + /* If we do not have to look for IPv6 addresses or the canonical + name, use the simple, old functions, which do not support +@@ -579,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + result = -EAI_MEMORY; + goto free_and_return; + } +- *pat = addrmem; ++ at = addrmem; + } + else + { +@@ -632,6 +649,8 @@ gaih_inet (const char *name, const struct gaih_service *service, + } + + struct gaih_addrtuple *addrfree = addrmem; ++ struct gaih_addrtuple **pat = &at; ++ + for (int i = 0; i < air->naddrs; ++i) + { + socklen_t size = (air->family[i] == AF_INET +@@ -695,12 +714,6 @@ gaih_inet (const char *name, const struct gaih_service *service, + + free (air); + +- if (at->family == AF_UNSPEC) +- { +- result = -EAI_NONAME; +- goto free_and_return; +- } +- + goto process_list; + } + else if (err == 0) +@@ -750,6 +763,22 @@ + + while (!no_more) + { ++ /* Always start afresh; continue should discard previous results ++ and the hosts database does not support merge. */ ++ at = NULL; ++ free (canonbuf); ++ free (addrmem); ++ canon = canonbuf = NULL; ++ addrmem = NULL; ++ got_ipv6 = false; ++ ++ if (do_merge) ++ { ++ __set_h_errno (NETDB_INTERNAL); ++ __set_errno (EBUSY); ++ break; ++ } ++ + no_data = 0; + nss_gethostbyname4_r fct4 = NULL; + +@@ -744,12 +773,14 @@ gaih_inet (const char *name, const struct gaih_service *service, + { + while (1) + { +- status = DL_CALL_FCT (fct4, (name, pat, ++ status = DL_CALL_FCT (fct4, (name, &at, + tmpbuf->data, tmpbuf->length, + &errno, &h_errno, + NULL)); + if (status == NSS_STATUS_SUCCESS) + break; ++ /* gethostbyname4_r may write into AT, so reset it. */ ++ at = NULL; + if (status != NSS_STATUS_TRYAGAIN + || errno != ERANGE || h_errno != NETDB_INTERNAL) + { +@@ -774,7 +805,9 @@ gaih_inet (const char *name, const struct gaih_service *service, + no_data = 1; + + if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) +- canon = (*pat)->name; ++ canon = at->name; ++ ++ struct gaih_addrtuple **pat = &at; + + while (*pat != NULL) + { +@@ -826,6 +859,8 @@ gaih_inet (const char *name, const struct gaih_service *service, + + if (fct != NULL) + { ++ struct gaih_addrtuple **pat = &at; ++ + if (req->ai_family == AF_INET6 + || req->ai_family == AF_UNSPEC) + { +@@ -917,6 +946,10 @@ + if (nss_next_action (nip, status) == NSS_ACTION_RETURN) + break; + ++ /* The hosts database does not support MERGE. */ ++ if (nss_next_action (nip, status) == NSS_ACTION_MERGE) ++ do_merge = true; ++ + if (nip->next == NULL) + no_more = -1; + else +@@ -930,7 +969,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + } + + process_list: +- if (at->family == AF_UNSPEC) ++ if (at == NULL) + { + result = -EAI_NONAME; + goto free_and_return; +-- +2.39.3 diff --git a/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch b/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch new file mode 100644 index 0000000000..4d3146509a --- /dev/null +++ b/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch @@ -0,0 +1,63 @@ +From d2b77337f734fcacdfc8e0ddec14cf31a746c7be Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@redhat.com> +Date: Mon, 11 Sep 2023 18:53:15 -0400 +Subject: [PATCH v2] tunables: Terminate immediately if end of input is reached + +The string parsing routine may end up writing beyond bounds of tunestr +if the input tunable string is malformed, of the form name=name=val. +This gets processed twice, first as name=name=val and next as name=val, +resulting in tunestr being name=name=val:name=val, thus overflowing +tunestr. + +Terminate the parsing loop at the first instance itself so that tunestr +does not overflow. +--- +Changes from v1: + +- Also null-terminate tunestr before exiting. + + elf/dl-tunables.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +Upstream-Status: Backport [git://sourceware.org/git/glibc.git] +CVE: CVE-2023-4911 + +diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c +index 8e7ee9df10..76cf8b9da3 100644 +--- a/elf/dl-tunables.c ++++ b/elf/dl-tunables.c +@@ -187,11 +187,7 @@ parse_tunables (char *tunestr, char *valstring) + /* If we reach the end of the string before getting a valid name-value + pair, bail out. */ + if (p[len] == '\0') +- { +- if (__libc_enable_secure) +- tunestr[off] = '\0'; +- return; +- } ++ break; + + /* We did not find a valid name-value pair before encountering the + colon. */ +@@ -251,9 +247,16 @@ parse_tunables (char *tunestr, char *valstring) + } + } + +- if (p[len] != '\0') +- p += len + 1; ++ /* We reached the end while processing the tunable string. */ ++ if (p[len] == '\0') ++ break; ++ ++ p += len + 1; + } ++ ++ /* Terminate tunestr before we leave. */ ++ if (__libc_enable_secure) ++ tunestr[off] = '\0'; + } + #endif + +-- +2.41.0 + diff --git a/meta/recipes-core/glibc/glibc/check-test-wrapper b/meta/recipes-core/glibc/glibc/check-test-wrapper index f8e04e02d2..5cc993f718 100644 --- a/meta/recipes-core/glibc/glibc/check-test-wrapper +++ b/meta/recipes-core/glibc/glibc/check-test-wrapper @@ -2,6 +2,7 @@ import sys import os import subprocess +import resource env = os.environ.copy() args = sys.argv[1:] @@ -44,12 +45,20 @@ if targettype == "user": qemuargs += ["-L", sysroot] qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))] command = qemuargs + args + + # We've seen qemu-arm using up all system memory for some glibc + # tests e.g. nptl/tst-pthread-timedlock-lockloop + # Cap at 8GB since no test should need more than that + # (5GB adds 7 failures for qemuarm glibc test run) + limit = 8*1024*1024*1024 + resource.setrlimit(resource.RLIMIT_AS, (limit, limit)) + elif targettype == "ssh": host = os.environ.get("SSH_HOST", None) user = os.environ.get("SSH_HOST_USER", None) port = os.environ.get("SSH_HOST_PORT", None) - command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"] + command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=quiet"] if port: command += ["-p", str(port)] if not host: |