Skip to content

Commit 19fe7d7

Browse files
authored
Support al2 (#14)
* Support AL2 as another patched platform * Support AL2 as another patched platform * Support AL2 as another patched platform * Updated patches that include backporting BZ17645 as well --------- Authored-by: Jos Martin <[email protected]>
1 parent 6e38d6a commit 19fe7d7

8 files changed

+1426
-0
lines changed

Dockerfile.al2

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2025 The MathWorks, Inc.
2+
ARG BUILD_ROOT=/root/
3+
ARG RPM_DIR=${BUILD_ROOT}/rpmbuild/RPMS/x86_64/
4+
5+
ARG ARCH=
6+
ARG DIST_BASE=amazonlinux
7+
ARG DIST_TAG=2
8+
FROM ${DIST_BASE}:${DIST_TAG} AS build-stage
9+
10+
RUN yum install -y rpm-build make yum-utils
11+
12+
ARG BUILD_ROOT
13+
WORKDIR ${BUILD_ROOT}
14+
15+
RUN yumdownloader --source glibc && \
16+
yum-builddep -y glibc-*.src.rpm && \
17+
rpm -ivh glibc-*.src.rpm
18+
19+
ARG GLIBC_VERSION=2.26
20+
COPY scripts/update-specfile-al2.sh ${BUILD_ROOT}
21+
COPY patches/al2/${GLIBC_VERSION} ${BUILD_ROOT}/patches
22+
23+
RUN cp patches/* rpmbuild/SOURCES && \
24+
./update-specfile-al2.sh
25+
26+
RUN rpmbuild --nocheck -bb rpmbuild/SPECS/glibc.spec
27+
28+
ARG RPM_DIR
29+
WORKDIR ${RPM_DIR}
30+
31+
RUN tar -czf all-packages.tar.gz *.rpm
32+
33+
FROM scratch AS release-stage
34+
ARG RPM_DIR
35+
COPY --from=build-stage ${RPM_DIR}/*.rpm /build/
36+
COPY --from=build-stage ${RPM_DIR}/all-packages.tar.gz /build/

Dockerfile.centos

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2025 The MathWorks, Inc.
2+
# This Dockerfile is still a work in progress and may not work
3+
ARG BUILD_ROOT=/root/
4+
ARG RPM_DIR=${BUILD_ROOT}/rpmbuild/RPMS/x86_64/
5+
6+
ARG ARCH=
7+
ARG DIST_BASE=centos
8+
ARG DIST_TAG=centos7.9.2009
9+
FROM ${DIST_BASE}:${DIST_TAG} AS build-stage
10+
11+
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS-*.repo && \
12+
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS-*.repo && \
13+
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS-*.repo
14+
15+
RUN yum install -y epel-release && \
16+
yum install -y dnf
17+
18+
RUN dnf install -y --nodocs dnf-plugins-core && \
19+
dnf install -y rpm-build make
20+
21+
ARG BUILD_ROOT
22+
WORKDIR ${BUILD_ROOT}
23+
24+
RUN dnf download --source glibc && \
25+
dnf builddep -y --nodocs glibc-*.src.rpm && \
26+
rpm -ivh glibc-*.src.rpm
27+
28+
ARG GLIBC_VERSION=2.17
29+
COPY scripts/update-specfile.sh ${BUILD_ROOT}
30+
COPY patches/rhel/${GLIBC_VERSION} ${BUILD_ROOT}/patches
31+
32+
RUN cp patches/* rpmbuild/SOURCES && \
33+
./update-specfile.sh
34+
35+
RUN rpmbuild --nocheck -bb rpmbuild/SPECS/glibc.spec
36+
37+
ARG RPM_DIR
38+
WORKDIR ${RPM_DIR}
39+
40+
RUN tar -czf all-packages.tar.gz *.rpm
41+
42+
FROM scratch AS release-stage
43+
ARG RPM_DIR
44+
COPY --from=build-stage ${RPM_DIR}/*.rpm /build/
45+
COPY --from=build-stage ${RPM_DIR}/all-packages.tar.gz /build/
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
From ef6eb8f97d4ebfbb471bdd8d37455f2dadf507a3 Mon Sep 17 00:00:00 2001
2+
From: Szabolcs Nagy <szabolcs dot nagy at arm dot com>
3+
Date: Wed, 30 Nov 2016 11:44:25 +0000
4+
Subject: [PATCH 1/5] remove broken code path for easier code review
5+
6+
This patch is not necessary for the bug fix, just makes concurrency
7+
code review easier (removes a data race and overflow from a broken
8+
code path).
9+
10+
dlopen can oom crash anyway in _dl_resize_dtv and it's probably
11+
better to crash than leave half setup modules around.
12+
13+
2016-11-30 Szabolcs Nagy <[email protected]>
14+
15+
* elf/dl-tls.c (_dl_add_to_slotinfo): OOM crash.
16+
---
17+
elf/dl-tls.c | 16 ++++------------
18+
1 file changed, 4 insertions(+), 12 deletions(-)
19+
20+
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
21+
index 5aba33b3fa..4daf88af6e 100644
22+
--- a/elf/dl-tls.c
23+
+++ b/elf/dl-tls.c
24+
@@ -927,18 +927,10 @@ _dl_add_to_slotinfo (struct link_map *l)
25+
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
26+
if (listp == NULL)
27+
{
28+
- /* We ran out of memory. We will simply fail this
29+
- call but don't undo anything we did so far. The
30+
- application will crash or be terminated anyway very
31+
- soon. */
32+
-
33+
- /* We have to do this since some entries in the dtv
34+
- slotinfo array might already point to this
35+
- generation. */
36+
- ++GL(dl_tls_generation);
37+
-
38+
- _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\
39+
-cannot create TLS data structures"));
40+
+ /* We ran out of memory in dlopen while updating tls structures.
41+
+ TODO: side-effects should be rolled back and the failure should
42+
+ be reported to the caller, but that's hard. */
43+
+ oom ();
44+
}
45+
46+
listp->len = TLS_SLOTINFO_SURPLUS;
47+
--
48+
2.39.5
49+
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
From b65f2c16f389d82b54404df97eed838630b1ee90 Mon Sep 17 00:00:00 2001
2+
From: Szabolcs Nagy <szabolcs dot nagy at arm dot com>
3+
Date: Wed, 30 Nov 2016 11:44:32 +0000
4+
Subject: [PATCH 2/5] Fix data races between pthread_create and dlopen
5+
6+
This fixes a subset of the issues described in
7+
https://sourceware.org/ml/libc-alpha/2016-11/msg01026.html
8+
without adding locks to pthread_create.
9+
10+
Only races between dlopen and pthread_create were considered,
11+
and the asserts got removed that tried to check for concurrency
12+
issues.
13+
14+
The patch is incomplete because dlclose, tls access and
15+
dl_iterate_phdr related code paths are not modified.
16+
17+
dlclose should be updated in a similar fashion to dlopen
18+
to make the patch complete alternatively pthread_create
19+
may take the GL(dl_load_write_lock) to sync with dlclose
20+
or the GL(dl_load_lock) to sync with dlopen and dlclose
21+
(that would simplify the concurrency design, but increase
22+
lock contention on the locks).
23+
24+
2016-11-30 Szabolcs Nagy <[email protected]>
25+
26+
[BZ #19329]
27+
* elf/dl-open.c (dl_open_worker): Write GL(dl_tls_generation)
28+
atomically.
29+
* elf/dl-tls.c (_dl_allocate_tls_init): Read GL(dl_tls_generation),
30+
GL(dl_tls_max_dtv_idx), slotinfo entries and listp->next atomically.
31+
Remove assertions that cannot be guaranteed.
32+
(_dl_add_to_slotinfo): Write the slotinfo entries and listp->next
33+
atomically.
34+
---
35+
elf/dl-open.c | 12 +++++--
36+
elf/dl-tls.c | 87 ++++++++++++++++++++++++++++++++++++++++++++-------
37+
2 files changed, 86 insertions(+), 13 deletions(-)
38+
39+
diff --git a/elf/dl-open.c b/elf/dl-open.c
40+
index cec54db413..a45319e5fc 100644
41+
--- a/elf/dl-open.c
42+
+++ b/elf/dl-open.c
43+
@@ -524,9 +524,17 @@ dl_open_worker (void *a)
44+
}
45+
46+
/* Bump the generation number if necessary. */
47+
- if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
48+
- _dl_fatal_printf (N_("\
49+
+ if (any_tls)
50+
+ {
51+
+ /* This cannot be in a data-race so non-atomic load is valid too. */
52+
+ size_t newgen = atomic_load_relaxed (&GL(dl_tls_generation)) + 1;
53+
+ /* Synchronize with _dl_allocate_tls_init (see notes there) and
54+
+ avoid storing an overflowed counter. */
55+
+ if (__builtin_expect (newgen == 0, 0))
56+
+ _dl_fatal_printf (N_("\
57+
TLS generation counter wrapped! Please report this."));
58+
+ atomic_store_release (&GL(dl_tls_generation), newgen);
59+
+ }
60+
61+
/* We need a second pass for static tls data, because _dl_update_slotinfo
62+
must not be run while calls to _dl_add_to_slotinfo are still pending. */
63+
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
64+
index 4daf88af6e..c60bbd72ea 100644
65+
--- a/elf/dl-tls.c
66+
+++ b/elf/dl-tls.c
67+
@@ -438,6 +438,36 @@ _dl_resize_dtv (dtv_t *dtv)
68+
}
69+
70+
71+
+/*
72+
+CONCURRENCY NOTES
73+
+
74+
+dlopen (and dlclose) holds the GL(dl_load_lock) while writing shared state,
75+
+which may be concurrently read by pthread_create and tls access without taking
76+
+the lock, so atomic access should be used. The shared state:
77+
+
78+
+ GL(dl_tls_max_dtv_idx) - max modid assigned, (modid can be reused).
79+
+ GL(dl_tls_generation) - generation count, incremented by dlopen and dlclose.
80+
+ GL(dl_tls_dtv_slotinfo_list) - list of entries, contains generation count
81+
+ and link_map for each module with a modid.
82+
+
83+
+A module gets a modid assigned if it has tls, a modid identifies a slotinfo
84+
+entry and it is the index of the corresponding dtv slot. The generation count
85+
+is assigned to slotinfo entries of a newly loaded or unloaded module and its
86+
+newly loaded or unloaded dependencies.
87+
+
88+
+TODO: dlclose may free memory read by a concurrent pthread_create or tls
89+
+access. This is broken now, so it is assumed that dlclose does not free
90+
+link_map structures while pthread_create or __tls_get_addr is reading them.
91+
+
92+
+pthread_create calls _dl_allocate_tls_init (before creating the new thread),
93+
+which should guarantee that the dtv is in a consistent state at the end:
94+
+
95+
+All slotinfo updates with generation <= dtv[0].counter are reflected in the
96+
+dtv and arbitrary later module unloads may also be reflected as unallocated
97+
+entries. (Note: a modid reuse implies a module unload and accessing tls in
98+
+an unloaded module is undefined.)
99+
+*/
100+
+
101+
void *
102+
internal_function
103+
_dl_allocate_tls_init (void *result)
104+
@@ -450,12 +480,24 @@ _dl_allocate_tls_init (void *result)
105+
struct dtv_slotinfo_list *listp;
106+
size_t total = 0;
107+
size_t maxgen = 0;
108+
+ /* Synchronizes with the increments in dl_{open,close}_worker.
109+
+ Slotinfo updates of this generation are sequenced before the
110+
+ write we read from here. */
111+
+ size_t gen_count = atomic_load_acquire (&GL(dl_tls_generation));
112+
+ /* Either reads from the last write that is sequenced before the
113+
+ generation counter increment we synchronized with or a write
114+
+ made by a later dlopen/dlclose. dlclose may decrement this,
115+
+ but only if related modules are unloaded. So it is an upper
116+
+ bound on non-unloaded modids up to gen_count generation. */
117+
+ size_t dtv_slots = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
118+
119+
/* Check if the current dtv is big enough. */
120+
- if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
121+
+ if (dtv[-1].counter < dtv_slots)
122+
{
123+
/* Resize the dtv. */
124+
dtv = _dl_resize_dtv (dtv);
125+
+ /* _dl_resize_dtv rereads GL(dl_tls_max_dtv_idx) which may decrease. */
126+
+ dtv_slots = dtv[-1].counter;
127+
128+
/* Install this new dtv in the thread data structures. */
129+
INSTALL_DTV (result, &dtv[-1]);
130+
@@ -472,22 +514,33 @@ _dl_allocate_tls_init (void *result)
131+
for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
132+
{
133+
struct link_map *map;
134+
+ size_t gen;
135+
void *dest;
136+
137+
/* Check for the total number of used slots. */
138+
- if (total + cnt > GL(dl_tls_max_dtv_idx))
139+
+ if (total + cnt > dtv_slots)
140+
break;
141+
142+
- map = listp->slotinfo[cnt].map;
143+
+ /* Synchronize with dl_add_to_slotinfo and remove_slotinfo. */
144+
+ map = atomic_load_acquire (&listp->slotinfo[cnt].map);
145+
if (map == NULL)
146+
/* Unused entry. */
147+
continue;
148+
149+
+ /* Consistent generation count with the map read above.
150+
+ Inconsistent gen may be read if the entry is being reused,
151+
+ in which case it is larger than gen_count and we skip it. */
152+
+ gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen);
153+
+ if (gen > gen_count)
154+
+ /* New entry. */
155+
+ continue;
156+
+
157+
/* Keep track of the maximum generation number. This might
158+
not be the generation counter. */
159+
- assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
160+
- maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
161+
+ maxgen = MAX (maxgen, gen);
162+
163+
+ /* TODO: concurrent dlclose may free map which would break
164+
+ the rest of the code below. */
165+
dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
166+
dtv[map->l_tls_modid].pointer.to_free = NULL;
167+
168+
@@ -517,11 +570,15 @@ _dl_allocate_tls_init (void *result)
169+
}
170+
171+
total += cnt;
172+
- if (total >= GL(dl_tls_max_dtv_idx))
173+
+ if (total >= dtv_slots)
174+
break;
175+
176+
- listp = listp->next;
177+
- assert (listp != NULL);
178+
+ /* Synchronize with dl_add_to_slotinfo. */
179+
+ listp = atomic_load_acquire (&listp->next);
180+
+ /* dtv_slots is an upper bound on the number of entries we care
181+
+ about, the list may end sooner. */
182+
+ if (listp == NULL)
183+
+ break;
184+
}
185+
186+
/* The DTV version is up-to-date now. */
187+
@@ -922,7 +979,7 @@ _dl_add_to_slotinfo (struct link_map *l)
188+
the first slot. */
189+
assert (idx == 0);
190+
191+
- listp = prevp->next = (struct dtv_slotinfo_list *)
192+
+ listp = (struct dtv_slotinfo_list *)
193+
malloc (sizeof (struct dtv_slotinfo_list)
194+
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
195+
if (listp == NULL)
196+
@@ -937,9 +994,17 @@ _dl_add_to_slotinfo (struct link_map *l)
197+
listp->next = NULL;
198+
memset (listp->slotinfo, '\0',
199+
TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
200+
+ /* Add the new list item and synchronize with _dl_allocate_tls_init. */
201+
+ atomic_store_release (&prevp->next, listp);
202+
}
203+
204+
/* Add the information into the slotinfo data structure. */
205+
- listp->slotinfo[idx].map = l;
206+
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
207+
+
208+
+ /* This cannot be in a data-race so non-atomic load would be valid too. */
209+
+ size_t newgen = atomic_load_relaxed (&GL(dl_tls_generation)) + 1;
210+
+ /* TODO: Concurrent readers may see an overflowed gen, which is bad,
211+
+ but overflow is guaranteed to crash the dlopen that is executing. */
212+
+ atomic_store_relaxed (&listp->slotinfo[idx].gen, newgen);
213+
+ /* Synchronize with _dl_allocate_tls_init (see notes there). */
214+
+ atomic_store_release (&listp->slotinfo[idx].map, l);
215+
}
216+
--
217+
2.39.5
218+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
From 82a104f513447ebcf0e43ad6f0a49fdfeff2a48b Mon Sep 17 00:00:00 2001
2+
From: Mike Gulick <[email protected]>
3+
Date: Wed, 15 Jan 2025 19:10:55 -0500
4+
Subject: [PATCH 3/5] BZ19329 fixup
5+
6+
---
7+
elf/dl-tls.c | 2 +-
8+
1 file changed, 1 insertion(+), 1 deletion(-)
9+
10+
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
11+
index c60bbd72ea..305eae3d6d 100644
12+
--- a/elf/dl-tls.c
13+
+++ b/elf/dl-tls.c
14+
@@ -570,7 +570,7 @@ _dl_allocate_tls_init (void *result)
15+
}
16+
17+
total += cnt;
18+
- if (total >= dtv_slots)
19+
+ if (total > dtv_slots)
20+
break;
21+
22+
/* Synchronize with dl_add_to_slotinfo. */
23+
--
24+
2.39.5
25+

0 commit comments

Comments
 (0)