diff options
Diffstat (limited to 'meta/recipes-core/glibc')
22 files changed, 2620 insertions, 299 deletions
diff --git a/meta/recipes-core/glibc/cross-localedef-native_2.31.bb b/meta/recipes-core/glibc/cross-localedef-native_2.31.bb index 24de55d929..9aa24eccfe 100644 --- a/meta/recipes-core/glibc/cross-localedef-native_2.31.bb +++ b/meta/recipes-core/glibc/cross-localedef-native_2.31.bb | |||
@@ -20,7 +20,7 @@ inherit autotools | |||
20 | FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:" | 20 | FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:" |
21 | 21 | ||
22 | SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ | 22 | SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ |
23 | git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \ | 23 | git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef;protocol=https \ |
24 | \ | 24 | \ |
25 | file://0001-localedef-Add-hardlink-resolver-to-build.patch;patchdir=localedef \ | 25 | file://0001-localedef-Add-hardlink-resolver-to-build.patch;patchdir=localedef \ |
26 | \ | 26 | \ |
diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc index 5f726537ff..95e2bba301 100644 --- a/meta/recipes-core/glibc/glibc-version.inc +++ b/meta/recipes-core/glibc/glibc-version.inc | |||
@@ -1,6 +1,6 @@ | |||
1 | SRCBRANCH ?= "release/2.31/master" | 1 | SRCBRANCH ?= "release/2.31/master" |
2 | PV = "2.31+git${SRCPV}" | 2 | PV = "2.31+git${SRCPV}" |
3 | SRCREV_glibc ?= "df31c7ca927242d5d4eee97f93a01e23ff47e332" | 3 | SRCREV_glibc ?= "2d4f26e5cfda682f9ce61444b81533b83f6381af" |
4 | SRCREV_localedef ?= "cd9f958c4c94a638fa7b2b4e21627364f1a1a655" | 4 | SRCREV_localedef ?= "cd9f958c4c94a638fa7b2b4e21627364f1a1a655" |
5 | 5 | ||
6 | GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" | 6 | GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" |
diff --git a/meta/recipes-core/glibc/glibc.inc b/meta/recipes-core/glibc/glibc.inc index 23a6ca99ae..e42040f3dc 100644 --- a/meta/recipes-core/glibc/glibc.inc +++ b/meta/recipes-core/glibc/glibc.inc | |||
@@ -1,7 +1,9 @@ | |||
1 | require glibc-common.inc | 1 | require glibc-common.inc |
2 | require glibc-ld.inc | 2 | require glibc-ld.inc |
3 | 3 | ||
4 | DEPENDS = "virtual/${TARGET_PREFIX}gcc libgcc-initial linux-libc-headers" | 4 | DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${TARGET_PREFIX}binutils${BUSUFFIX} libgcc-initial linux-libc-headers" |
5 | BUSUFFIX= "" | ||
6 | BUSUFFIX:class-nativesdk = "-crosssdk" | ||
5 | 7 | ||
6 | PROVIDES = "virtual/libc" | 8 | PROVIDES = "virtual/libc" |
7 | PROVIDES += "virtual/libintl virtual/libiconv" | 9 | PROVIDES += "virtual/libintl virtual/libiconv" |
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/CVE-2019-25013.patch b/meta/recipes-core/glibc/glibc/CVE-2019-25013.patch deleted file mode 100644 index 73df1da868..0000000000 --- a/meta/recipes-core/glibc/glibc/CVE-2019-25013.patch +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | From ee7a3144c9922808181009b7b3e50e852fb4999b Mon Sep 17 00:00:00 2001 | ||
2 | From: Andreas Schwab <schwab@suse.de> | ||
3 | Date: Mon, 21 Dec 2020 08:56:43 +0530 | ||
4 | Subject: [PATCH] Fix buffer overrun in EUC-KR conversion module (bz #24973) | ||
5 | |||
6 | The byte 0xfe as input to the EUC-KR conversion denotes a user-defined | ||
7 | area and is not allowed. The from_euc_kr function used to skip two bytes | ||
8 | when told to skip over the unknown designation, potentially running over | ||
9 | the buffer end. | ||
10 | |||
11 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ee7a3144c9922808181009b7b3e50e852fb4999b] | ||
12 | CVE: CVE-2019-25013 | ||
13 | Signed-off-by: Scott Murray <scott.murray@konsulko.com> | ||
14 | [Refreshed for Dundell context; Makefile changes] | ||
15 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
16 | |||
17 | --- | ||
18 | iconvdata/Makefile | 3 ++- | ||
19 | iconvdata/bug-iconv13.c | 53 +++++++++++++++++++++++++++++++++++++++++ | ||
20 | iconvdata/euc-kr.c | 6 +---- | ||
21 | iconvdata/ksc5601.h | 6 ++--- | ||
22 | 4 files changed, 59 insertions(+), 9 deletions(-) | ||
23 | create mode 100644 iconvdata/bug-iconv13.c | ||
24 | |||
25 | Index: git/iconvdata/Makefile | ||
26 | =================================================================== | ||
27 | --- git.orig/iconvdata/Makefile | ||
28 | +++ git/iconvdata/Makefile | ||
29 | @@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules | ||
30 | ifeq (yes,$(build-shared)) | ||
31 | tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ | ||
32 | tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ | ||
33 | - bug-iconv10 bug-iconv11 bug-iconv12 | ||
34 | + bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 | ||
35 | ifeq ($(have-thread-library),yes) | ||
36 | tests += bug-iconv3 | ||
37 | endif | ||
38 | Index: git/iconvdata/bug-iconv13.c | ||
39 | =================================================================== | ||
40 | --- /dev/null | ||
41 | +++ git/iconvdata/bug-iconv13.c | ||
42 | @@ -0,0 +1,53 @@ | ||
43 | +/* bug 24973: Test EUC-KR module | ||
44 | + Copyright (C) 2020 Free Software Foundation, Inc. | ||
45 | + This file is part of the GNU C Library. | ||
46 | + | ||
47 | + The GNU C Library is free software; you can redistribute it and/or | ||
48 | + modify it under the terms of the GNU Lesser General Public | ||
49 | + License as published by the Free Software Foundation; either | ||
50 | + version 2.1 of the License, or (at your option) any later version. | ||
51 | + | ||
52 | + The GNU C Library is distributed in the hope that it will be useful, | ||
53 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
54 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
55 | + Lesser General Public License for more details. | ||
56 | + | ||
57 | + You should have received a copy of the GNU Lesser General Public | ||
58 | + License along with the GNU C Library; if not, see | ||
59 | + <https://www.gnu.org/licenses/>. */ | ||
60 | + | ||
61 | +#include <errno.h> | ||
62 | +#include <iconv.h> | ||
63 | +#include <stdio.h> | ||
64 | +#include <support/check.h> | ||
65 | + | ||
66 | +static int | ||
67 | +do_test (void) | ||
68 | +{ | ||
69 | + iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR"); | ||
70 | + TEST_VERIFY_EXIT (cd != (iconv_t) -1); | ||
71 | + | ||
72 | + /* 0xfe (->0x7e : row 94) and 0xc9 (->0x49 : row 41) are user-defined | ||
73 | + areas, which are not allowed and should be skipped over due to | ||
74 | + //IGNORE. The trailing 0xfe also is an incomplete sequence, which | ||
75 | + should be checked first. */ | ||
76 | + char input[4] = { '\xc9', '\xa1', '\0', '\xfe' }; | ||
77 | + char *inptr = input; | ||
78 | + size_t insize = sizeof (input); | ||
79 | + char output[4]; | ||
80 | + char *outptr = output; | ||
81 | + size_t outsize = sizeof (output); | ||
82 | + | ||
83 | + /* This used to crash due to buffer overrun. */ | ||
84 | + TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); | ||
85 | + TEST_VERIFY (errno == EINVAL); | ||
86 | + /* The conversion should produce one character, the converted null | ||
87 | + character. */ | ||
88 | + TEST_VERIFY (sizeof (output) - outsize == 1); | ||
89 | + | ||
90 | + TEST_VERIFY_EXIT (iconv_close (cd) != -1); | ||
91 | + | ||
92 | + return 0; | ||
93 | +} | ||
94 | + | ||
95 | +#include <support/test-driver.c> | ||
96 | Index: git/iconvdata/euc-kr.c | ||
97 | =================================================================== | ||
98 | --- git.orig/iconvdata/euc-kr.c | ||
99 | +++ git/iconvdata/euc-kr.c | ||
100 | @@ -80,11 +80,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned c | ||
101 | \ | ||
102 | if (ch <= 0x9f) \ | ||
103 | ++inptr; \ | ||
104 | - /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ | ||
105 | - user-defined areas. */ \ | ||
106 | - else if (__builtin_expect (ch == 0xa0, 0) \ | ||
107 | - || __builtin_expect (ch > 0xfe, 0) \ | ||
108 | - || __builtin_expect (ch == 0xc9, 0)) \ | ||
109 | + else if (__glibc_unlikely (ch == 0xa0)) \ | ||
110 | { \ | ||
111 | /* This is illegal. */ \ | ||
112 | STANDARD_FROM_LOOP_ERR_HANDLER (1); \ | ||
113 | Index: git/iconvdata/ksc5601.h | ||
114 | =================================================================== | ||
115 | --- git.orig/iconvdata/ksc5601.h | ||
116 | +++ git/iconvdata/ksc5601.h | ||
117 | @@ -50,15 +50,15 @@ ksc5601_to_ucs4 (const unsigned char **s | ||
118 | unsigned char ch2; | ||
119 | int idx; | ||
120 | |||
121 | + if (avail < 2) | ||
122 | + return 0; | ||
123 | + | ||
124 | /* row 94(0x7e) and row 41(0x49) are user-defined area in KS C 5601 */ | ||
125 | |||
126 | if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e | ||
127 | || (ch - offset) == 0x49) | ||
128 | return __UNKNOWN_10646_CHAR; | ||
129 | |||
130 | - if (avail < 2) | ||
131 | - return 0; | ||
132 | - | ||
133 | ch2 = (*s)[1]; | ||
134 | if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f) | ||
135 | return __UNKNOWN_10646_CHAR; | ||
diff --git a/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch b/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch deleted file mode 100644 index c51fb3223a..0000000000 --- a/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch +++ /dev/null | |||
@@ -1,156 +0,0 @@ | |||
1 | From 228edd356f03bf62dcf2b1335f25d43c602ee68d Mon Sep 17 00:00:00 2001 | ||
2 | From: Michael Colavita <mcolavita@fb.com> | ||
3 | Date: Thu, 19 Nov 2020 11:44:40 -0500 | ||
4 | Subject: [PATCH] iconv: Fix incorrect UCS4 inner loop bounds (BZ#26923) | ||
5 | |||
6 | Previously, in UCS4 conversion routines we limit the number of | ||
7 | characters we examine to the minimum of the number of characters in the | ||
8 | input and the number of characters in the output. This is not the | ||
9 | correct behavior when __GCONV_IGNORE_ERRORS is set, as we do not consume | ||
10 | an output character when we skip a code unit. Instead, track the input | ||
11 | and output pointers and terminate the loop when either reaches its | ||
12 | limit. | ||
13 | |||
14 | This resolves assertion failures when resetting the input buffer in a step of | ||
15 | iconv, which assumes that the input will be fully consumed given sufficient | ||
16 | output space. | ||
17 | |||
18 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=228edd356f03bf62dcf2b1335f25d43c602ee68d] | ||
19 | CVE: CVE-2020-29562 | ||
20 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
21 | |||
22 | --- | ||
23 | iconv/Makefile | 2 +- | ||
24 | iconv/gconv_simple.c | 16 ++++---------- | ||
25 | iconv/tst-iconv8.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ | ||
26 | 3 files changed, 55 insertions(+), 13 deletions(-) | ||
27 | create mode 100644 iconv/tst-iconv8.c | ||
28 | |||
29 | diff --git a/iconv/Makefile b/iconv/Makefile | ||
30 | index 30bf996d3a..f9b51e23ec 100644 | ||
31 | --- a/iconv/Makefile | ||
32 | +++ b/iconv/Makefile | ||
33 | @@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION | ||
34 | CFLAGS-simple-hash.c += -I../locale | ||
35 | |||
36 | tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ | ||
37 | - tst-iconv7 tst-iconv-mt tst-iconv-opt | ||
38 | + tst-iconv7 tst-iconv8 tst-iconv-mt tst-iconv-opt | ||
39 | |||
40 | others = iconv_prog iconvconfig | ||
41 | install-others-programs = $(inst_bindir)/iconv | ||
42 | diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c | ||
43 | index d4797fba17..963b29f246 100644 | ||
44 | --- a/iconv/gconv_simple.c | ||
45 | +++ b/iconv/gconv_simple.c | ||
46 | @@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step, | ||
47 | int flags = step_data->__flags; | ||
48 | const unsigned char *inptr = *inptrp; | ||
49 | unsigned char *outptr = *outptrp; | ||
50 | - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; | ||
51 | int result; | ||
52 | - size_t cnt; | ||
53 | |||
54 | - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) | ||
55 | + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) | ||
56 | { | ||
57 | uint32_t inval; | ||
58 | |||
59 | @@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step, | ||
60 | int flags = step_data->__flags; | ||
61 | const unsigned char *inptr = *inptrp; | ||
62 | unsigned char *outptr = *outptrp; | ||
63 | - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; | ||
64 | int result; | ||
65 | - size_t cnt; | ||
66 | |||
67 | - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) | ||
68 | + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) | ||
69 | { | ||
70 | if (__glibc_unlikely (inptr[0] > 0x80)) | ||
71 | { | ||
72 | @@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step, | ||
73 | int flags = step_data->__flags; | ||
74 | const unsigned char *inptr = *inptrp; | ||
75 | unsigned char *outptr = *outptrp; | ||
76 | - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; | ||
77 | int result; | ||
78 | - size_t cnt; | ||
79 | |||
80 | - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) | ||
81 | + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) | ||
82 | { | ||
83 | uint32_t inval; | ||
84 | |||
85 | @@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step, | ||
86 | int flags = step_data->__flags; | ||
87 | const unsigned char *inptr = *inptrp; | ||
88 | unsigned char *outptr = *outptrp; | ||
89 | - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; | ||
90 | int result; | ||
91 | - size_t cnt; | ||
92 | |||
93 | - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) | ||
94 | + for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) | ||
95 | { | ||
96 | if (__glibc_unlikely (inptr[3] > 0x80)) | ||
97 | { | ||
98 | diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c | ||
99 | new file mode 100644 | ||
100 | index 0000000000..0b92b19f66 | ||
101 | --- /dev/null | ||
102 | +++ b/iconv/tst-iconv8.c | ||
103 | @@ -0,0 +1,50 @@ | ||
104 | +/* Test iconv behavior on UCS4 conversions with //IGNORE. | ||
105 | + Copyright (C) 2020 Free Software Foundation, Inc. | ||
106 | + This file is part of the GNU C Library. | ||
107 | + | ||
108 | + The GNU C Library is free software; you can redistribute it and/or | ||
109 | + modify it under the terms of the GNU Lesser General Public | ||
110 | + License as published by the Free Software Foundation; either | ||
111 | + version 2.1 of the License, or (at your option) any later version. | ||
112 | + | ||
113 | + The GNU C Library is distributed in the hope that it will be useful, | ||
114 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
115 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
116 | + Lesser General Public License for more details. | ||
117 | + | ||
118 | + You should have received a copy of the GNU Lesser General Public | ||
119 | + License along with the GNU C Library; if not, see | ||
120 | + <http://www.gnu.org/licenses/>. */ | ||
121 | + | ||
122 | +/* Derived from BZ #26923 */ | ||
123 | +#include <errno.h> | ||
124 | +#include <iconv.h> | ||
125 | +#include <stdio.h> | ||
126 | +#include <support/check.h> | ||
127 | + | ||
128 | +static int | ||
129 | +do_test (void) | ||
130 | +{ | ||
131 | + iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/"); | ||
132 | + TEST_VERIFY_EXIT (cd != (iconv_t) -1); | ||
133 | + | ||
134 | + /* | ||
135 | + * Convert sequence beginning with an irreversible character into buffer that | ||
136 | + * is too small. | ||
137 | + */ | ||
138 | + char input[12] = "\xe1\x80\xa1" "AAAAAAAAA"; | ||
139 | + char *inptr = input; | ||
140 | + size_t insize = sizeof (input); | ||
141 | + char output[6]; | ||
142 | + char *outptr = output; | ||
143 | + size_t outsize = sizeof (output); | ||
144 | + | ||
145 | + TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1); | ||
146 | + TEST_VERIFY (errno == E2BIG); | ||
147 | + | ||
148 | + TEST_VERIFY_EXIT (iconv_close (cd) != -1); | ||
149 | + | ||
150 | + return 0; | ||
151 | +} | ||
152 | + | ||
153 | +#include <support/test-driver.c> | ||
154 | -- | ||
155 | 2.27.0 | ||
156 | |||
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 @@ | |||
1 | From 42d359350510506b87101cf77202fefcbfc790cb Mon Sep 17 00:00:00 2001 | ||
2 | From: Andreas Schwab <schwab@linux-m68k.org> | ||
3 | Date: Thu, 27 May 2021 12:49:47 +0200 | ||
4 | Subject: [PATCH] Use __pthread_attr_copy in mq_notify (bug 27896) | ||
5 | |||
6 | Make a deep copy of the pthread attribute object to remove a potential | ||
7 | use-after-free issue. | ||
8 | |||
9 | Upstream-Status: Backport | ||
10 | CVE: CVE-2021-33574 patch#1 | ||
11 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
12 | |||
13 | --- | ||
14 | diff --git a/NEWS b/NEWS | ||
15 | index 8a20d3c4e3..be489243ac 100644 | ||
16 | --- a/NEWS | ||
17 | +++ b/NEWS | ||
18 | @@ -7,6 +7,10 @@ using `glibc' in the "product" field. | ||
19 | |||
20 | Version 2.31.1 | ||
21 | |||
22 | + CVE-2021-33574: The mq_notify function has a potential use-after-free | ||
23 | + issue when using a notification type of SIGEV_THREAD and a thread | ||
24 | + attribute with a non-default affinity mask. | ||
25 | + | ||
26 | The following bugs are resolved with this release: | ||
27 | [14231] stdio-common tests memory requirements | ||
28 | [19519] iconv(1) with -c option hangs on illegal multi-byte sequences | ||
29 | diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c | ||
30 | index f288bac477..dd47f0b777 100644 | ||
31 | --- a/sysdeps/unix/sysv/linux/mq_notify.c | ||
32 | +++ b/sysdeps/unix/sysv/linux/mq_notify.c | ||
33 | @@ -135,8 +135,11 @@ helper_thread (void *arg) | ||
34 | (void) __pthread_barrier_wait (¬ify_barrier); | ||
35 | } | ||
36 | else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) | ||
37 | - /* The only state we keep is the copy of the thread attributes. */ | ||
38 | - free (data.attr); | ||
39 | + { | ||
40 | + /* The only state we keep is the copy of the thread attributes. */ | ||
41 | + pthread_attr_destroy (data.attr); | ||
42 | + free (data.attr); | ||
43 | + } | ||
44 | } | ||
45 | return NULL; | ||
46 | } | ||
47 | @@ -257,8 +260,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) | ||
48 | if (data.attr == NULL) | ||
49 | return -1; | ||
50 | |||
51 | - memcpy (data.attr, notification->sigev_notify_attributes, | ||
52 | - sizeof (pthread_attr_t)); | ||
53 | + __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); | ||
54 | } | ||
55 | |||
56 | /* Construct the new request. */ | ||
57 | @@ -272,7 +274,10 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) | ||
58 | |||
59 | /* If it failed, free the allocated memory. */ | ||
60 | if (__glibc_unlikely (retval != 0)) | ||
61 | - free (data.attr); | ||
62 | + { | ||
63 | + pthread_attr_destroy (data.attr); | ||
64 | + free (data.attr); | ||
65 | + } | ||
66 | |||
67 | return retval; | ||
68 | } | ||
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 @@ | |||
1 | From 217b6dc298156bdb0d6aea9ea93e7e394a5ff091 Mon Sep 17 00:00:00 2001 | ||
2 | From: Florian Weimer <fweimer@redhat.com> | ||
3 | Date: Tue, 1 Jun 2021 17:51:41 +0200 | ||
4 | Subject: [PATCH] Fix use of __pthread_attr_copy in mq_notify (bug 27896) | ||
5 | |||
6 | __pthread_attr_copy can fail and does not initialize the attribute | ||
7 | structure in that case. | ||
8 | |||
9 | If __pthread_attr_copy is never called and there is no allocated | ||
10 | attribute, pthread_attr_destroy should not be called, otherwise | ||
11 | there is a null pointer dereference in rt/tst-mqueue6. | ||
12 | |||
13 | Fixes commit 42d359350510506b87101cf77202fefcbfc790cb | ||
14 | ("Use __pthread_attr_copy in mq_notify (bug 27896)"). | ||
15 | |||
16 | Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||
17 | |||
18 | https://sourceware.org/bugzilla/attachment.cgi?id=13497 | ||
19 | |||
20 | Upstream-Status: Backport | ||
21 | CVE: CVE-2021-33574 patch#2 | ||
22 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
23 | |||
24 | --- | ||
25 | Index: git/sysdeps/unix/sysv/linux/mq_notify.c | ||
26 | =================================================================== | ||
27 | --- git.orig/sysdeps/unix/sysv/linux/mq_notify.c | ||
28 | +++ git/sysdeps/unix/sysv/linux/mq_notify.c | ||
29 | @@ -260,7 +260,34 @@ mq_notify (mqd_t mqdes, const struct sig | ||
30 | if (data.attr == NULL) | ||
31 | return -1; | ||
32 | |||
33 | - __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); | ||
34 | + memcpy (data.attr, notification->sigev_notify_attributes, | ||
35 | + sizeof (pthread_attr_t)); | ||
36 | + | ||
37 | + struct pthread_attr *source = | ||
38 | + (struct pthread_attr *) (notification->sigev_notify_attributes); | ||
39 | + struct pthread_attr *target = (struct pthread_attr *) (data.attr); | ||
40 | + cpu_set_t *newp; | ||
41 | + cpu_set_t *cpuset = source->cpuset; | ||
42 | + size_t cpusetsize = source->cpusetsize; | ||
43 | + | ||
44 | + /* alloc a new memory for cpuset to avoid use after free */ | ||
45 | + if (cpuset != NULL && cpusetsize > 0) | ||
46 | + { | ||
47 | + newp = (cpu_set_t *) malloc (cpusetsize); | ||
48 | + if (newp == NULL) | ||
49 | + { | ||
50 | + free(data.attr); | ||
51 | + return -1; | ||
52 | + } | ||
53 | + | ||
54 | + memcpy (newp, cpuset, cpusetsize); | ||
55 | + target->cpuset = newp; | ||
56 | + } | ||
57 | + else | ||
58 | + { | ||
59 | + target->cpuset = NULL; | ||
60 | + target->cpusetsize = 0; | ||
61 | + } | ||
62 | } | ||
63 | |||
64 | /* Construct the new request. */ | ||
65 | @@ -273,7 +300,7 @@ mq_notify (mqd_t mqdes, const struct sig | ||
66 | int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); | ||
67 | |||
68 | /* If it failed, free the allocated memory. */ | ||
69 | - if (__glibc_unlikely (retval != 0)) | ||
70 | + if (retval != 0 && data.attr != NULL) | ||
71 | { | ||
72 | pthread_attr_destroy (data.attr); | ||
73 | 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 @@ | |||
1 | From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nikita Popov <npv1310@gmail.com> | ||
3 | Date: Mon, 9 Aug 2021 20:17:34 +0530 | ||
4 | Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213) | ||
5 | |||
6 | Helper thread frees copied attribute on NOTIFY_REMOVED message | ||
7 | received from the OS kernel. Unfortunately, it fails to check whether | ||
8 | copied attribute actually exists (data.attr != NULL). This worked | ||
9 | earlier because free() checks passed pointer before actually | ||
10 | attempting to release corresponding memory. But | ||
11 | __pthread_attr_destroy assumes pointer is not NULL. | ||
12 | |||
13 | So passing NULL pointer to __pthread_attr_destroy will result in | ||
14 | segmentation fault. This scenario is possible if | ||
15 | notification->sigev_notify_attributes == NULL (which means default | ||
16 | thread attributes should be used). | ||
17 | |||
18 | Signed-off-by: Nikita Popov <npv1310@gmail.com> | ||
19 | Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||
20 | |||
21 | Upstream-Status: Backport | ||
22 | CVE: CVE-2021-38604 | ||
23 | Signed-off-by: Armin Kuser <akuster@mvista.com> | ||
24 | |||
25 | --- | ||
26 | sysdeps/unix/sysv/linux/mq_notify.c | 2 +- | ||
27 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
28 | |||
29 | Index: git/sysdeps/unix/sysv/linux/mq_notify.c | ||
30 | =================================================================== | ||
31 | --- git.orig/sysdeps/unix/sysv/linux/mq_notify.c | ||
32 | +++ git/sysdeps/unix/sysv/linux/mq_notify.c | ||
33 | @@ -134,7 +134,7 @@ helper_thread (void *arg) | ||
34 | to wait until it is done with it. */ | ||
35 | (void) __pthread_barrier_wait (¬ify_barrier); | ||
36 | } | ||
37 | - else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) | ||
38 | + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) | ||
39 | { | ||
40 | /* The only state we keep is the copy of the thread attributes. */ | ||
41 | 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 @@ | |||
1 | From 952aff5c00ad7c6b83c3f310f2643939538827f8 Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= | ||
3 | =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru> | ||
4 | Date: Sat, 4 Feb 2023 14:41:38 +0300 | ||
5 | Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444) | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | The `__monstartup()` allocates a buffer used to store all the data | ||
11 | accumulated by the monitor. | ||
12 | |||
13 | The size of this buffer depends on the size of the internal structures | ||
14 | used and the address range for which the monitor is activated, as well | ||
15 | as on the maximum density of call instructions and/or callable functions | ||
16 | that could be potentially on a segment of executable code. | ||
17 | |||
18 | In particular a hash table of arcs is placed at the end of this buffer. | ||
19 | The size of this hash table is calculated in bytes as | ||
20 | p->fromssize = p->textsize / HASHFRACTION; | ||
21 | |||
22 | but actually should be | ||
23 | p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); | ||
24 | |||
25 | This results in writing beyond the end of the allocated buffer when an | ||
26 | added arc corresponds to a call near from the end of the monitored | ||
27 | address range, since `_mcount()` check the incoming caller address for | ||
28 | monitored range but not the intermediate result hash-like index that | ||
29 | uses to write into the table. | ||
30 | |||
31 | It should be noted that when the results are output to `gmon.out`, the | ||
32 | table is read to the last element calculated from the allocated size in | ||
33 | bytes, so the arcs stored outside the buffer boundary did not fall into | ||
34 | `gprof` for analysis. Thus this "feature" help me to found this bug | ||
35 | during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438 | ||
36 | |||
37 | Just in case, I will explicitly note that the problem breaks the | ||
38 | `make test t=gmon/tst-gmon-dso` added for Bug 29438. | ||
39 | There, the arc of the `f3()` call disappears from the output, since in | ||
40 | the DSO case, the call to `f3` is located close to the end of the | ||
41 | monitored range. | ||
42 | |||
43 | Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru> | ||
44 | |||
45 | Another minor error seems a related typo in the calculation of | ||
46 | `kcountsize`, but since kcounts are smaller than froms, this is | ||
47 | actually to align the p->froms data. | ||
48 | |||
49 | Co-authored-by: DJ Delorie <dj@redhat.com> | ||
50 | Reviewed-by: Carlos O'Donell <carlos@redhat.com> | ||
51 | |||
52 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=801af9fafd4689337ebf27260aa115335a0cb2bc] | ||
53 | CVE: CVE-2023-0687 | ||
54 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | ||
55 | --- | ||
56 | gmon/gmon.c | 4 +++- | ||
57 | 1 file changed, 3 insertions(+), 1 deletion(-) | ||
58 | |||
59 | diff --git a/gmon/gmon.c b/gmon/gmon.c | ||
60 | index dee6480..bf76358 100644 | ||
61 | --- a/gmon/gmon.c | ||
62 | +++ b/gmon/gmon.c | ||
63 | @@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc) | ||
64 | p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); | ||
65 | p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); | ||
66 | p->textsize = p->highpc - p->lowpc; | ||
67 | + /* This looks like a typo, but it's here to align the p->froms | ||
68 | + section. */ | ||
69 | p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); | ||
70 | p->hashfraction = HASHFRACTION; | ||
71 | p->log_hashfraction = -1; | ||
72 | @@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc) | ||
73 | instead of integer division. Precompute shift amount. */ | ||
74 | p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; | ||
75 | } | ||
76 | - p->fromssize = p->textsize / HASHFRACTION; | ||
77 | + p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); | ||
78 | p->tolimit = p->textsize * ARCDENSITY / 100; | ||
79 | if (p->tolimit < MINARCS) | ||
80 | p->tolimit = MINARCS; | ||
81 | -- | ||
82 | 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 @@ | |||
1 | From 1c37b8022e8763fedbb3f79c02e05c6acfe5a215 Mon Sep 17 00:00:00 2001 | ||
2 | From: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||
3 | Date: Thu, 17 Mar 2022 11:44:34 +0530 | ||
4 | Subject: [PATCH] Simplify allocations and fix merge and continue actions [BZ | ||
5 | #28931] | ||
6 | |||
7 | Allocations for address tuples is currently a bit confusing because of | ||
8 | the pointer chasing through PAT, making it hard to observe the sequence | ||
9 | in which allocations have been made. Narrow scope of the pointer | ||
10 | chasing through PAT so that it is only used where necessary. | ||
11 | |||
12 | This also tightens actions behaviour with the hosts database in | ||
13 | getaddrinfo to comply with the manual text. The "continue" action | ||
14 | discards previous results and the "merge" action results in an immedate | ||
15 | lookup failure. Consequently, chaining of allocations across modules is | ||
16 | no longer necessary, thus opening up cleanup opportunities. | ||
17 | |||
18 | A test has been added that checks some combinations to ensure that they | ||
19 | work correctly. | ||
20 | |||
21 | Resolves: BZ #28931 | ||
22 | |||
23 | CVE: CVE-2023-4813 | ||
24 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=1c37b8022e8763fedbb3f79c02e05c6acfe5a215] | ||
25 | Comments: Hunks refreshed | ||
26 | |||
27 | Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||
28 | Reviewed-by: DJ Delorie <dj@redhat.com> | ||
29 | Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> | ||
30 | --- | ||
31 | nss/Makefile | 1 + | ||
32 | nss/tst-nss-gai-actions.c | 149 ++++++ | ||
33 | nss/tst-nss-gai-actions.root/etc/host.conf | 1 + | ||
34 | nss/tst-nss-gai-actions.root/etc/hosts | 508 +++++++++++++++++++++ | ||
35 | sysdeps/posix/getaddrinfo.c | 143 +++--- | ||
36 | 5 files changed, 750 insertions(+), 52 deletions(-) | ||
37 | create mode 100644 nss/tst-nss-gai-actions.c | ||
38 | create mode 100644 nss/tst-nss-gai-actions.root/etc/host.conf | ||
39 | create mode 100644 nss/tst-nss-gai-actions.root/etc/hosts | ||
40 | |||
41 | diff --git a/nss/Makefile b/nss/Makefile | ||
42 | index 42a59535cb..d8b06b44fb 100644 | ||
43 | --- a/nss/Makefile | ||
44 | +++ b/nss/Makefile | ||
45 | @@ -61,6 +61,7 @@ | ||
46 | |||
47 | tests-container = \ | ||
48 | tst-nss-test3 \ | ||
49 | + tst-nss-gai-actions \ | ||
50 | tst-nss-files-hosts-long \ | ||
51 | tst-nss-db-endpwent \ | ||
52 | tst-nss-db-endgrent | ||
53 | diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c | ||
54 | new file mode 100644 | ||
55 | index 0000000000..efca6cd183 | ||
56 | --- /dev/null | ||
57 | +++ b/nss/tst-nss-gai-actions.c | ||
58 | @@ -0,0 +1,149 @@ | ||
59 | +/* Test continue and merge NSS actions for getaddrinfo. | ||
60 | + Copyright The GNU Toolchain Authors. | ||
61 | + This file is part of the GNU C Library. | ||
62 | + | ||
63 | + The GNU C Library is free software; you can redistribute it and/or | ||
64 | + modify it under the terms of the GNU Lesser General Public | ||
65 | + License as published by the Free Software Foundation; either | ||
66 | + version 2.1 of the License, or (at your option) any later version. | ||
67 | + | ||
68 | + The GNU C Library is distributed in the hope that it will be useful, | ||
69 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
70 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
71 | + Lesser General Public License for more details. | ||
72 | + | ||
73 | + You should have received a copy of the GNU Lesser General Public | ||
74 | + License along with the GNU C Library; if not, see | ||
75 | + <https://www.gnu.org/licenses/>. */ | ||
76 | + | ||
77 | +#include <dlfcn.h> | ||
78 | +#include <gnu/lib-names.h> | ||
79 | +#include <nss.h> | ||
80 | +#include <stdio.h> | ||
81 | +#include <stdlib.h> | ||
82 | +#include <string.h> | ||
83 | + | ||
84 | +#include <support/check.h> | ||
85 | +#include <support/format_nss.h> | ||
86 | +#include <support/support.h> | ||
87 | +#include <support/xstdio.h> | ||
88 | +#include <support/xunistd.h> | ||
89 | + | ||
90 | +enum | ||
91 | +{ | ||
92 | + ACTION_MERGE = 0, | ||
93 | + ACTION_CONTINUE, | ||
94 | +}; | ||
95 | + | ||
96 | +static const char * | ||
97 | +family_str (int family) | ||
98 | +{ | ||
99 | + switch (family) | ||
100 | + { | ||
101 | + case AF_UNSPEC: | ||
102 | + return "AF_UNSPEC"; | ||
103 | + case AF_INET: | ||
104 | + return "AF_INET"; | ||
105 | + default: | ||
106 | + __builtin_unreachable (); | ||
107 | + } | ||
108 | +} | ||
109 | + | ||
110 | +static const char * | ||
111 | +action_str (int action) | ||
112 | +{ | ||
113 | + switch (action) | ||
114 | + { | ||
115 | + case ACTION_MERGE: | ||
116 | + return "merge"; | ||
117 | + case ACTION_CONTINUE: | ||
118 | + return "continue"; | ||
119 | + default: | ||
120 | + __builtin_unreachable (); | ||
121 | + } | ||
122 | +} | ||
123 | + | ||
124 | +static void | ||
125 | +do_one_test (int action, int family, bool canon) | ||
126 | +{ | ||
127 | + struct addrinfo hints = | ||
128 | + { | ||
129 | + .ai_family = family, | ||
130 | + }; | ||
131 | + | ||
132 | + struct addrinfo *ai; | ||
133 | + | ||
134 | + if (canon) | ||
135 | + hints.ai_flags = AI_CANONNAME; | ||
136 | + | ||
137 | + printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n", | ||
138 | + action_str (action), family_str (family), | ||
139 | + canon ? "AI_CANONNAME" : ""); | ||
140 | + | ||
141 | + int ret = getaddrinfo ("example.org", "80", &hints, &ai); | ||
142 | + | ||
143 | + switch (action) | ||
144 | + { | ||
145 | + case ACTION_MERGE: | ||
146 | + if (ret == 0) | ||
147 | + { | ||
148 | + char *formatted = support_format_addrinfo (ai, ret); | ||
149 | + | ||
150 | + printf ("merge unexpectedly succeeded:\n %s\n", formatted); | ||
151 | + support_record_failure (); | ||
152 | + free (formatted); | ||
153 | + } | ||
154 | + else | ||
155 | + return; | ||
156 | + case ACTION_CONTINUE: | ||
157 | + { | ||
158 | + char *formatted = support_format_addrinfo (ai, ret); | ||
159 | + | ||
160 | + /* Verify that the result appears exactly once. */ | ||
161 | + const char *expected = "address: STREAM/TCP 192.0.0.1 80\n" | ||
162 | + "address: DGRAM/UDP 192.0.0.1 80\n" | ||
163 | + "address: RAW/IP 192.0.0.1 80\n"; | ||
164 | + | ||
165 | + const char *contains = strstr (formatted, expected); | ||
166 | + const char *contains2 = NULL; | ||
167 | + | ||
168 | + if (contains != NULL) | ||
169 | + contains2 = strstr (contains + strlen (expected), expected); | ||
170 | + | ||
171 | + if (contains == NULL || contains2 != NULL) | ||
172 | + { | ||
173 | + printf ("continue failed:\n%s\n", formatted); | ||
174 | + support_record_failure (); | ||
175 | + } | ||
176 | + | ||
177 | + free (formatted); | ||
178 | + break; | ||
179 | + } | ||
180 | + default: | ||
181 | + __builtin_unreachable (); | ||
182 | + } | ||
183 | +} | ||
184 | + | ||
185 | +static void | ||
186 | +do_one_test_set (int action) | ||
187 | +{ | ||
188 | + char buf[32]; | ||
189 | + | ||
190 | + snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files", | ||
191 | + action_str (action)); | ||
192 | + __nss_configure_lookup ("hosts", buf); | ||
193 | + | ||
194 | + do_one_test (action, AF_UNSPEC, false); | ||
195 | + do_one_test (action, AF_INET, false); | ||
196 | + do_one_test (action, AF_INET, true); | ||
197 | +} | ||
198 | + | ||
199 | +static int | ||
200 | +do_test (void) | ||
201 | +{ | ||
202 | + do_one_test_set (ACTION_CONTINUE); | ||
203 | + do_one_test_set (ACTION_MERGE); | ||
204 | + return 0; | ||
205 | +} | ||
206 | + | ||
207 | +#include <support/test-driver.c> | ||
208 | diff --git a/nss/tst-nss-gai-actions.root/etc/host.conf b/nss/tst-nss-gai-actions.root/etc/host.conf | ||
209 | new file mode 100644 | ||
210 | index 0000000000..d1a59f73a9 | ||
211 | --- /dev/null | ||
212 | +++ b/nss/tst-nss-gai-actions.root/etc/host.conf | ||
213 | @@ -0,0 +1 @@ | ||
214 | +multi on | ||
215 | diff --git a/nss/tst-nss-gai-actions.root/etc/hosts b/nss/tst-nss-gai-actions.root/etc/hosts | ||
216 | new file mode 100644 | ||
217 | index 0000000000..50ce9774dc | ||
218 | --- /dev/null | ||
219 | +++ b/nss/tst-nss-gai-actions.root/etc/hosts | ||
220 | @@ -0,0 +1,508 @@ | ||
221 | +192.0.0.1 example.org | ||
222 | +192.0.0.2 example.org | ||
223 | +192.0.0.3 example.org | ||
224 | +192.0.0.4 example.org | ||
225 | +192.0.0.5 example.org | ||
226 | +192.0.0.6 example.org | ||
227 | +192.0.0.7 example.org | ||
228 | +192.0.0.8 example.org | ||
229 | +192.0.0.9 example.org | ||
230 | +192.0.0.10 example.org | ||
231 | +192.0.0.11 example.org | ||
232 | +192.0.0.12 example.org | ||
233 | +192.0.0.13 example.org | ||
234 | +192.0.0.14 example.org | ||
235 | +192.0.0.15 example.org | ||
236 | +192.0.0.16 example.org | ||
237 | +192.0.0.17 example.org | ||
238 | +192.0.0.18 example.org | ||
239 | +192.0.0.19 example.org | ||
240 | +192.0.0.20 example.org | ||
241 | +192.0.0.21 example.org | ||
242 | +192.0.0.22 example.org | ||
243 | +192.0.0.23 example.org | ||
244 | +192.0.0.24 example.org | ||
245 | +192.0.0.25 example.org | ||
246 | +192.0.0.26 example.org | ||
247 | +192.0.0.27 example.org | ||
248 | +192.0.0.28 example.org | ||
249 | +192.0.0.29 example.org | ||
250 | +192.0.0.30 example.org | ||
251 | +192.0.0.31 example.org | ||
252 | +192.0.0.32 example.org | ||
253 | +192.0.0.33 example.org | ||
254 | +192.0.0.34 example.org | ||
255 | +192.0.0.35 example.org | ||
256 | +192.0.0.36 example.org | ||
257 | +192.0.0.37 example.org | ||
258 | +192.0.0.38 example.org | ||
259 | +192.0.0.39 example.org | ||
260 | +192.0.0.40 example.org | ||
261 | +192.0.0.41 example.org | ||
262 | +192.0.0.42 example.org | ||
263 | +192.0.0.43 example.org | ||
264 | +192.0.0.44 example.org | ||
265 | +192.0.0.45 example.org | ||
266 | +192.0.0.46 example.org | ||
267 | +192.0.0.47 example.org | ||
268 | +192.0.0.48 example.org | ||
269 | +192.0.0.49 example.org | ||
270 | +192.0.0.50 example.org | ||
271 | +192.0.0.51 example.org | ||
272 | +192.0.0.52 example.org | ||
273 | +192.0.0.53 example.org | ||
274 | +192.0.0.54 example.org | ||
275 | +192.0.0.55 example.org | ||
276 | +192.0.0.56 example.org | ||
277 | +192.0.0.57 example.org | ||
278 | +192.0.0.58 example.org | ||
279 | +192.0.0.59 example.org | ||
280 | +192.0.0.60 example.org | ||
281 | +192.0.0.61 example.org | ||
282 | +192.0.0.62 example.org | ||
283 | +192.0.0.63 example.org | ||
284 | +192.0.0.64 example.org | ||
285 | +192.0.0.65 example.org | ||
286 | +192.0.0.66 example.org | ||
287 | +192.0.0.67 example.org | ||
288 | +192.0.0.68 example.org | ||
289 | +192.0.0.69 example.org | ||
290 | +192.0.0.70 example.org | ||
291 | +192.0.0.71 example.org | ||
292 | +192.0.0.72 example.org | ||
293 | +192.0.0.73 example.org | ||
294 | +192.0.0.74 example.org | ||
295 | +192.0.0.75 example.org | ||
296 | +192.0.0.76 example.org | ||
297 | +192.0.0.77 example.org | ||
298 | +192.0.0.78 example.org | ||
299 | +192.0.0.79 example.org | ||
300 | +192.0.0.80 example.org | ||
301 | +192.0.0.81 example.org | ||
302 | +192.0.0.82 example.org | ||
303 | +192.0.0.83 example.org | ||
304 | +192.0.0.84 example.org | ||
305 | +192.0.0.85 example.org | ||
306 | +192.0.0.86 example.org | ||
307 | +192.0.0.87 example.org | ||
308 | +192.0.0.88 example.org | ||
309 | +192.0.0.89 example.org | ||
310 | +192.0.0.90 example.org | ||
311 | +192.0.0.91 example.org | ||
312 | +192.0.0.92 example.org | ||
313 | +192.0.0.93 example.org | ||
314 | +192.0.0.94 example.org | ||
315 | +192.0.0.95 example.org | ||
316 | +192.0.0.96 example.org | ||
317 | +192.0.0.97 example.org | ||
318 | +192.0.0.98 example.org | ||
319 | +192.0.0.99 example.org | ||
320 | +192.0.0.100 example.org | ||
321 | +192.0.0.101 example.org | ||
322 | +192.0.0.102 example.org | ||
323 | +192.0.0.103 example.org | ||
324 | +192.0.0.104 example.org | ||
325 | +192.0.0.105 example.org | ||
326 | +192.0.0.106 example.org | ||
327 | +192.0.0.107 example.org | ||
328 | +192.0.0.108 example.org | ||
329 | +192.0.0.109 example.org | ||
330 | +192.0.0.110 example.org | ||
331 | +192.0.0.111 example.org | ||
332 | +192.0.0.112 example.org | ||
333 | +192.0.0.113 example.org | ||
334 | +192.0.0.114 example.org | ||
335 | +192.0.0.115 example.org | ||
336 | +192.0.0.116 example.org | ||
337 | +192.0.0.117 example.org | ||
338 | +192.0.0.118 example.org | ||
339 | +192.0.0.119 example.org | ||
340 | +192.0.0.120 example.org | ||
341 | +192.0.0.121 example.org | ||
342 | +192.0.0.122 example.org | ||
343 | +192.0.0.123 example.org | ||
344 | +192.0.0.124 example.org | ||
345 | +192.0.0.125 example.org | ||
346 | +192.0.0.126 example.org | ||
347 | +192.0.0.127 example.org | ||
348 | +192.0.0.128 example.org | ||
349 | +192.0.0.129 example.org | ||
350 | +192.0.0.130 example.org | ||
351 | +192.0.0.131 example.org | ||
352 | +192.0.0.132 example.org | ||
353 | +192.0.0.133 example.org | ||
354 | +192.0.0.134 example.org | ||
355 | +192.0.0.135 example.org | ||
356 | +192.0.0.136 example.org | ||
357 | +192.0.0.137 example.org | ||
358 | +192.0.0.138 example.org | ||
359 | +192.0.0.139 example.org | ||
360 | +192.0.0.140 example.org | ||
361 | +192.0.0.141 example.org | ||
362 | +192.0.0.142 example.org | ||
363 | +192.0.0.143 example.org | ||
364 | +192.0.0.144 example.org | ||
365 | +192.0.0.145 example.org | ||
366 | +192.0.0.146 example.org | ||
367 | +192.0.0.147 example.org | ||
368 | +192.0.0.148 example.org | ||
369 | +192.0.0.149 example.org | ||
370 | +192.0.0.150 example.org | ||
371 | +192.0.0.151 example.org | ||
372 | +192.0.0.152 example.org | ||
373 | +192.0.0.153 example.org | ||
374 | +192.0.0.154 example.org | ||
375 | +192.0.0.155 example.org | ||
376 | +192.0.0.156 example.org | ||
377 | +192.0.0.157 example.org | ||
378 | +192.0.0.158 example.org | ||
379 | +192.0.0.159 example.org | ||
380 | +192.0.0.160 example.org | ||
381 | +192.0.0.161 example.org | ||
382 | +192.0.0.162 example.org | ||
383 | +192.0.0.163 example.org | ||
384 | +192.0.0.164 example.org | ||
385 | +192.0.0.165 example.org | ||
386 | +192.0.0.166 example.org | ||
387 | +192.0.0.167 example.org | ||
388 | +192.0.0.168 example.org | ||
389 | +192.0.0.169 example.org | ||
390 | +192.0.0.170 example.org | ||
391 | +192.0.0.171 example.org | ||
392 | +192.0.0.172 example.org | ||
393 | +192.0.0.173 example.org | ||
394 | +192.0.0.174 example.org | ||
395 | +192.0.0.175 example.org | ||
396 | +192.0.0.176 example.org | ||
397 | +192.0.0.177 example.org | ||
398 | +192.0.0.178 example.org | ||
399 | +192.0.0.179 example.org | ||
400 | +192.0.0.180 example.org | ||
401 | +192.0.0.181 example.org | ||
402 | +192.0.0.182 example.org | ||
403 | +192.0.0.183 example.org | ||
404 | +192.0.0.184 example.org | ||
405 | +192.0.0.185 example.org | ||
406 | +192.0.0.186 example.org | ||
407 | +192.0.0.187 example.org | ||
408 | +192.0.0.188 example.org | ||
409 | +192.0.0.189 example.org | ||
410 | +192.0.0.190 example.org | ||
411 | +192.0.0.191 example.org | ||
412 | +192.0.0.192 example.org | ||
413 | +192.0.0.193 example.org | ||
414 | +192.0.0.194 example.org | ||
415 | +192.0.0.195 example.org | ||
416 | +192.0.0.196 example.org | ||
417 | +192.0.0.197 example.org | ||
418 | +192.0.0.198 example.org | ||
419 | +192.0.0.199 example.org | ||
420 | +192.0.0.200 example.org | ||
421 | +192.0.0.201 example.org | ||
422 | +192.0.0.202 example.org | ||
423 | +192.0.0.203 example.org | ||
424 | +192.0.0.204 example.org | ||
425 | +192.0.0.205 example.org | ||
426 | +192.0.0.206 example.org | ||
427 | +192.0.0.207 example.org | ||
428 | +192.0.0.208 example.org | ||
429 | +192.0.0.209 example.org | ||
430 | +192.0.0.210 example.org | ||
431 | +192.0.0.211 example.org | ||
432 | +192.0.0.212 example.org | ||
433 | +192.0.0.213 example.org | ||
434 | +192.0.0.214 example.org | ||
435 | +192.0.0.215 example.org | ||
436 | +192.0.0.216 example.org | ||
437 | +192.0.0.217 example.org | ||
438 | +192.0.0.218 example.org | ||
439 | +192.0.0.219 example.org | ||
440 | +192.0.0.220 example.org | ||
441 | +192.0.0.221 example.org | ||
442 | +192.0.0.222 example.org | ||
443 | +192.0.0.223 example.org | ||
444 | +192.0.0.224 example.org | ||
445 | +192.0.0.225 example.org | ||
446 | +192.0.0.226 example.org | ||
447 | +192.0.0.227 example.org | ||
448 | +192.0.0.228 example.org | ||
449 | +192.0.0.229 example.org | ||
450 | +192.0.0.230 example.org | ||
451 | +192.0.0.231 example.org | ||
452 | +192.0.0.232 example.org | ||
453 | +192.0.0.233 example.org | ||
454 | +192.0.0.234 example.org | ||
455 | +192.0.0.235 example.org | ||
456 | +192.0.0.236 example.org | ||
457 | +192.0.0.237 example.org | ||
458 | +192.0.0.238 example.org | ||
459 | +192.0.0.239 example.org | ||
460 | +192.0.0.240 example.org | ||
461 | +192.0.0.241 example.org | ||
462 | +192.0.0.242 example.org | ||
463 | +192.0.0.243 example.org | ||
464 | +192.0.0.244 example.org | ||
465 | +192.0.0.245 example.org | ||
466 | +192.0.0.246 example.org | ||
467 | +192.0.0.247 example.org | ||
468 | +192.0.0.248 example.org | ||
469 | +192.0.0.249 example.org | ||
470 | +192.0.0.250 example.org | ||
471 | +192.0.0.251 example.org | ||
472 | +192.0.0.252 example.org | ||
473 | +192.0.0.253 example.org | ||
474 | +192.0.0.254 example.org | ||
475 | +192.0.1.1 example.org | ||
476 | +192.0.1.2 example.org | ||
477 | +192.0.1.3 example.org | ||
478 | +192.0.1.4 example.org | ||
479 | +192.0.1.5 example.org | ||
480 | +192.0.1.6 example.org | ||
481 | +192.0.1.7 example.org | ||
482 | +192.0.1.8 example.org | ||
483 | +192.0.1.9 example.org | ||
484 | +192.0.1.10 example.org | ||
485 | +192.0.1.11 example.org | ||
486 | +192.0.1.12 example.org | ||
487 | +192.0.1.13 example.org | ||
488 | +192.0.1.14 example.org | ||
489 | +192.0.1.15 example.org | ||
490 | +192.0.1.16 example.org | ||
491 | +192.0.1.17 example.org | ||
492 | +192.0.1.18 example.org | ||
493 | +192.0.1.19 example.org | ||
494 | +192.0.1.20 example.org | ||
495 | +192.0.1.21 example.org | ||
496 | +192.0.1.22 example.org | ||
497 | +192.0.1.23 example.org | ||
498 | +192.0.1.24 example.org | ||
499 | +192.0.1.25 example.org | ||
500 | +192.0.1.26 example.org | ||
501 | +192.0.1.27 example.org | ||
502 | +192.0.1.28 example.org | ||
503 | +192.0.1.29 example.org | ||
504 | +192.0.1.30 example.org | ||
505 | +192.0.1.31 example.org | ||
506 | +192.0.1.32 example.org | ||
507 | +192.0.1.33 example.org | ||
508 | +192.0.1.34 example.org | ||
509 | +192.0.1.35 example.org | ||
510 | +192.0.1.36 example.org | ||
511 | +192.0.1.37 example.org | ||
512 | +192.0.1.38 example.org | ||
513 | +192.0.1.39 example.org | ||
514 | +192.0.1.40 example.org | ||
515 | +192.0.1.41 example.org | ||
516 | +192.0.1.42 example.org | ||
517 | +192.0.1.43 example.org | ||
518 | +192.0.1.44 example.org | ||
519 | +192.0.1.45 example.org | ||
520 | +192.0.1.46 example.org | ||
521 | +192.0.1.47 example.org | ||
522 | +192.0.1.48 example.org | ||
523 | +192.0.1.49 example.org | ||
524 | +192.0.1.50 example.org | ||
525 | +192.0.1.51 example.org | ||
526 | +192.0.1.52 example.org | ||
527 | +192.0.1.53 example.org | ||
528 | +192.0.1.54 example.org | ||
529 | +192.0.1.55 example.org | ||
530 | +192.0.1.56 example.org | ||
531 | +192.0.1.57 example.org | ||
532 | +192.0.1.58 example.org | ||
533 | +192.0.1.59 example.org | ||
534 | +192.0.1.60 example.org | ||
535 | +192.0.1.61 example.org | ||
536 | +192.0.1.62 example.org | ||
537 | +192.0.1.63 example.org | ||
538 | +192.0.1.64 example.org | ||
539 | +192.0.1.65 example.org | ||
540 | +192.0.1.66 example.org | ||
541 | +192.0.1.67 example.org | ||
542 | +192.0.1.68 example.org | ||
543 | +192.0.1.69 example.org | ||
544 | +192.0.1.70 example.org | ||
545 | +192.0.1.71 example.org | ||
546 | +192.0.1.72 example.org | ||
547 | +192.0.1.73 example.org | ||
548 | +192.0.1.74 example.org | ||
549 | +192.0.1.75 example.org | ||
550 | +192.0.1.76 example.org | ||
551 | +192.0.1.77 example.org | ||
552 | +192.0.1.78 example.org | ||
553 | +192.0.1.79 example.org | ||
554 | +192.0.1.80 example.org | ||
555 | +192.0.1.81 example.org | ||
556 | +192.0.1.82 example.org | ||
557 | +192.0.1.83 example.org | ||
558 | +192.0.1.84 example.org | ||
559 | +192.0.1.85 example.org | ||
560 | +192.0.1.86 example.org | ||
561 | +192.0.1.87 example.org | ||
562 | +192.0.1.88 example.org | ||
563 | +192.0.1.89 example.org | ||
564 | +192.0.1.90 example.org | ||
565 | +192.0.1.91 example.org | ||
566 | +192.0.1.92 example.org | ||
567 | +192.0.1.93 example.org | ||
568 | +192.0.1.94 example.org | ||
569 | +192.0.1.95 example.org | ||
570 | +192.0.1.96 example.org | ||
571 | +192.0.1.97 example.org | ||
572 | +192.0.1.98 example.org | ||
573 | +192.0.1.99 example.org | ||
574 | +192.0.1.100 example.org | ||
575 | +192.0.1.101 example.org | ||
576 | +192.0.1.102 example.org | ||
577 | +192.0.1.103 example.org | ||
578 | +192.0.1.104 example.org | ||
579 | +192.0.1.105 example.org | ||
580 | +192.0.1.106 example.org | ||
581 | +192.0.1.107 example.org | ||
582 | +192.0.1.108 example.org | ||
583 | +192.0.1.109 example.org | ||
584 | +192.0.1.110 example.org | ||
585 | +192.0.1.111 example.org | ||
586 | +192.0.1.112 example.org | ||
587 | +192.0.1.113 example.org | ||
588 | +192.0.1.114 example.org | ||
589 | +192.0.1.115 example.org | ||
590 | +192.0.1.116 example.org | ||
591 | +192.0.1.117 example.org | ||
592 | +192.0.1.118 example.org | ||
593 | +192.0.1.119 example.org | ||
594 | +192.0.1.120 example.org | ||
595 | +192.0.1.121 example.org | ||
596 | +192.0.1.122 example.org | ||
597 | +192.0.1.123 example.org | ||
598 | +192.0.1.124 example.org | ||
599 | +192.0.1.125 example.org | ||
600 | +192.0.1.126 example.org | ||
601 | +192.0.1.127 example.org | ||
602 | +192.0.1.128 example.org | ||
603 | +192.0.1.129 example.org | ||
604 | +192.0.1.130 example.org | ||
605 | +192.0.1.131 example.org | ||
606 | +192.0.1.132 example.org | ||
607 | +192.0.1.133 example.org | ||
608 | +192.0.1.134 example.org | ||
609 | +192.0.1.135 example.org | ||
610 | +192.0.1.136 example.org | ||
611 | +192.0.1.137 example.org | ||
612 | +192.0.1.138 example.org | ||
613 | +192.0.1.139 example.org | ||
614 | +192.0.1.140 example.org | ||
615 | +192.0.1.141 example.org | ||
616 | +192.0.1.142 example.org | ||
617 | +192.0.1.143 example.org | ||
618 | +192.0.1.144 example.org | ||
619 | +192.0.1.145 example.org | ||
620 | +192.0.1.146 example.org | ||
621 | +192.0.1.147 example.org | ||
622 | +192.0.1.148 example.org | ||
623 | +192.0.1.149 example.org | ||
624 | +192.0.1.150 example.org | ||
625 | +192.0.1.151 example.org | ||
626 | +192.0.1.152 example.org | ||
627 | +192.0.1.153 example.org | ||
628 | +192.0.1.154 example.org | ||
629 | +192.0.1.155 example.org | ||
630 | +192.0.1.156 example.org | ||
631 | +192.0.1.157 example.org | ||
632 | +192.0.1.158 example.org | ||
633 | +192.0.1.159 example.org | ||
634 | +192.0.1.160 example.org | ||
635 | +192.0.1.161 example.org | ||
636 | +192.0.1.162 example.org | ||
637 | +192.0.1.163 example.org | ||
638 | +192.0.1.164 example.org | ||
639 | +192.0.1.165 example.org | ||
640 | +192.0.1.166 example.org | ||
641 | +192.0.1.167 example.org | ||
642 | +192.0.1.168 example.org | ||
643 | +192.0.1.169 example.org | ||
644 | +192.0.1.170 example.org | ||
645 | +192.0.1.171 example.org | ||
646 | +192.0.1.172 example.org | ||
647 | +192.0.1.173 example.org | ||
648 | +192.0.1.174 example.org | ||
649 | +192.0.1.175 example.org | ||
650 | +192.0.1.176 example.org | ||
651 | +192.0.1.177 example.org | ||
652 | +192.0.1.178 example.org | ||
653 | +192.0.1.179 example.org | ||
654 | +192.0.1.180 example.org | ||
655 | +192.0.1.181 example.org | ||
656 | +192.0.1.182 example.org | ||
657 | +192.0.1.183 example.org | ||
658 | +192.0.1.184 example.org | ||
659 | +192.0.1.185 example.org | ||
660 | +192.0.1.186 example.org | ||
661 | +192.0.1.187 example.org | ||
662 | +192.0.1.188 example.org | ||
663 | +192.0.1.189 example.org | ||
664 | +192.0.1.190 example.org | ||
665 | +192.0.1.191 example.org | ||
666 | +192.0.1.192 example.org | ||
667 | +192.0.1.193 example.org | ||
668 | +192.0.1.194 example.org | ||
669 | +192.0.1.195 example.org | ||
670 | +192.0.1.196 example.org | ||
671 | +192.0.1.197 example.org | ||
672 | +192.0.1.198 example.org | ||
673 | +192.0.1.199 example.org | ||
674 | +192.0.1.200 example.org | ||
675 | +192.0.1.201 example.org | ||
676 | +192.0.1.202 example.org | ||
677 | +192.0.1.203 example.org | ||
678 | +192.0.1.204 example.org | ||
679 | +192.0.1.205 example.org | ||
680 | +192.0.1.206 example.org | ||
681 | +192.0.1.207 example.org | ||
682 | +192.0.1.208 example.org | ||
683 | +192.0.1.209 example.org | ||
684 | +192.0.1.210 example.org | ||
685 | +192.0.1.211 example.org | ||
686 | +192.0.1.212 example.org | ||
687 | +192.0.1.213 example.org | ||
688 | +192.0.1.214 example.org | ||
689 | +192.0.1.215 example.org | ||
690 | +192.0.1.216 example.org | ||
691 | +192.0.1.217 example.org | ||
692 | +192.0.1.218 example.org | ||
693 | +192.0.1.219 example.org | ||
694 | +192.0.1.220 example.org | ||
695 | +192.0.1.221 example.org | ||
696 | +192.0.1.222 example.org | ||
697 | +192.0.1.223 example.org | ||
698 | +192.0.1.224 example.org | ||
699 | +192.0.1.225 example.org | ||
700 | +192.0.1.226 example.org | ||
701 | +192.0.1.227 example.org | ||
702 | +192.0.1.228 example.org | ||
703 | +192.0.1.229 example.org | ||
704 | +192.0.1.230 example.org | ||
705 | +192.0.1.231 example.org | ||
706 | +192.0.1.232 example.org | ||
707 | +192.0.1.233 example.org | ||
708 | +192.0.1.234 example.org | ||
709 | +192.0.1.235 example.org | ||
710 | +192.0.1.236 example.org | ||
711 | +192.0.1.237 example.org | ||
712 | +192.0.1.238 example.org | ||
713 | +192.0.1.239 example.org | ||
714 | +192.0.1.240 example.org | ||
715 | +192.0.1.241 example.org | ||
716 | +192.0.1.242 example.org | ||
717 | +192.0.1.243 example.org | ||
718 | +192.0.1.244 example.org | ||
719 | +192.0.1.245 example.org | ||
720 | +192.0.1.246 example.org | ||
721 | +192.0.1.247 example.org | ||
722 | +192.0.1.248 example.org | ||
723 | +192.0.1.249 example.org | ||
724 | +192.0.1.250 example.org | ||
725 | +192.0.1.251 example.org | ||
726 | +192.0.1.252 example.org | ||
727 | +192.0.1.253 example.org | ||
728 | +192.0.1.254 example.org | ||
729 | diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c | ||
730 | index 18dccd5924..3d9bea60c6 100644 | ||
731 | --- a/sysdeps/posix/getaddrinfo.c | ||
732 | +++ b/sysdeps/posix/getaddrinfo.c | ||
733 | @@ -458,11 +458,6 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
734 | |||
735 | if (name != NULL) | ||
736 | { | ||
737 | - at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); | ||
738 | - at->family = AF_UNSPEC; | ||
739 | - at->scopeid = 0; | ||
740 | - at->next = NULL; | ||
741 | - | ||
742 | if (req->ai_flags & AI_IDN) | ||
743 | { | ||
744 | char *out; | ||
745 | @@ -473,13 +468,21 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
746 | malloc_name = true; | ||
747 | } | ||
748 | |||
749 | - if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) | ||
750 | + uint32_t addr[4]; | ||
751 | + if (__inet_aton_exact (name, (struct in_addr *) addr) != 0) | ||
752 | { | ||
753 | + at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); | ||
754 | + at->scopeid = 0; | ||
755 | + at->next = NULL; | ||
756 | + | ||
757 | if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) | ||
758 | - at->family = AF_INET; | ||
759 | + { | ||
760 | + memcpy (at->addr, addr, sizeof (at->addr)); | ||
761 | + at->family = AF_INET; | ||
762 | + } | ||
763 | else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED)) | ||
764 | { | ||
765 | - at->addr[3] = at->addr[0]; | ||
766 | + at->addr[3] = addr[0]; | ||
767 | at->addr[2] = htonl (0xffff); | ||
768 | at->addr[1] = 0; | ||
769 | at->addr[0] = 0; | ||
770 | @@ -505,49 +505,62 @@ | ||
771 | |||
772 | if (req->ai_flags & AI_CANONNAME) | ||
773 | canon = name; | ||
774 | + | ||
775 | + goto process_list; | ||
776 | } | ||
777 | - else if (at->family == AF_UNSPEC) | ||
778 | + | ||
779 | + char *scope_delim = strchr (name, SCOPE_DELIMITER); | ||
780 | + int e; | ||
781 | + | ||
782 | + if (scope_delim == NULL) | ||
783 | + e = inet_pton (AF_INET6, name, addr); | ||
784 | + else | ||
785 | + e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr); | ||
786 | + | ||
787 | + if (e > 0) | ||
788 | { | ||
789 | - char *scope_delim = strchr (name, SCOPE_DELIMITER); | ||
790 | - int e; | ||
791 | - if (scope_delim == NULL) | ||
792 | - e = inet_pton (AF_INET6, name, at->addr); | ||
793 | + at = alloca_account (sizeof (struct gaih_addrtuple), | ||
794 | + alloca_used); | ||
795 | + at->scopeid = 0; | ||
796 | + at->next = NULL; | ||
797 | + | ||
798 | + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) | ||
799 | + { | ||
800 | + memcpy (at->addr, addr, sizeof (at->addr)); | ||
801 | + at->family = AF_INET6; | ||
802 | + } | ||
803 | + else if (req->ai_family == AF_INET | ||
804 | + && IN6_IS_ADDR_V4MAPPED (addr)) | ||
805 | + { | ||
806 | + at->addr[0] = addr[3]; | ||
807 | + at->addr[1] = addr[1]; | ||
808 | + at->addr[2] = addr[2]; | ||
809 | + at->addr[3] = addr[3]; | ||
810 | + at->family = AF_INET; | ||
811 | + } | ||
812 | else | ||
813 | - e = __inet_pton_length (AF_INET6, name, scope_delim - name, | ||
814 | - at->addr); | ||
815 | - if (e > 0) | ||
816 | { | ||
817 | - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) | ||
818 | - at->family = AF_INET6; | ||
819 | - else if (req->ai_family == AF_INET | ||
820 | - && IN6_IS_ADDR_V4MAPPED (at->addr)) | ||
821 | - { | ||
822 | - at->addr[0] = at->addr[3]; | ||
823 | - at->family = AF_INET; | ||
824 | - } | ||
825 | - else | ||
826 | - { | ||
827 | - result = -EAI_ADDRFAMILY; | ||
828 | - goto free_and_return; | ||
829 | - } | ||
830 | - | ||
831 | - if (scope_delim != NULL | ||
832 | - && __inet6_scopeid_pton ((struct in6_addr *) at->addr, | ||
833 | - scope_delim + 1, | ||
834 | - &at->scopeid) != 0) | ||
835 | - { | ||
836 | - result = -EAI_NONAME; | ||
837 | - goto free_and_return; | ||
838 | - } | ||
839 | + result = -EAI_ADDRFAMILY; | ||
840 | + goto free_and_return; | ||
841 | + } | ||
842 | |||
843 | - if (req->ai_flags & AI_CANONNAME) | ||
844 | - canon = name; | ||
845 | + if (scope_delim != NULL | ||
846 | + && __inet6_scopeid_pton ((struct in6_addr *) at->addr, | ||
847 | + scope_delim + 1, | ||
848 | + &at->scopeid) != 0) | ||
849 | + { | ||
850 | + result = -EAI_NONAME; | ||
851 | + goto free_and_return; | ||
852 | } | ||
853 | + | ||
854 | + if (req->ai_flags & AI_CANONNAME) | ||
855 | + canon = name; | ||
856 | + | ||
857 | + goto process_list; | ||
858 | } | ||
859 | |||
860 | - if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) | ||
861 | + if ((req->ai_flags & AI_NUMERICHOST) == 0) | ||
862 | { | ||
863 | - struct gaih_addrtuple **pat = &at; | ||
864 | int no_data = 0; | ||
865 | int no_inet6_data = 0; | ||
866 | service_user *nip; | ||
867 | @@ -543,6 +559,7 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
868 | enum nss_status status = NSS_STATUS_UNAVAIL; | ||
869 | int no_more; | ||
870 | struct resolv_context *res_ctx = NULL; | ||
871 | + bool do_merge = false; | ||
872 | |||
873 | /* If we do not have to look for IPv6 addresses or the canonical | ||
874 | name, use the simple, old functions, which do not support | ||
875 | @@ -579,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
876 | result = -EAI_MEMORY; | ||
877 | goto free_and_return; | ||
878 | } | ||
879 | - *pat = addrmem; | ||
880 | + at = addrmem; | ||
881 | } | ||
882 | else | ||
883 | { | ||
884 | @@ -632,6 +649,8 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
885 | } | ||
886 | |||
887 | struct gaih_addrtuple *addrfree = addrmem; | ||
888 | + struct gaih_addrtuple **pat = &at; | ||
889 | + | ||
890 | for (int i = 0; i < air->naddrs; ++i) | ||
891 | { | ||
892 | socklen_t size = (air->family[i] == AF_INET | ||
893 | @@ -695,12 +714,6 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
894 | |||
895 | free (air); | ||
896 | |||
897 | - if (at->family == AF_UNSPEC) | ||
898 | - { | ||
899 | - result = -EAI_NONAME; | ||
900 | - goto free_and_return; | ||
901 | - } | ||
902 | - | ||
903 | goto process_list; | ||
904 | } | ||
905 | else if (err == 0) | ||
906 | @@ -750,6 +763,22 @@ | ||
907 | |||
908 | while (!no_more) | ||
909 | { | ||
910 | + /* Always start afresh; continue should discard previous results | ||
911 | + and the hosts database does not support merge. */ | ||
912 | + at = NULL; | ||
913 | + free (canonbuf); | ||
914 | + free (addrmem); | ||
915 | + canon = canonbuf = NULL; | ||
916 | + addrmem = NULL; | ||
917 | + got_ipv6 = false; | ||
918 | + | ||
919 | + if (do_merge) | ||
920 | + { | ||
921 | + __set_h_errno (NETDB_INTERNAL); | ||
922 | + __set_errno (EBUSY); | ||
923 | + break; | ||
924 | + } | ||
925 | + | ||
926 | no_data = 0; | ||
927 | nss_gethostbyname4_r fct4 = NULL; | ||
928 | |||
929 | @@ -744,12 +773,14 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
930 | { | ||
931 | while (1) | ||
932 | { | ||
933 | - status = DL_CALL_FCT (fct4, (name, pat, | ||
934 | + status = DL_CALL_FCT (fct4, (name, &at, | ||
935 | tmpbuf->data, tmpbuf->length, | ||
936 | &errno, &h_errno, | ||
937 | NULL)); | ||
938 | if (status == NSS_STATUS_SUCCESS) | ||
939 | break; | ||
940 | + /* gethostbyname4_r may write into AT, so reset it. */ | ||
941 | + at = NULL; | ||
942 | if (status != NSS_STATUS_TRYAGAIN | ||
943 | || errno != ERANGE || h_errno != NETDB_INTERNAL) | ||
944 | { | ||
945 | @@ -774,7 +805,9 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
946 | no_data = 1; | ||
947 | |||
948 | if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) | ||
949 | - canon = (*pat)->name; | ||
950 | + canon = at->name; | ||
951 | + | ||
952 | + struct gaih_addrtuple **pat = &at; | ||
953 | |||
954 | while (*pat != NULL) | ||
955 | { | ||
956 | @@ -826,6 +859,8 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
957 | |||
958 | if (fct != NULL) | ||
959 | { | ||
960 | + struct gaih_addrtuple **pat = &at; | ||
961 | + | ||
962 | if (req->ai_family == AF_INET6 | ||
963 | || req->ai_family == AF_UNSPEC) | ||
964 | { | ||
965 | @@ -917,6 +946,10 @@ | ||
966 | if (nss_next_action (nip, status) == NSS_ACTION_RETURN) | ||
967 | break; | ||
968 | |||
969 | + /* The hosts database does not support MERGE. */ | ||
970 | + if (nss_next_action (nip, status) == NSS_ACTION_MERGE) | ||
971 | + do_merge = true; | ||
972 | + | ||
973 | if (nip->next == NULL) | ||
974 | no_more = -1; | ||
975 | else | ||
976 | @@ -930,7 +969,7 @@ gaih_inet (const char *name, const struct gaih_service *service, | ||
977 | } | ||
978 | |||
979 | process_list: | ||
980 | - if (at->family == AF_UNSPEC) | ||
981 | + if (at == NULL) | ||
982 | { | ||
983 | result = -EAI_NONAME; | ||
984 | goto free_and_return; | ||
985 | -- | ||
986 | 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 @@ | |||
1 | From d2b77337f734fcacdfc8e0ddec14cf31a746c7be Mon Sep 17 00:00:00 2001 | ||
2 | From: Siddhesh Poyarekar <siddhesh@redhat.com> | ||
3 | Date: Mon, 11 Sep 2023 18:53:15 -0400 | ||
4 | Subject: [PATCH v2] tunables: Terminate immediately if end of input is reached | ||
5 | |||
6 | The string parsing routine may end up writing beyond bounds of tunestr | ||
7 | if the input tunable string is malformed, of the form name=name=val. | ||
8 | This gets processed twice, first as name=name=val and next as name=val, | ||
9 | resulting in tunestr being name=name=val:name=val, thus overflowing | ||
10 | tunestr. | ||
11 | |||
12 | Terminate the parsing loop at the first instance itself so that tunestr | ||
13 | does not overflow. | ||
14 | --- | ||
15 | Changes from v1: | ||
16 | |||
17 | - Also null-terminate tunestr before exiting. | ||
18 | |||
19 | elf/dl-tunables.c | 17 ++++++++++------- | ||
20 | 1 file changed, 10 insertions(+), 7 deletions(-) | ||
21 | |||
22 | Upstream-Status: Backport [git://sourceware.org/git/glibc.git] | ||
23 | CVE: CVE-2023-4911 | ||
24 | |||
25 | diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c | ||
26 | index 8e7ee9df10..76cf8b9da3 100644 | ||
27 | --- a/elf/dl-tunables.c | ||
28 | +++ b/elf/dl-tunables.c | ||
29 | @@ -187,11 +187,7 @@ parse_tunables (char *tunestr, char *valstring) | ||
30 | /* If we reach the end of the string before getting a valid name-value | ||
31 | pair, bail out. */ | ||
32 | if (p[len] == '\0') | ||
33 | - { | ||
34 | - if (__libc_enable_secure) | ||
35 | - tunestr[off] = '\0'; | ||
36 | - return; | ||
37 | - } | ||
38 | + break; | ||
39 | |||
40 | /* We did not find a valid name-value pair before encountering the | ||
41 | colon. */ | ||
42 | @@ -251,9 +247,16 @@ parse_tunables (char *tunestr, char *valstring) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | - if (p[len] != '\0') | ||
47 | - p += len + 1; | ||
48 | + /* We reached the end while processing the tunable string. */ | ||
49 | + if (p[len] == '\0') | ||
50 | + break; | ||
51 | + | ||
52 | + p += len + 1; | ||
53 | } | ||
54 | + | ||
55 | + /* Terminate tunestr before we leave. */ | ||
56 | + if (__libc_enable_secure) | ||
57 | + tunestr[off] = '\0'; | ||
58 | } | ||
59 | #endif | ||
60 | |||
61 | -- | ||
62 | 2.41.0 | ||
63 | |||
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 @@ | |||
2 | import sys | 2 | import sys |
3 | import os | 3 | import os |
4 | import subprocess | 4 | import subprocess |
5 | import resource | ||
5 | 6 | ||
6 | env = os.environ.copy() | 7 | env = os.environ.copy() |
7 | args = sys.argv[1:] | 8 | args = sys.argv[1:] |
@@ -44,12 +45,20 @@ if targettype == "user": | |||
44 | qemuargs += ["-L", sysroot] | 45 | qemuargs += ["-L", sysroot] |
45 | qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))] | 46 | qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))] |
46 | command = qemuargs + args | 47 | command = qemuargs + args |
48 | |||
49 | # We've seen qemu-arm using up all system memory for some glibc | ||
50 | # tests e.g. nptl/tst-pthread-timedlock-lockloop | ||
51 | # Cap at 8GB since no test should need more than that | ||
52 | # (5GB adds 7 failures for qemuarm glibc test run) | ||
53 | limit = 8*1024*1024*1024 | ||
54 | resource.setrlimit(resource.RLIMIT_AS, (limit, limit)) | ||
55 | |||
47 | elif targettype == "ssh": | 56 | elif targettype == "ssh": |
48 | host = os.environ.get("SSH_HOST", None) | 57 | host = os.environ.get("SSH_HOST", None) |
49 | user = os.environ.get("SSH_HOST_USER", None) | 58 | user = os.environ.get("SSH_HOST_USER", None) |
50 | port = os.environ.get("SSH_HOST_PORT", None) | 59 | port = os.environ.get("SSH_HOST_PORT", None) |
51 | 60 | ||
52 | command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"] | 61 | command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=quiet"] |
53 | if port: | 62 | if port: |
54 | command += ["-p", str(port)] | 63 | command += ["-p", str(port)] |
55 | if not host: | 64 | if not host: |
diff --git a/meta/recipes-core/glibc/glibc_2.31.bb b/meta/recipes-core/glibc/glibc_2.31.bb index b75bbb4196..296c892994 100644 --- a/meta/recipes-core/glibc/glibc_2.31.bb +++ b/meta/recipes-core/glibc/glibc_2.31.bb | |||
@@ -1,7 +1,40 @@ | |||
1 | require glibc.inc | 1 | require glibc.inc |
2 | require glibc-version.inc | 2 | require glibc-version.inc |
3 | 3 | ||
4 | CVE_CHECK_WHITELIST += "CVE-2020-10029 CVE-2020-6096 CVE-2016-10228 CVE-2020-1751 CVE-2020-1752" | 4 | CVE_CHECK_WHITELIST += "CVE-2020-10029 CVE-2020-6096 CVE-2016-10228 CVE-2020-1751 CVE-2020-1752 \ |
5 | CVE-2021-27645 CVE-2021-3326 CVE-2020-27618 CVE-2020-29562 CVE-2019-25013 \ | ||
6 | CVE-2022-23218 CVE-2022-23219 \ | ||
7 | " | ||
8 | |||
9 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010022 | ||
10 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010023 | ||
11 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010024 | ||
12 | # Upstream glibc maintainers dispute there is any issue and have no plans to address it further. | ||
13 | # "this is being treated as a non-security bug and no real threat." | ||
14 | CVE_CHECK_WHITELIST += "CVE-2019-1010022 CVE-2019-1010023 CVE-2019-1010024" | ||
15 | |||
16 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010025 | ||
17 | # Allows for ASLR bypass so can bypass some hardening, not an exploit in itself, may allow | ||
18 | # easier access for another. "ASLR bypass itself is not a vulnerability." | ||
19 | # Potential patch at https://sourceware.org/bugzilla/show_bug.cgi?id=22853 | ||
20 | CVE_CHECK_WHITELIST += "CVE-2019-1010025" | ||
21 | |||
22 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-35942 | ||
23 | # The wordexp function in the GNU C Library (aka glibc) through 2.33 may crash | ||
24 | # or read arbitrary memory in parse_param (in posix/wordexp.c) when called with | ||
25 | # an untrusted, crafted pattern, potentially resulting in a denial of service | ||
26 | # or disclosure of information. Patch was backported to 2.31 branch already: | ||
27 | # https://sourceware.org/git/?p=glibc.git;a=commit;h=4f0a61f75385c9a5879cbe7202042e88f692a3c8 | ||
28 | # which is already included in the dunfell branch of poky: | ||
29 | # https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?h=dunfell&id=e1e89ff7d75c3d2223f9e3bd875b9b0c5e15836b | ||
30 | CVE_CHECK_WHITELIST += "CVE-2021-35942" | ||
31 | |||
32 | # glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2023-4527 | ||
33 | # This vulnerability was introduced in 2.36 by commit | ||
34 | # f282cdbe7f436c75864e5640a409a10485e9abb2 resolv: Implement no-aaaa stub resolver option | ||
35 | # so our version is not yet vulnerable | ||
36 | # See https://sourceware.org/bugzilla/show_bug.cgi?id=30842 | ||
37 | CVE_CHECK_WHITELIST += "CVE-2023-4527" | ||
5 | 38 | ||
6 | DEPENDS += "gperf-native bison-native make-native" | 39 | DEPENDS += "gperf-native bison-native make-native" |
7 | 40 | ||
@@ -41,9 +74,21 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ | |||
41 | file://0027-intl-Emit-no-lines-in-bison-generated-files.patch \ | 74 | file://0027-intl-Emit-no-lines-in-bison-generated-files.patch \ |
42 | file://0028-inject-file-assembly-directives.patch \ | 75 | file://0028-inject-file-assembly-directives.patch \ |
43 | file://0029-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch \ | 76 | file://0029-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch \ |
44 | file://CVE-2020-29562.patch \ | ||
45 | file://CVE-2020-29573.patch \ | 77 | file://CVE-2020-29573.patch \ |
46 | file://CVE-2019-25013.patch \ | 78 | file://CVE-2021-33574_1.patch \ |
79 | file://CVE-2021-33574_2.patch \ | ||
80 | file://CVE-2021-38604.patch \ | ||
81 | file://0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch \ | ||
82 | file://0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch \ | ||
83 | file://0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch \ | ||
84 | file://0033-elf-Add-test-case-for-BZ-19329.patch \ | ||
85 | file://0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch \ | ||
86 | file://0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \ | ||
87 | file://0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \ | ||
88 | file://0037-Avoid-deadlock-between-pthread_create-and-ctors.patch \ | ||
89 | file://CVE-2023-0687.patch \ | ||
90 | file://CVE-2023-4911.patch \ | ||
91 | file://CVE-2023-4813.patch \ | ||
47 | " | 92 | " |
48 | S = "${WORKDIR}/git" | 93 | S = "${WORKDIR}/git" |
49 | B = "${WORKDIR}/build-${TARGET_SYS}" | 94 | B = "${WORKDIR}/build-${TARGET_SYS}" |
diff --git a/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch b/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch index 52986e61c7..d1835c7a10 100644 --- a/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch +++ b/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch | |||
@@ -400,7 +400,7 @@ Index: ldconfig-native-2.12.1/ldconfig.c | |||
400 | return 0; | 400 | return 0; |
401 | } | 401 | } |
402 | 402 | ||
403 | +#define REPORT_BUGS_TO "mailing list : poky@yoctoproject.org" | 403 | +#define REPORT_BUGS_TO "mailing list : poky@lists.yoctoproject.org" |
404 | /* Print bug-reporting information in the help message. */ | 404 | /* Print bug-reporting information in the help message. */ |
405 | static char * | 405 | static char * |
406 | more_help (int key, const char *text, void *input) | 406 | more_help (int key, const char *text, void *input) |