diff options
9 files changed, 1251 insertions, 0 deletions
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 @@ | |||
1 | From c0669ae1a629e16b536bf11cdd0865e0dbcf4bee Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Wed, 30 Dec 2020 21:52:38 +0000 | ||
4 | Subject: [PATCH] elf: Refactor _dl_update_slotinfo to avoid use after free | ||
5 | |||
6 | map is not valid to access here because it can be freed by a concurrent | ||
7 | dlclose: during tls access (via __tls_get_addr) _dl_update_slotinfo is | ||
8 | called without holding dlopen locks. So don't check the modid of map. | ||
9 | |||
10 | The map == 0 and map != 0 code paths can be shared (avoiding the dtv | ||
11 | resize in case of map == 0 is just an optimization: larger dtv than | ||
12 | necessary would be fine too). | ||
13 | |||
14 | Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
15 | --- | ||
16 | elf/dl-tls.c | 21 +++++---------------- | ||
17 | 1 file changed, 5 insertions(+), 16 deletions(-) | ||
18 | --- | ||
19 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=c0669ae1a629e16b536bf11cdd0865e0dbcf4bee] | ||
20 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
21 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
22 | --- | ||
23 | diff --git a/elf/dl-tls.c b/elf/dl-tls.c | ||
24 | index 24d00c14ef..f8b32b3ecb 100644 | ||
25 | --- a/elf/dl-tls.c | ||
26 | +++ b/elf/dl-tls.c | ||
27 | @@ -743,6 +743,8 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
28 | { | ||
29 | for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) | ||
30 | { | ||
31 | + size_t modid = total + cnt; | ||
32 | + | ||
33 | size_t gen = listp->slotinfo[cnt].gen; | ||
34 | |||
35 | if (gen > new_gen) | ||
36 | @@ -758,25 +760,12 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
37 | |||
38 | /* If there is no map this means the entry is empty. */ | ||
39 | struct link_map *map = listp->slotinfo[cnt].map; | ||
40 | - if (map == NULL) | ||
41 | - { | ||
42 | - if (dtv[-1].counter >= total + cnt) | ||
43 | - { | ||
44 | - /* If this modid was used at some point the memory | ||
45 | - might still be allocated. */ | ||
46 | - free (dtv[total + cnt].pointer.to_free); | ||
47 | - dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; | ||
48 | - dtv[total + cnt].pointer.to_free = NULL; | ||
49 | - } | ||
50 | - | ||
51 | - continue; | ||
52 | - } | ||
53 | - | ||
54 | /* Check whether the current dtv array is large enough. */ | ||
55 | - size_t modid = map->l_tls_modid; | ||
56 | - assert (total + cnt == modid); | ||
57 | if (dtv[-1].counter < modid) | ||
58 | { | ||
59 | + if (map == NULL) | ||
60 | + continue; | ||
61 | + | ||
62 | /* Resize the dtv. */ | ||
63 | dtv = _dl_resize_dtv (dtv); | ||
64 | |||
65 | -- | ||
66 | 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 @@ | |||
1 | From 1387ad6225c2222f027790e3f460e31aa5dd2c54 Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Wed, 30 Dec 2020 19:19:37 +0000 | ||
4 | Subject: [PATCH] elf: Fix data races in pthread_create and TLS access [BZ | ||
5 | #19329] | ||
6 | |||
7 | DTV setup at thread creation (_dl_allocate_tls_init) is changed | ||
8 | to take the dlopen lock, GL(dl_load_lock). Avoiding data races | ||
9 | here without locks would require design changes: the map that is | ||
10 | accessed for static TLS initialization here may be concurrently | ||
11 | freed by dlclose. That use after free may be solved by only | ||
12 | locking around static TLS setup or by ensuring dlclose does not | ||
13 | free modules with static TLS, however currently every link map | ||
14 | with TLS has to be accessed at least to see if it needs static | ||
15 | TLS. And even if that's solved, still a lot of atomics would be | ||
16 | needed to synchronize DTV related globals without a lock. So fix | ||
17 | both bug 19329 and bug 27111 with a lock that prevents DTV setup | ||
18 | running concurrently with dlopen or dlclose. | ||
19 | |||
20 | _dl_update_slotinfo at TLS access still does not use any locks | ||
21 | so CONCURRENCY NOTES are added to explain the synchronization. | ||
22 | The early exit from the slotinfo walk when max_modid is reached | ||
23 | is not strictly necessary, but does not hurt either. | ||
24 | |||
25 | An incorrect acquire load was removed from _dl_resize_dtv: it | ||
26 | did not synchronize with any release store or fence and | ||
27 | synchronization is now handled separately at thread creation | ||
28 | and TLS access time. | ||
29 | |||
30 | There are still a number of racy read accesses to globals that | ||
31 | will be changed to relaxed MO atomics in a followup patch. This | ||
32 | should not introduce regressions compared to existing behaviour | ||
33 | and avoid cluttering the main part of the fix. | ||
34 | |||
35 | Not all TLS access related data races got fixed here: there are | ||
36 | additional races at lazy tlsdesc relocations see bug 27137. | ||
37 | |||
38 | Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
39 | --- | ||
40 | elf/dl-tls.c | 63 +++++++++++++++++++++++++++++++++++++++------------- | ||
41 | 1 file changed, 47 insertions(+), 16 deletions(-) | ||
42 | --- | ||
43 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=1387ad6225c2222f027790e3f460e31aa5dd2c54] | ||
44 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
45 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
46 | --- | ||
47 | diff --git a/elf/dl-tls.c b/elf/dl-tls.c | ||
48 | index 6baff0c1ea..94f3cdbae0 100644 | ||
49 | --- a/elf/dl-tls.c | ||
50 | +++ b/elf/dl-tls.c | ||
51 | @@ -475,14 +475,11 @@ extern dtv_t _dl_static_dtv[]; | ||
52 | #endif | ||
53 | |||
54 | static dtv_t * | ||
55 | -_dl_resize_dtv (dtv_t *dtv) | ||
56 | +_dl_resize_dtv (dtv_t *dtv, size_t max_modid) | ||
57 | { | ||
58 | /* Resize the dtv. */ | ||
59 | dtv_t *newp; | ||
60 | - /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by | ||
61 | - other threads concurrently. */ | ||
62 | - size_t newsize | ||
63 | - = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS; | ||
64 | + size_t newsize = max_modid + DTV_SURPLUS; | ||
65 | size_t oldsize = dtv[-1].counter; | ||
66 | |||
67 | if (dtv == GL(dl_initial_dtv)) | ||
68 | @@ -528,11 +525,14 @@ _dl_allocate_tls_init (void *result) | ||
69 | size_t total = 0; | ||
70 | size_t maxgen = 0; | ||
71 | |||
72 | + /* Protects global dynamic TLS related state. */ | ||
73 | + __rtld_lock_lock_recursive (GL(dl_load_lock)); | ||
74 | + | ||
75 | /* Check if the current dtv is big enough. */ | ||
76 | if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) | ||
77 | { | ||
78 | /* Resize the dtv. */ | ||
79 | - dtv = _dl_resize_dtv (dtv); | ||
80 | + dtv = _dl_resize_dtv (dtv, GL(dl_tls_max_dtv_idx)); | ||
81 | |||
82 | /* Install this new dtv in the thread data structures. */ | ||
83 | INSTALL_DTV (result, &dtv[-1]); | ||
84 | @@ -600,6 +600,7 @@ _dl_allocate_tls_init (void *result) | ||
85 | listp = listp->next; | ||
86 | assert (listp != NULL); | ||
87 | } | ||
88 | + __rtld_lock_unlock_recursive (GL(dl_load_lock)); | ||
89 | |||
90 | /* The DTV version is up-to-date now. */ | ||
91 | dtv[0].counter = maxgen; | ||
92 | @@ -734,12 +735,29 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
93 | |||
94 | if (dtv[0].counter < listp->slotinfo[idx].gen) | ||
95 | { | ||
96 | - /* The generation counter for the slot is higher than what the | ||
97 | - current dtv implements. We have to update the whole dtv but | ||
98 | - only those entries with a generation counter <= the one for | ||
99 | - the entry we need. */ | ||
100 | + /* CONCURRENCY NOTES: | ||
101 | + | ||
102 | + Here the dtv needs to be updated to new_gen generation count. | ||
103 | + | ||
104 | + This code may be called during TLS access when GL(dl_load_lock) | ||
105 | + is not held. In that case the user code has to synchronize with | ||
106 | + dlopen and dlclose calls of relevant modules. A module m is | ||
107 | + relevant if the generation of m <= new_gen and dlclose of m is | ||
108 | + synchronized: a memory access here happens after the dlopen and | ||
109 | + before the dlclose of relevant modules. The dtv entries for | ||
110 | + relevant modules need to be updated, other entries can be | ||
111 | + arbitrary. | ||
112 | + | ||
113 | + This e.g. means that the first part of the slotinfo list can be | ||
114 | + accessed race free, but the tail may be concurrently extended. | ||
115 | + Similarly relevant slotinfo entries can be read race free, but | ||
116 | + other entries are racy. However updating a non-relevant dtv | ||
117 | + entry does not affect correctness. For a relevant module m, | ||
118 | + max_modid >= modid of m. */ | ||
119 | size_t new_gen = listp->slotinfo[idx].gen; | ||
120 | size_t total = 0; | ||
121 | + size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx)); | ||
122 | + assert (max_modid >= req_modid); | ||
123 | |||
124 | /* We have to look through the entire dtv slotinfo list. */ | ||
125 | listp = GL(dl_tls_dtv_slotinfo_list); | ||
126 | @@ -749,12 +767,14 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
127 | { | ||
128 | size_t modid = total + cnt; | ||
129 | |||
130 | + /* Later entries are not relevant. */ | ||
131 | + if (modid > max_modid) | ||
132 | + break; | ||
133 | + | ||
134 | size_t gen = listp->slotinfo[cnt].gen; | ||
135 | |||
136 | if (gen > new_gen) | ||
137 | - /* This is a slot for a generation younger than the | ||
138 | - one we are handling now. It might be incompletely | ||
139 | - set up so ignore it. */ | ||
140 | + /* Not relevant. */ | ||
141 | continue; | ||
142 | |||
143 | /* If the entry is older than the current dtv layout we | ||
144 | @@ -771,7 +791,7 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
145 | continue; | ||
146 | |||
147 | /* Resize the dtv. */ | ||
148 | - dtv = _dl_resize_dtv (dtv); | ||
149 | + dtv = _dl_resize_dtv (dtv, max_modid); | ||
150 | |||
151 | assert (modid <= dtv[-1].counter); | ||
152 | |||
153 | @@ -793,8 +813,17 @@ _dl_update_slotinfo (unsigned long int req_modid) | ||
154 | } | ||
155 | |||
156 | total += listp->len; | ||
157 | + if (total > max_modid) | ||
158 | + break; | ||
159 | + | ||
160 | + /* Synchronize with _dl_add_to_slotinfo. Ideally this would | ||
161 | + be consume MO since we only need to order the accesses to | ||
162 | + the next node after the read of the address and on most | ||
163 | + hardware (other than alpha) a normal load would do that | ||
164 | + because of the address dependency. */ | ||
165 | + listp = atomic_load_acquire (&listp->next); | ||
166 | } | ||
167 | - while ((listp = listp->next) != NULL); | ||
168 | + while (listp != NULL); | ||
169 | |||
170 | /* This will be the new maximum generation counter. */ | ||
171 | dtv[0].counter = new_gen; | ||
172 | @@ -986,7 +1015,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add) | ||
173 | the first slot. */ | ||
174 | assert (idx == 0); | ||
175 | |||
176 | - listp = prevp->next = (struct dtv_slotinfo_list *) | ||
177 | + listp = (struct dtv_slotinfo_list *) | ||
178 | malloc (sizeof (struct dtv_slotinfo_list) | ||
179 | + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); | ||
180 | if (listp == NULL) | ||
181 | @@ -1000,6 +1029,8 @@ cannot create TLS data structures")); | ||
182 | listp->next = NULL; | ||
183 | memset (listp->slotinfo, '\0', | ||
184 | TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); | ||
185 | + /* Synchronize with _dl_update_slotinfo. */ | ||
186 | + atomic_store_release (&prevp->next, listp); | ||
187 | } | ||
188 | |||
189 | /* Add the information into the slotinfo data structure. */ | ||
190 | -- | ||
191 | 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 @@ | |||
1 | From f4f8f4d4e0f92488431b268c8cd9555730b9afe9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Wed, 30 Dec 2020 19:19:37 +0000 | ||
4 | Subject: [PATCH] elf: Use relaxed atomics for racy accesses [BZ #19329] | ||
5 | |||
6 | This is a follow up patch to the fix for bug 19329. This adds relaxed | ||
7 | MO atomics to accesses that were previously data races but are now | ||
8 | race conditions, and where relaxed MO is sufficient. | ||
9 | |||
10 | The race conditions all follow the pattern that the write is behind the | ||
11 | dlopen lock, but a read can happen concurrently (e.g. during tls access) | ||
12 | without holding the lock. For slotinfo entries the read value only | ||
13 | matters if it reads from a synchronized write in dlopen or dlclose, | ||
14 | otherwise the related dtv entry is not valid to access so it is fine | ||
15 | to leave it in an inconsistent state. The same applies for | ||
16 | GL(dl_tls_max_dtv_idx) and GL(dl_tls_generation), but there the | ||
17 | algorithm relies on the fact that the read of the last synchronized | ||
18 | write is an increasing value. | ||
19 | |||
20 | Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
21 | --- | ||
22 | elf/dl-close.c | 20 +++++++++++++------- | ||
23 | elf/dl-open.c | 5 ++++- | ||
24 | elf/dl-tls.c | 31 +++++++++++++++++++++++-------- | ||
25 | sysdeps/x86_64/dl-tls.c | 3 ++- | ||
26 | 4 files changed, 42 insertions(+), 17 deletions(-) | ||
27 | --- | ||
28 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=f4f8f4d4e0f92488431b268c8cd9555730b9afe9] | ||
29 | Comment: Hunks from elf/dl-open.c and elf/dl-tls.c are refreshed due to offset change. | ||
30 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
31 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
32 | --- | ||
33 | diff --git a/elf/dl-close.c b/elf/dl-close.c | ||
34 | index c51becd06b..3720e47dd1 100644 | ||
35 | --- a/elf/dl-close.c | ||
36 | +++ b/elf/dl-close.c | ||
37 | @@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, | ||
38 | { | ||
39 | assert (old_map->l_tls_modid == idx); | ||
40 | |||
41 | - /* Mark the entry as unused. */ | ||
42 | - listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1; | ||
43 | - listp->slotinfo[idx - disp].map = NULL; | ||
44 | + /* Mark the entry as unused. These can be read concurrently. */ | ||
45 | + atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, | ||
46 | + GL(dl_tls_generation) + 1); | ||
47 | + atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL); | ||
48 | } | ||
49 | |||
50 | /* If this is not the last currently used entry no need to look | ||
51 | @@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, | ||
52 | |||
53 | if (listp->slotinfo[idx - disp].map != NULL) | ||
54 | { | ||
55 | - /* Found a new last used index. */ | ||
56 | - GL(dl_tls_max_dtv_idx) = idx; | ||
57 | + /* Found a new last used index. This can be read concurrently. */ | ||
58 | + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx); | ||
59 | return true; | ||
60 | } | ||
61 | } | ||
62 | @@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force) | ||
63 | GL(dl_tls_dtv_slotinfo_list), 0, | ||
64 | imap->l_init_called)) | ||
65 | /* All dynamically loaded modules with TLS are unloaded. */ | ||
66 | - GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem); | ||
67 | + /* Can be read concurrently. */ | ||
68 | + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), | ||
69 | + GL(dl_tls_static_nelem)); | ||
70 | |||
71 | if (imap->l_tls_offset != NO_TLS_OFFSET | ||
72 | && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET) | ||
73 | @@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force) | ||
74 | /* If we removed any object which uses TLS bump the generation counter. */ | ||
75 | if (any_tls) | ||
76 | { | ||
77 | - if (__glibc_unlikely (++GL(dl_tls_generation) == 0)) | ||
78 | + size_t newgen = GL(dl_tls_generation) + 1; | ||
79 | + if (__glibc_unlikely (newgen == 0)) | ||
80 | _dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n"); | ||
81 | + /* Can be read concurrently. */ | ||
82 | + atomic_store_relaxed (&GL(dl_tls_generation), newgen); | ||
83 | |||
84 | if (tls_free_end == GL(dl_tls_static_used)) | ||
85 | GL(dl_tls_static_used) = tls_free_start; | ||
86 | diff --git a/elf/dl-open.c b/elf/dl-open.c | ||
87 | index 09f0df7d38..bb79ef00f1 100644 | ||
88 | --- a/elf/dl-open.c | ||
89 | +++ b/elf/dl-open.c | ||
90 | @@ -387,9 +387,12 @@ | ||
91 | } | ||
92 | } | ||
93 | |||
94 | - if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) | ||
95 | + size_t newgen = GL(dl_tls_generation) + 1; | ||
96 | + if (__glibc_unlikely (newgen == 0)) | ||
97 | _dl_fatal_printf (N_("\ | ||
98 | TLS generation counter wrapped! Please report this.")); | ||
99 | + /* Can be read concurrently. */ | ||
100 | + atomic_store_relaxed (&GL(dl_tls_generation), newgen); | ||
101 | |||
102 | /* We need a second pass for static tls data, because | ||
103 | _dl_update_slotinfo must not be run while calls to | ||
104 | diff --git a/elf/dl-tls.c b/elf/dl-tls.c | ||
105 | index 94f3cdbae0..dc69cd984e 100644 | ||
106 | --- a/elf/dl-tls.c | ||
107 | +++ b/elf/dl-tls.c | ||
108 | @@ -96,7 +96,9 @@ | ||
109 | /* No gaps, allocate a new entry. */ | ||
110 | nogaps: | ||
111 | |||
112 | - result = ++GL(dl_tls_max_dtv_idx); | ||
113 | + result = GL(dl_tls_max_dtv_idx) + 1; | ||
114 | + /* Can be read concurrently. */ | ||
115 | + atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); | ||
116 | } | ||
117 | |||
118 | return result; | ||
119 | @@ -279,10 +281,12 @@ | ||
120 | dtv_t *dtv; | ||
121 | size_t dtv_length; | ||
122 | |||
123 | + /* Relaxed MO, because the dtv size is later rechecked, not relied on. */ | ||
124 | + size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx)); | ||
125 | /* We allocate a few more elements in the dtv than are needed for the | ||
126 | initial set of modules. This should avoid in most cases expansions | ||
127 | of the dtv. */ | ||
128 | - dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; | ||
129 | + dtv_length = max_modid + DTV_SURPLUS; | ||
130 | dtv = calloc (dtv_length + 2, sizeof (dtv_t)); | ||
131 | if (dtv != NULL) | ||
132 | { | ||
133 | @@ -687,7 +691,7 @@ | ||
134 | if (modid > max_modid) | ||
135 | break; | ||
136 | |||
137 | - size_t gen = listp->slotinfo[cnt].gen; | ||
138 | + size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen); | ||
139 | |||
140 | if (gen > new_gen) | ||
141 | /* Not relevant. */ | ||
142 | @@ -699,7 +703,8 @@ | ||
143 | continue; | ||
144 | |||
145 | /* If there is no map this means the entry is empty. */ | ||
146 | - struct link_map *map = listp->slotinfo[cnt].map; | ||
147 | + struct link_map *map | ||
148 | + = atomic_load_relaxed (&listp->slotinfo[cnt].map); | ||
149 | /* Check whether the current dtv array is large enough. */ | ||
150 | if (dtv[-1].counter < modid) | ||
151 | { | ||
152 | @@ -843,7 +848,12 @@ | ||
153 | { | ||
154 | dtv_t *dtv = THREAD_DTV (); | ||
155 | |||
156 | - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) | ||
157 | + /* Update is needed if dtv[0].counter < the generation of the accessed | ||
158 | + module. The global generation counter is used here as it is easier | ||
159 | + to check. Synchronization for the relaxed MO access is guaranteed | ||
160 | + by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */ | ||
161 | + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); | ||
162 | + if (__glibc_unlikely (dtv[0].counter != gen)) | ||
163 | return update_get_addr (GET_ADDR_PARAM); | ||
164 | |||
165 | void *p = dtv[GET_ADDR_MODULE].pointer.val; | ||
166 | @@ -866,7 +876,10 @@ | ||
167 | return NULL; | ||
168 | |||
169 | dtv_t *dtv = THREAD_DTV (); | ||
170 | - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) | ||
171 | + /* This may be called without holding the GL(dl_load_lock). Reading | ||
172 | + arbitrary gen value is fine since this is best effort code. */ | ||
173 | + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); | ||
174 | + if (__glibc_unlikely (dtv[0].counter != gen)) | ||
175 | { | ||
176 | /* This thread's DTV is not completely current, | ||
177 | but it might already cover this module. */ | ||
178 | @@ -961,7 +974,9 @@ | ||
179 | /* Add the information into the slotinfo data structure. */ | ||
180 | if (do_add) | ||
181 | { | ||
182 | - listp->slotinfo[idx].map = l; | ||
183 | - listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; | ||
184 | + /* Can be read concurrently. See _dl_update_slotinfo. */ | ||
185 | + atomic_store_relaxed (&listp->slotinfo[idx].map, l); | ||
186 | + atomic_store_relaxed (&listp->slotinfo[idx].gen, | ||
187 | + GL(dl_tls_generation) + 1); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c | ||
192 | index 6595f6615b..24ef560b71 100644 | ||
193 | --- a/sysdeps/x86_64/dl-tls.c | ||
194 | +++ b/sysdeps/x86_64/dl-tls.c | ||
195 | @@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS) | ||
196 | { | ||
197 | dtv_t *dtv = THREAD_DTV (); | ||
198 | |||
199 | - if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) | ||
200 | + size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); | ||
201 | + if (__glibc_unlikely (dtv[0].counter != gen)) | ||
202 | return update_get_addr (GET_ADDR_PARAM); | ||
203 | |||
204 | return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); | ||
205 | -- | ||
206 | 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 @@ | |||
1 | From 9d0e30329c23b5ad736fda3f174208c25970dbce Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Tue, 13 Dec 2016 12:28:41 +0000 | ||
4 | Subject: [PATCH] elf: Add test case for [BZ #19329] | ||
5 | |||
6 | Test concurrent dlopen and pthread_create when the loaded modules have | ||
7 | TLS. This triggers dl-tls assertion failures more reliably than the | ||
8 | nptl/tst-stack4 test. | ||
9 | |||
10 | The dlopened module has 100 DT_NEEDED dependencies with TLS, they were | ||
11 | reused from an existing TLS test. The number of created threads during | ||
12 | dlopen depends on filesystem speed and hardware, but at most 3 threads | ||
13 | are alive at a time to limit resource usage. | ||
14 | |||
15 | Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
16 | --- | ||
17 | elf/Makefile | 9 ++++-- | ||
18 | elf/tst-tls21.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
19 | elf/tst-tls21mod.c | 1 + | ||
20 | 3 files changed, 76 insertions(+), 2 deletions(-) | ||
21 | create mode 100644 elf/tst-tls21.c | ||
22 | create mode 100644 elf/tst-tls21mod.c | ||
23 | --- | ||
24 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=9d0e30329c23b5ad736fda3f174208c25970dbce] | ||
25 | Comment: Hunks from elf/Makefile are refreshed as per glibc 2.31 codebase. | ||
26 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
27 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
28 | --- | ||
29 | diff --git a/elf/Makefile b/elf/Makefile | ||
30 | index d3e909637a..3241cb6046 100644 | ||
31 | --- a/elf/Makefile | ||
32 | +++ b/elf/Makefile | ||
33 | @@ -201,7 +201,7 @@ | ||
34 | tst-unwind-ctor tst-unwind-main tst-audit13 \ | ||
35 | tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \ | ||
36 | tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ | ||
37 | - tst-dlopenfail-2 | ||
38 | + tst-dlopenfail-2 tst-tls21 | ||
39 | # reldep9 | ||
40 | tests-internal += loadtest unload unload2 circleload1 \ | ||
41 | neededtest neededtest2 neededtest3 neededtest4 \ | ||
42 | @@ -312,7 +312,7 @@ | ||
43 | tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ | ||
44 | tst-initlazyfailmod tst-finilazyfailmod \ | ||
45 | tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ | ||
46 | - tst-dlopenfailmod3 tst-ldconfig-ld-mod | ||
47 | + tst-dlopenfailmod3 tst-ldconfig-ld-mod tst-tls21mod | ||
48 | # Most modules build with _ISOMAC defined, but those filtered out | ||
49 | # depend on internal headers. | ||
50 | modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\ | ||
51 | @@ -1697,5 +1697,10 @@ | ||
52 | $(objpfx)tst-dlopen-nodelete-reloc-mod16.so | ||
53 | LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed | ||
54 | |||
55 | +# Reuses tst-tls-many-dynamic-modules | ||
56 | +$(objpfx)tst-tls21: $(libdl) $(shared-thread-library) | ||
57 | +$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so | ||
58 | +$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) | ||
59 | + | ||
60 | $(objpfx)tst-ldconfig-ld_so_conf-update.out: $(objpfx)tst-ldconfig-ld-mod.so | ||
61 | $(objpfx)tst-ldconfig-ld_so_conf-update: $(libdl) | ||
62 | diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c | ||
63 | new file mode 100644 | ||
64 | index 0000000000..560bf5813a | ||
65 | --- /dev/null | ||
66 | +++ b/elf/tst-tls21.c | ||
67 | @@ -0,0 +1,68 @@ | ||
68 | +/* Test concurrent dlopen and pthread_create: BZ 19329. | ||
69 | + Copyright (C) 2021 Free Software Foundation, Inc. | ||
70 | + This file is part of the GNU C Library. | ||
71 | + | ||
72 | + The GNU C Library is free software; you can redistribute it and/or | ||
73 | + modify it under the terms of the GNU Lesser General Public | ||
74 | + License as published by the Free Software Foundation; either | ||
75 | + version 2.1 of the License, or (at your option) any later version. | ||
76 | + | ||
77 | + The GNU C Library is distributed in the hope that it will be useful, | ||
78 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
79 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
80 | + Lesser General Public License for more details. | ||
81 | + | ||
82 | + You should have received a copy of the GNU Lesser General Public | ||
83 | + License along with the GNU C Library; if not, see | ||
84 | + <http://www.gnu.org/licenses/>. */ | ||
85 | + | ||
86 | +#include <dlfcn.h> | ||
87 | +#include <pthread.h> | ||
88 | +#include <stdio.h> | ||
89 | +#include <stdatomic.h> | ||
90 | +#include <support/xdlfcn.h> | ||
91 | +#include <support/xthread.h> | ||
92 | + | ||
93 | +#define THREADS 10000 | ||
94 | + | ||
95 | +static atomic_int done; | ||
96 | + | ||
97 | +static void * | ||
98 | +start (void *a) | ||
99 | +{ | ||
100 | + /* Load a module with many dependencies that each have TLS. */ | ||
101 | + xdlopen ("tst-tls21mod.so", RTLD_LAZY); | ||
102 | + atomic_store_explicit (&done, 1, memory_order_release); | ||
103 | + return 0; | ||
104 | +} | ||
105 | + | ||
106 | +static void * | ||
107 | +nop (void *a) | ||
108 | +{ | ||
109 | + return 0; | ||
110 | +} | ||
111 | + | ||
112 | +static int | ||
113 | +do_test (void) | ||
114 | +{ | ||
115 | + pthread_t t1, t2; | ||
116 | + int i; | ||
117 | + | ||
118 | + /* Load a module with lots of dependencies and TLS. */ | ||
119 | + t1 = xpthread_create (0, start, 0); | ||
120 | + | ||
121 | + /* Concurrently create lots of threads until dlopen is observably done. */ | ||
122 | + for (i = 0; i < THREADS; i++) | ||
123 | + { | ||
124 | + if (atomic_load_explicit (&done, memory_order_acquire) != 0) | ||
125 | + break; | ||
126 | + t2 = xpthread_create (0, nop, 0); | ||
127 | + xpthread_join (t2); | ||
128 | + } | ||
129 | + | ||
130 | + xpthread_join (t1); | ||
131 | + printf ("threads created during dlopen: %d\n", i); | ||
132 | + return 0; | ||
133 | +} | ||
134 | + | ||
135 | +#include <support/test-driver.c> | ||
136 | diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c | ||
137 | new file mode 100644 | ||
138 | index 0000000000..206ece4fb3 | ||
139 | --- /dev/null | ||
140 | +++ b/elf/tst-tls21mod.c | ||
141 | @@ -0,0 +1 @@ | ||
142 | +int __thread x; | ||
143 | -- | ||
144 | 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 @@ | |||
1 | From ba33937be210da5d07f7f01709323743f66011ce Mon Sep 17 00:00:00 2001 | ||
2 | From: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
3 | Date: Fri, 25 Jun 2021 10:54:12 -0300 | ||
4 | Subject: [PATCH] elf: Fix DTV gap reuse logic (BZ #27135) | ||
5 | |||
6 | This is updated version of the 572bd547d57a (reverted by 40ebfd016ad2) | ||
7 | that fixes the _dl_next_tls_modid issues. | ||
8 | |||
9 | This issue with 572bd547d57a patch is the DTV entry will be only | ||
10 | update on dl_open_worker() with the update_tls_slotinfo() call after | ||
11 | all dependencies are being processed by _dl_map_object_deps(). However | ||
12 | _dl_map_object_deps() itself might call _dl_next_tls_modid(), and since | ||
13 | the _dl_tls_dtv_slotinfo_list::map is not yet set the entry will be | ||
14 | wrongly reused. | ||
15 | |||
16 | This patch fixes by renaming the _dl_next_tls_modid() function to | ||
17 | _dl_assign_tls_modid() and by passing the link_map so it can set | ||
18 | the slotinfo value so a subsequente _dl_next_tls_modid() call will | ||
19 | see the entry as allocated. | ||
20 | |||
21 | The intermediary value is cleared up on remove_slotinfo() for the case | ||
22 | a library fails to load with RTLD_NOW. | ||
23 | |||
24 | This patch fixes BZ #27135. | ||
25 | |||
26 | Checked on x86_64-linux-gnu. | ||
27 | |||
28 | Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
29 | --- | ||
30 | elf/dl-close.c | 8 +- | ||
31 | elf/dl-load.c | 2 +- | ||
32 | elf/dl-open.c | 10 -- | ||
33 | elf/dl-tls.c | 17 +-- | ||
34 | elf/rtld.c | 2 +- | ||
35 | sysdeps/generic/ldsodefs.h | 4 +- | ||
36 | 6 files changed, 349 insertions(+), 33 deletions(-) | ||
37 | --- | ||
38 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ba33937be210da5d07f7f01709323743f66011ce] | ||
39 | Comment: Removed hunks those were related to test. Hunk from elf/rtld.c is refreshed. | ||
40 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
41 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
42 | --- | ||
43 | diff --git a/elf/dl-close.c b/elf/dl-close.c | ||
44 | index 3720e47dd1..f39001cab9 100644 | ||
45 | --- a/elf/dl-close.c | ||
46 | +++ b/elf/dl-close.c | ||
47 | @@ -77,8 +77,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, | ||
48 | object that wasn't fully set up. */ | ||
49 | if (__glibc_likely (old_map != NULL)) | ||
50 | { | ||
51 | - assert (old_map->l_tls_modid == idx); | ||
52 | - | ||
53 | /* Mark the entry as unused. These can be read concurrently. */ | ||
54 | atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, | ||
55 | GL(dl_tls_generation) + 1); | ||
56 | @@ -88,7 +86,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, | ||
57 | /* If this is not the last currently used entry no need to look | ||
58 | further. */ | ||
59 | if (idx != GL(dl_tls_max_dtv_idx)) | ||
60 | - return true; | ||
61 | + { | ||
62 | + /* There is an unused dtv entry in the middle. */ | ||
63 | + GL(dl_tls_dtv_gaps) = true; | ||
64 | + return true; | ||
65 | + } | ||
66 | } | ||
67 | |||
68 | while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) | ||
69 | diff --git a/elf/dl-load.c b/elf/dl-load.c | ||
70 | index a08df001af..650e4edc35 100644 | ||
71 | --- a/elf/dl-load.c | ||
72 | +++ b/elf/dl-load.c | ||
73 | @@ -1498,7 +1498,7 @@ cannot enable executable stack as shared object requires"); | ||
74 | not set up TLS data structures, so don't use them now. */ | ||
75 | || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))) | ||
76 | /* Assign the next available module ID. */ | ||
77 | - l->l_tls_modid = _dl_next_tls_modid (); | ||
78 | + _dl_assign_tls_modid (l); | ||
79 | |||
80 | #ifdef DL_AFTER_LOAD | ||
81 | DL_AFTER_LOAD (l); | ||
82 | diff --git a/elf/dl-open.c b/elf/dl-open.c | ||
83 | index a066f39bd0..d2240d8747 100644 | ||
84 | --- a/elf/dl-open.c | ||
85 | +++ b/elf/dl-open.c | ||
86 | @@ -899,16 +899,6 @@ no more namespaces available for dlmopen()")); | ||
87 | state if relocation failed, for example. */ | ||
88 | if (args.map) | ||
89 | { | ||
90 | - /* Maybe some of the modules which were loaded use TLS. | ||
91 | - Since it will be removed in the following _dl_close call | ||
92 | - we have to mark the dtv array as having gaps to fill the | ||
93 | - holes. This is a pessimistic assumption which won't hurt | ||
94 | - if not true. There is no need to do this when we are | ||
95 | - loading the auditing DSOs since TLS has not yet been set | ||
96 | - up. */ | ||
97 | - if ((mode & __RTLD_AUDIT) == 0) | ||
98 | - GL(dl_tls_dtv_gaps) = true; | ||
99 | - | ||
100 | _dl_close_worker (args.map, true); | ||
101 | |||
102 | /* All l_nodelete_pending objects should have been deleted | ||
103 | diff --git a/elf/dl-tls.c b/elf/dl-tls.c | ||
104 | index 2b5161d10a..423e380f7c 100644 | ||
105 | --- a/elf/dl-tls.c | ||
106 | +++ b/elf/dl-tls.c | ||
107 | @@ -126,8 +126,8 @@ oom (void) | ||
108 | } | ||
109 | |||
110 | |||
111 | -size_t | ||
112 | -_dl_next_tls_modid (void) | ||
113 | +void | ||
114 | +_dl_assign_tls_modid (struct link_map *l) | ||
115 | { | ||
116 | size_t result; | ||
117 | |||
118 | @@ -157,7 +157,11 @@ _dl_next_tls_modid (void) | ||
119 | } | ||
120 | |||
121 | if (result - disp < runp->len) | ||
122 | - break; | ||
123 | + { | ||
124 | + /* Mark the entry as used, so any dependency see it. */ | ||
125 | + atomic_store_relaxed (&runp->slotinfo[result - disp].map, l); | ||
126 | + break; | ||
127 | + } | ||
128 | |||
129 | disp += runp->len; | ||
130 | } | ||
131 | @@ -184,17 +188,14 @@ _dl_next_tls_modid (void) | ||
132 | atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); | ||
133 | } | ||
134 | |||
135 | - return result; | ||
136 | + l->l_tls_modid = result; | ||
137 | } | ||
138 | |||
139 | |||
140 | size_t | ||
141 | _dl_count_modids (void) | ||
142 | { | ||
143 | - /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where | ||
144 | - we fail to load a module and unload it leaving a gap. If we don't | ||
145 | - have gaps then the number of modids is the current maximum so | ||
146 | - return that. */ | ||
147 | + /* The count is the max unless dlclose or failed dlopen created gaps. */ | ||
148 | if (__glibc_likely (!GL(dl_tls_dtv_gaps))) | ||
149 | return GL(dl_tls_max_dtv_idx); | ||
150 | |||
151 | diff --git a/elf/rtld.c b/elf/rtld.c | ||
152 | index e3fb2a5b2a..d733359eaf 100644 | ||
153 | --- a/elf/rtld.c | ||
154 | +++ b/elf/rtld.c | ||
155 | @@ -1612,7 +1612,7 @@ | ||
156 | /* Add the dynamic linker to the TLS list if it also uses TLS. */ | ||
157 | if (GL(dl_rtld_map).l_tls_blocksize != 0) | ||
158 | /* Assign a module ID. Do this before loading any audit modules. */ | ||
159 | - GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); | ||
160 | + _dl_assign_tls_modid (&GL(dl_rtld_map)); | ||
161 | |||
162 | /* If we have auditing DSOs to load, do it now. */ | ||
163 | bool need_security_init = true; | ||
164 | diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h | ||
165 | index 176394de4d..9c15259236 100644 | ||
166 | --- a/sysdeps/generic/ldsodefs.h | ||
167 | +++ b/sysdeps/generic/ldsodefs.h | ||
168 | @@ -1171,8 +1171,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr, | ||
169 | extern void _dl_sysdep_start_cleanup (void) attribute_hidden; | ||
170 | |||
171 | |||
172 | -/* Determine next available module ID. */ | ||
173 | -extern size_t _dl_next_tls_modid (void) attribute_hidden; | ||
174 | +/* Determine next available module ID and set the L l_tls_modid. */ | ||
175 | +extern void _dl_assign_tls_modid (struct link_map *l) attribute_hidden; | ||
176 | |||
177 | /* Count the modules with TLS segments. */ | ||
178 | extern size_t _dl_count_modids (void) attribute_hidden; | ||
179 | -- | ||
180 | 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 @@ | |||
1 | From 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86 Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Thu, 11 Feb 2021 11:29:23 +0000 | ||
4 | Subject: [PATCH] x86_64: Avoid lazy relocation of tlsdesc [BZ #27137] | ||
5 | |||
6 | Lazy tlsdesc relocation is racy because the static tls optimization and | ||
7 | tlsdesc management operations are done without holding the dlopen lock. | ||
8 | |||
9 | This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 | ||
10 | for aarch64, but it fixes a different race: bug 27137. | ||
11 | |||
12 | Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to | ||
13 | relocate tlsdesc lazily, but that does not work in a BIND_NOW module | ||
14 | due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at | ||
15 | load time fixes this bug 27721 too. | ||
16 | --- | ||
17 | sysdeps/x86_64/dl-machine.h | 19 ++++++++++++++----- | ||
18 | 1 file changed, 14 insertions(+), 5 deletions(-) | ||
19 | --- | ||
20 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86] | ||
21 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
22 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
23 | --- | ||
24 | diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h | ||
25 | index 103eee6c3f..9a876a371e 100644 | ||
26 | --- a/sysdeps/x86_64/dl-machine.h | ||
27 | +++ b/sysdeps/x86_64/dl-machine.h | ||
28 | @@ -570,12 +570,21 @@ elf_machine_lazy_rel (struct link_map *map, | ||
29 | } | ||
30 | else if (__glibc_likely (r_type == R_X86_64_TLSDESC)) | ||
31 | { | ||
32 | - struct tlsdesc volatile * __attribute__((__unused__)) td = | ||
33 | - (struct tlsdesc volatile *)reloc_addr; | ||
34 | + const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); | ||
35 | + const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); | ||
36 | + const ElfW (Sym) *sym = &symtab[symndx]; | ||
37 | + const struct r_found_version *version = NULL; | ||
38 | |||
39 | - td->arg = (void*)reloc; | ||
40 | - td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) | ||
41 | - + map->l_addr); | ||
42 | + if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) | ||
43 | + { | ||
44 | + const ElfW (Half) *vernum = | ||
45 | + (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); | ||
46 | + version = &map->l_versions[vernum[symndx] & 0x7fff]; | ||
47 | + } | ||
48 | + | ||
49 | + /* Always initialize TLS descriptors completely at load time, in | ||
50 | + case static TLS is allocated for it that requires locking. */ | ||
51 | + elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); | ||
52 | } | ||
53 | else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE)) | ||
54 | { | ||
55 | -- | ||
56 | 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 @@ | |||
1 | From ddcacd91cc10ff92d6201eda87047d029c14158d Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Thu, 11 Feb 2021 11:40:11 +0000 | ||
4 | Subject: [PATCH] i386: Avoid lazy relocation of tlsdesc [BZ #27137] | ||
5 | |||
6 | Lazy tlsdesc relocation is racy because the static tls optimization and | ||
7 | tlsdesc management operations are done without holding the dlopen lock. | ||
8 | |||
9 | This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 | ||
10 | for aarch64, but it fixes a different race: bug 27137. | ||
11 | |||
12 | On i386 the code is a bit more complicated than on x86_64 because both | ||
13 | rel and rela relocs are supported. | ||
14 | --- | ||
15 | sysdeps/i386/dl-machine.h | 76 ++++++++++++++++++--------------------- | ||
16 | 1 file changed, 34 insertions(+), 42 deletions(-) | ||
17 | --- | ||
18 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ddcacd91cc10ff92d6201eda87047d029c14158d] | ||
19 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
20 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
21 | --- | ||
22 | diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h | ||
23 | index 23e9cc3bfb..590b41d8d7 100644 | ||
24 | --- a/sysdeps/i386/dl-machine.h | ||
25 | +++ b/sysdeps/i386/dl-machine.h | ||
26 | @@ -688,50 +688,32 @@ elf_machine_lazy_rel (struct link_map *map, | ||
27 | } | ||
28 | else if (__glibc_likely (r_type == R_386_TLS_DESC)) | ||
29 | { | ||
30 | - struct tlsdesc volatile * __attribute__((__unused__)) td = | ||
31 | - (struct tlsdesc volatile *)reloc_addr; | ||
32 | - | ||
33 | - /* Handle relocations that reference the local *ABS* in a simple | ||
34 | - way, so as to preserve a potential addend. */ | ||
35 | - if (ELF32_R_SYM (reloc->r_info) == 0) | ||
36 | - td->entry = _dl_tlsdesc_resolve_abs_plus_addend; | ||
37 | - /* Given a known-zero addend, we can store a pointer to the | ||
38 | - reloc in the arg position. */ | ||
39 | - else if (td->arg == 0) | ||
40 | - { | ||
41 | - td->arg = (void*)reloc; | ||
42 | - td->entry = _dl_tlsdesc_resolve_rel; | ||
43 | - } | ||
44 | - else | ||
45 | - { | ||
46 | - /* We could handle non-*ABS* relocations with non-zero addends | ||
47 | - by allocating dynamically an arg to hold a pointer to the | ||
48 | - reloc, but that sounds pointless. */ | ||
49 | - const Elf32_Rel *const r = reloc; | ||
50 | - /* The code below was borrowed from elf_dynamic_do_rel(). */ | ||
51 | - const ElfW(Sym) *const symtab = | ||
52 | - (const void *) D_PTR (map, l_info[DT_SYMTAB]); | ||
53 | + const Elf32_Rel *const r = reloc; | ||
54 | + /* The code below was borrowed from elf_dynamic_do_rel(). */ | ||
55 | + const ElfW(Sym) *const symtab = | ||
56 | + (const void *) D_PTR (map, l_info[DT_SYMTAB]); | ||
57 | |||
58 | + /* Always initialize TLS descriptors completely at load time, in | ||
59 | + case static TLS is allocated for it that requires locking. */ | ||
60 | # ifdef RTLD_BOOTSTRAP | ||
61 | - /* The dynamic linker always uses versioning. */ | ||
62 | - assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); | ||
63 | + /* The dynamic linker always uses versioning. */ | ||
64 | + assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); | ||
65 | # else | ||
66 | - if (map->l_info[VERSYMIDX (DT_VERSYM)]) | ||
67 | + if (map->l_info[VERSYMIDX (DT_VERSYM)]) | ||
68 | # endif | ||
69 | - { | ||
70 | - const ElfW(Half) *const version = | ||
71 | - (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); | ||
72 | - ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; | ||
73 | - elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], | ||
74 | - &map->l_versions[ndx], | ||
75 | - (void *) (l_addr + r->r_offset), skip_ifunc); | ||
76 | - } | ||
77 | + { | ||
78 | + const ElfW(Half) *const version = | ||
79 | + (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); | ||
80 | + ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; | ||
81 | + elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], | ||
82 | + &map->l_versions[ndx], | ||
83 | + (void *) (l_addr + r->r_offset), skip_ifunc); | ||
84 | + } | ||
85 | # ifndef RTLD_BOOTSTRAP | ||
86 | - else | ||
87 | - elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, | ||
88 | - (void *) (l_addr + r->r_offset), skip_ifunc); | ||
89 | + else | ||
90 | + elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, | ||
91 | + (void *) (l_addr + r->r_offset), skip_ifunc); | ||
92 | # endif | ||
93 | - } | ||
94 | } | ||
95 | else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) | ||
96 | { | ||
97 | @@ -758,11 +740,21 @@ elf_machine_lazy_rela (struct link_map *map, | ||
98 | ; | ||
99 | else if (__glibc_likely (r_type == R_386_TLS_DESC)) | ||
100 | { | ||
101 | - struct tlsdesc volatile * __attribute__((__unused__)) td = | ||
102 | - (struct tlsdesc volatile *)reloc_addr; | ||
103 | + const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); | ||
104 | + const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); | ||
105 | + const ElfW (Sym) *sym = &symtab[symndx]; | ||
106 | + const struct r_found_version *version = NULL; | ||
107 | + | ||
108 | + if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) | ||
109 | + { | ||
110 | + const ElfW (Half) *vernum = | ||
111 | + (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); | ||
112 | + version = &map->l_versions[vernum[symndx] & 0x7fff]; | ||
113 | + } | ||
114 | |||
115 | - td->arg = (void*)reloc; | ||
116 | - td->entry = _dl_tlsdesc_resolve_rela; | ||
117 | + /* Always initialize TLS descriptors completely at load time, in | ||
118 | + case static TLS is allocated for it that requires locking. */ | ||
119 | + elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); | ||
120 | } | ||
121 | else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) | ||
122 | { | ||
123 | -- | ||
124 | 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 @@ | |||
1 | From 83b5323261bb72313bffcf37476c1b8f0847c736 Mon Sep 17 00:00:00 2001 | ||
2 | From: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||
3 | Date: Wed, 15 Sep 2021 15:16:19 +0100 | ||
4 | Subject: [PATCH] elf: Avoid deadlock between pthread_create and ctors [BZ | ||
5 | #28357] | ||
6 | |||
7 | The fix for bug 19329 caused a regression such that pthread_create can | ||
8 | deadlock when concurrent ctors from dlopen are waiting for it to finish. | ||
9 | Use a new GL(dl_load_tls_lock) in pthread_create that is not taken | ||
10 | around ctors in dlopen. | ||
11 | |||
12 | The new lock is also used in __tls_get_addr instead of GL(dl_load_lock). | ||
13 | |||
14 | The new lock is held in _dl_open_worker and _dl_close_worker around | ||
15 | most of the logic before/after the init/fini routines. When init/fini | ||
16 | routines are running then TLS is in a consistent, usable state. | ||
17 | In _dl_open_worker the new lock requires catching and reraising dlopen | ||
18 | failures that happen in the critical section. | ||
19 | |||
20 | The new lock is reinitialized in a fork child, to keep the existing | ||
21 | behaviour and it is kept recursive in case malloc interposition or TLS | ||
22 | access from signal handlers can retake it. It is not obvious if this | ||
23 | is necessary or helps, but avoids changing the preexisting behaviour. | ||
24 | |||
25 | The new lock may be more appropriate for dl_iterate_phdr too than | ||
26 | GL(dl_load_write_lock), since TLS state of an incompletely loaded | ||
27 | module may be accessed. If the new lock can replace the old one, | ||
28 | that can be a separate change. | ||
29 | |||
30 | Fixes bug 28357. | ||
31 | |||
32 | Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||
33 | --- | ||
34 | elf/dl-close.c | 6 ++ | ||
35 | elf/dl-open.c | 35 ++++++++- | ||
36 | elf/dl-support.c | 7 ++ | ||
37 | elf/dl-tls.c | 16 ++--- | ||
38 | elf/rtld.c | 1 + | ||
39 | sysdeps/nptl/fork.c | 3 + | ||
40 | sysdeps/generic/ldsodefs.h | 9 ++- | ||
41 | 10 files changed, 235 insertions(+), 12 deletions(-) | ||
42 | --- | ||
43 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=024a7640ab9ecea80e527f4e4d7f7a1868e952c5] | ||
44 | 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. | ||
45 | Signed-off-by: Akash Hadke <akash.hadke@kpit.com> | ||
46 | Signed-off-by: Akash Hadke <hadkeakash4@gmail.com> | ||
47 | --- | ||
48 | diff --git a/elf/dl-close.c b/elf/dl-close.c | ||
49 | index 93ff5c96e9..cfe0f1c0c9 100644 | ||
50 | --- a/elf/dl-close.c | ||
51 | +++ b/elf/dl-close.c | ||
52 | @@ -551,6 +551,9 @@ | ||
53 | size_t tls_free_end; | ||
54 | tls_free_start = tls_free_end = NO_TLS_OFFSET; | ||
55 | |||
56 | + /* Protects global and module specitic TLS state. */ | ||
57 | + __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); | ||
58 | + | ||
59 | /* We modify the list of loaded objects. */ | ||
60 | __rtld_lock_lock_recursive (GL(dl_load_write_lock)); | ||
61 | |||
62 | @@ -786,6 +789,9 @@ | ||
63 | GL(dl_tls_static_used) = tls_free_start; | ||
64 | } | ||
65 | |||
66 | + /* TLS is cleaned up for the unloaded modules. */ | ||
67 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
68 | + | ||
69 | #ifdef SHARED | ||
70 | /* Auditing checkpoint: we have deleted all objects. */ | ||
71 | if (__glibc_unlikely (do_audit)) | ||
72 | diff --git a/elf/dl-open.c b/elf/dl-open.c | ||
73 | index 5295e931b0..6ea5dd2457 100644 | ||
74 | --- a/elf/dl-open.c | ||
75 | +++ b/elf/dl-open.c | ||
76 | @@ -57,6 +57,9 @@ | ||
77 | (non-negative). */ | ||
78 | unsigned int original_global_scope_pending_adds; | ||
79 | |||
80 | + /* Set to true if the end of dl_open_worker_begin was reached. */ | ||
81 | + bool worker_continue; | ||
82 | + | ||
83 | /* Original parameters to the program and the current environment. */ | ||
84 | int argc; | ||
85 | char **argv; | ||
86 | @@ -473,7 +473,7 @@ | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | -dl_open_worker (void *a) | ||
91 | +dl_open_worker_begin (void *a) | ||
92 | { | ||
93 | struct dl_open_args *args = a; | ||
94 | const char *file = args->file; | ||
95 | @@ -747,6 +747,36 @@ | ||
96 | if (mode & RTLD_GLOBAL) | ||
97 | add_to_global_resize (new); | ||
98 | |||
99 | + args->worker_continue = true; | ||
100 | +} | ||
101 | + | ||
102 | +static void | ||
103 | +dl_open_worker (void *a) | ||
104 | +{ | ||
105 | + struct dl_open_args *args = a; | ||
106 | + | ||
107 | + args->worker_continue = false; | ||
108 | + | ||
109 | + { | ||
110 | + /* Protects global and module specific TLS state. */ | ||
111 | + __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); | ||
112 | + | ||
113 | + struct dl_exception ex; | ||
114 | + int err = _dl_catch_exception (&ex, dl_open_worker_begin, args); | ||
115 | + | ||
116 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
117 | + | ||
118 | + if (__glibc_unlikely (ex.errstring != NULL)) | ||
119 | + /* Reraise the error. */ | ||
120 | + _dl_signal_exception (err, &ex, NULL); | ||
121 | + } | ||
122 | + | ||
123 | + if (!args->worker_continue) | ||
124 | + return; | ||
125 | + | ||
126 | + int mode = args->mode; | ||
127 | + struct link_map *new = args->map; | ||
128 | + | ||
129 | /* Run the initializer functions of new objects. Temporarily | ||
130 | disable the exception handler, so that lazy binding failures are | ||
131 | fatal. */ | ||
132 | diff --git a/elf/dl-support.c b/elf/dl-support.c | ||
133 | index 02e2ed72f5..d99c1f1d62 100644 | ||
134 | --- a/elf/dl-support.c | ||
135 | +++ b/elf/dl-support.c | ||
136 | @@ -219,6 +219,13 @@ | ||
137 | list of loaded objects while an object is added to or removed from | ||
138 | that list. */ | ||
139 | __rtld_lock_define_initialized_recursive (, _dl_load_write_lock) | ||
140 | +/* This lock protects global and module specific TLS related data. | ||
141 | + E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), | ||
142 | + GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are | ||
143 | + accessed and when TLS related relocations are processed for a | ||
144 | + module. It was introduced to keep pthread_create accessing TLS | ||
145 | + state that is being set up. */ | ||
146 | +__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock) | ||
147 | |||
148 | |||
149 | #ifdef HAVE_AUX_VECTOR | ||
150 | diff --git a/elf/dl-tls.c b/elf/dl-tls.c | ||
151 | index d554ae4497..9260d2d696 100644 | ||
152 | --- a/elf/dl-tls.c | ||
153 | +++ b/elf/dl-tls.c | ||
154 | @@ -443,7 +443,7 @@ | ||
155 | size_t maxgen = 0; | ||
156 | |||
157 | /* Protects global dynamic TLS related state. */ | ||
158 | - __rtld_lock_lock_recursive (GL(dl_load_lock)); | ||
159 | + __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); | ||
160 | |||
161 | /* Check if the current dtv is big enough. */ | ||
162 | if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) | ||
163 | @@ -517,7 +517,7 @@ | ||
164 | listp = listp->next; | ||
165 | assert (listp != NULL); | ||
166 | } | ||
167 | - __rtld_lock_unlock_recursive (GL(dl_load_lock)); | ||
168 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
169 | |||
170 | /* The DTV version is up-to-date now. */ | ||
171 | dtv[0].counter = maxgen; | ||
172 | @@ -656,7 +656,7 @@ | ||
173 | |||
174 | Here the dtv needs to be updated to new_gen generation count. | ||
175 | |||
176 | - This code may be called during TLS access when GL(dl_load_lock) | ||
177 | + This code may be called during TLS access when GL(dl_load_tls_lock) | ||
178 | is not held. In that case the user code has to synchronize with | ||
179 | dlopen and dlclose calls of relevant modules. A module m is | ||
180 | relevant if the generation of m <= new_gen and dlclose of m is | ||
181 | @@ -778,11 +778,11 @@ | ||
182 | if (__glibc_unlikely (the_map->l_tls_offset | ||
183 | != FORCED_DYNAMIC_TLS_OFFSET)) | ||
184 | { | ||
185 | - __rtld_lock_lock_recursive (GL(dl_load_lock)); | ||
186 | + __rtld_lock_lock_recursive (GL(dl_load_tls_lock)); | ||
187 | if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET)) | ||
188 | { | ||
189 | the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET; | ||
190 | - __rtld_lock_unlock_recursive (GL(dl_load_lock)); | ||
191 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
192 | } | ||
193 | else if (__glibc_likely (the_map->l_tls_offset | ||
194 | != FORCED_DYNAMIC_TLS_OFFSET)) | ||
195 | @@ -794,7 +794,7 @@ | ||
196 | #else | ||
197 | # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" | ||
198 | #endif | ||
199 | - __rtld_lock_unlock_recursive (GL(dl_load_lock)); | ||
200 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
201 | |||
202 | dtv[GET_ADDR_MODULE].pointer.to_free = NULL; | ||
203 | dtv[GET_ADDR_MODULE].pointer.val = p; | ||
204 | @@ -802,7 +802,7 @@ | ||
205 | return (char *) p + GET_ADDR_OFFSET; | ||
206 | } | ||
207 | else | ||
208 | - __rtld_lock_unlock_recursive (GL(dl_load_lock)); | ||
209 | + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); | ||
210 | } | ||
211 | struct dtv_pointer result = allocate_and_init (the_map); | ||
212 | dtv[GET_ADDR_MODULE].pointer = result; | ||
213 | @@ -873,7 +873,7 @@ | ||
214 | return NULL; | ||
215 | |||
216 | dtv_t *dtv = THREAD_DTV (); | ||
217 | - /* This may be called without holding the GL(dl_load_lock). Reading | ||
218 | + /* This may be called without holding the GL(dl_load_tls_lock). Reading | ||
219 | arbitrary gen value is fine since this is best effort code. */ | ||
220 | size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); | ||
221 | if (__glibc_unlikely (dtv[0].counter != gen)) | ||
222 | diff --git a/elf/rtld.c b/elf/rtld.c | ||
223 | index 8d2bba3d43..9642eb9c92 100644 | ||
224 | --- a/elf/rtld.c | ||
225 | +++ b/elf/rtld.c | ||
226 | @@ -283,6 +283,7 @@ | ||
227 | #ifdef _LIBC_REENTRANT | ||
228 | ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, | ||
229 | ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, | ||
230 | + ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, | ||
231 | #endif | ||
232 | ._dl_nns = 1, | ||
233 | ._dl_ns = | ||
234 | diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c | ||
235 | index c471f7b15f..021691b9b7 100644 | ||
236 | --- a/sysdeps/nptl/fork.c | ||
237 | +++ b/sysdeps/nptl/fork.c | ||
238 | @@ -125,6 +125,9 @@ | ||
239 | /* Reset the lock the dynamic loader uses to protect its data. */ | ||
240 | __rtld_lock_initialize (GL(dl_load_lock)); | ||
241 | |||
242 | + /* Reset the lock protecting dynamic TLS related data. */ | ||
243 | + __rtld_lock_initialize (GL(dl_load_tls_lock)); | ||
244 | + | ||
245 | /* Run the handlers registered for the child. */ | ||
246 | __run_fork_handlers (atfork_run_child, multiple_threads); | ||
247 | } | ||
248 | diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h | ||
249 | index d49529da0d..9ec1511bb0 100644 | ||
250 | --- a/sysdeps/generic/ldsodefs.h | ||
251 | +++ b/sysdeps/generic/ldsodefs.h | ||
252 | @@ -369,6 +369,13 @@ | ||
253 | list of loaded objects while an object is added to or removed | ||
254 | from that list. */ | ||
255 | __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock) | ||
256 | + /* This lock protects global and module specific TLS related data. | ||
257 | + E.g. it is held in dlopen and dlclose when GL(dl_tls_generation), | ||
258 | + GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are | ||
259 | + accessed and when TLS related relocations are processed for a | ||
260 | + module. It was introduced to keep pthread_create accessing TLS | ||
261 | + state that is being set up. */ | ||
262 | + __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock) | ||
263 | |||
264 | /* Incremented whenever something may have been added to dl_loaded. */ | ||
265 | EXTERN unsigned long long _dl_load_adds; | ||
266 | @@ -1153,7 +1160,7 @@ | ||
267 | |||
268 | /* Add module to slot information data. If DO_ADD is false, only the | ||
269 | required memory is allocated. Must be called with GL | ||
270 | - (dl_load_lock) acquired. If the function has already been called | ||
271 | + (dl_load_tls_lock) acquired. If the function has already been called | ||
272 | for the link map L with !do_add, then this function will not raise | ||
273 | an exception, otherwise it is possible that it encounters a memory | ||
274 | allocation failure. */ | ||
275 | -- | ||
276 | 2.27.0 | ||
diff --git a/meta/recipes-core/glibc/glibc_2.31.bb b/meta/recipes-core/glibc/glibc_2.31.bb index 3a3586f1b9..4a545cb97d 100644 --- a/meta/recipes-core/glibc/glibc_2.31.bb +++ b/meta/recipes-core/glibc/glibc_2.31.bb | |||
@@ -70,6 +70,14 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ | |||
70 | file://CVE-2021-33574_1.patch \ | 70 | file://CVE-2021-33574_1.patch \ |
71 | file://CVE-2021-33574_2.patch \ | 71 | file://CVE-2021-33574_2.patch \ |
72 | file://CVE-2021-38604.patch \ | 72 | file://CVE-2021-38604.patch \ |
73 | file://0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch \ | ||
74 | file://0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch \ | ||
75 | file://0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch \ | ||
76 | file://0033-elf-Add-test-case-for-BZ-19329.patch \ | ||
77 | file://0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch \ | ||
78 | file://0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \ | ||
79 | file://0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \ | ||
80 | file://0037-Avoid-deadlock-between-pthread_create-and-ctors.patch \ | ||
73 | " | 81 | " |
74 | S = "${WORKDIR}/git" | 82 | S = "${WORKDIR}/git" |
75 | B = "${WORKDIR}/build-${TARGET_SYS}" | 83 | B = "${WORKDIR}/build-${TARGET_SYS}" |