Skip to content

Commit f3107c2

Browse files
committed
memory_maps: move ia2_threads_metadata global definition to INIT_RUNTIME to have a once-mapped definition
Without this, `liblibia2.a` contains the `ia2_threads_metadata`, which is then linked into each compartment's `*.so`, causing each compartment to reference a different version of the global, causing lots of errors and segfaults. This also requires moving the type and other definitions from `memory_maps.{h,c}` to `ia2.h`.
1 parent 246bc74 commit f3107c2

File tree

4 files changed

+70
-45
lines changed

4 files changed

+70
-45
lines changed

runtime/libia2/include/ia2.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#endif
1313

1414
#include <errno.h>
15+
#include <pthread.h>
1516
#include <stdint.h>
1617
#include <unistd.h>
1718

@@ -190,6 +191,52 @@
190191
/// Convert a compartment pkey to a PKRU register value
191192
#define PKRU(pkey) (~((3U << (2 * pkey)) | 3))
192193

194+
// Moved `ia2_thread_metadata` from `memory_maps.h`
195+
// and `IA2_MAX_THREADS` and `ia2_all_threads_metadata`
196+
// from `memory_maps.c` to here
197+
// so that it can be used in `ia2_internal.h` within `_IA2_INIT_RUNTIME`
198+
// to only initialize the `ia2_threads_metadata` global once.
199+
200+
/// The data here is shared, so it should not be trusted for use as a pointer,
201+
/// but it can be used best effort for non-trusted purposes.
202+
struct ia2_thread_metadata {
203+
pid_t tid;
204+
pthread_t thread;
205+
206+
/// The start function passed to `pthread_create`.
207+
void *(*start_fn)(void *arg);
208+
209+
/// The addresses of each compartment's stack for this thread.
210+
uintptr_t stack_addrs[IA2_MAX_COMPARTMENTS];
211+
212+
/// The addresses of each compartment's TLS region for this thread,
213+
/// except for compartment 1, which has split TLS regions (see below).
214+
uintptr_t tls_addrs[IA2_MAX_COMPARTMENTS];
215+
216+
/// The TLS region is split only for the first compartment,
217+
/// so we need two addresses for just that one.
218+
///
219+
/// Compartment 1's TLS region is split because there is a page of
220+
/// unprotected data for `ia2_stackptr_0` (in compartment 0), plus padding,
221+
/// as we don't have a general implementation of shared TLS yet,
222+
/// but `ia2_stackptr_0` is special-cased for now
223+
/// as it must be stored in TLS and unprotected.
224+
uintptr_t tls_addr_compartment1_first;
225+
uintptr_t tls_addr_compartment1_second;
226+
};
227+
228+
// It's much simpler to only support a static number of created threads,
229+
// especially because we want to have very few dependencies.
230+
// If a program needs more threads, you can just increase this number.
231+
#define IA2_MAX_THREADS 512
232+
233+
struct ia2_all_threads_metadata {
234+
pthread_mutex_t lock;
235+
size_t num_threads;
236+
pid_t tids[IA2_MAX_THREADS];
237+
struct ia2_thread_metadata thread_metadata[IA2_MAX_THREADS];
238+
};
239+
193240
#ifdef __cplusplus
194241
extern "C" {
195242
#endif

runtime/libia2/include/ia2_internal.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,19 @@ __attribute__((__noreturn__)) void ia2_reinit_stack_err(int i);
439439
\
440440
void ia2_setup_destructors(void) { \
441441
REPEATB##n(setup_destructors_for_compartment, nop_macro); \
442-
}
442+
} \
443+
\
444+
/* Moved `ia2_threads_metadata` from `memory_maps.c` to here */ \
445+
/* so that it can be used in `_IA2_INIT_RUNTIME` */ \
446+
/* to only initialize the `ia2_threads_metadata` global once. */ \
447+
\
448+
/* All zeroed, so this should go in `.bss` */ \
449+
/* and only have pages lazily allocated. */ \
450+
struct ia2_all_threads_metadata ia2_threads_metadata IA2_SHARED_DATA = { \
451+
.lock = PTHREAD_MUTEX_INITIALIZER, \
452+
.num_threads = 0, \
453+
.thread_metadata = {0}, \
454+
};
443455

444456
#if IA2_VERBOSE
445457
#define ia2_log(fmt, ...) fprintf(stdout, "%s: " fmt, __func__, ##__VA_ARGS__)

runtime/libia2/memory_maps.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,9 @@
66
// This reduces the trusted codebase and avoids runtime overhead.
77
#if IA2_DEBUG_MEMORY
88

9-
// It's much simpler to only support a static number of created threads,
10-
// especially because we want to have very few dependencies.
11-
// If a program needs more threads, you can just increase this number.
12-
#define IA2_MAX_THREADS 512
13-
14-
struct ia2_all_threads_metadata {
15-
pthread_mutex_t lock;
16-
size_t num_threads;
17-
pid_t tids[IA2_MAX_THREADS];
18-
struct ia2_thread_metadata thread_metadata[IA2_MAX_THREADS];
19-
};
9+
// Moved `IA2_MAX_THREADS` and `ia2_all_threads_metadata` from here to `ia2.h`
10+
// so that it can be used in `ia2_internal.h` within `_IA2_INIT_RUNTIME`
11+
// to only initialize the `ia2_threads_metadata` global once.
2012

2113
#define array_len(a) (sizeof(a) / sizeof(*(a)))
2214

@@ -101,12 +93,10 @@ struct ia2_addr_location ia2_all_threads_metadata_find_addr(struct ia2_all_threa
10193
return location;
10294
}
10395

104-
// All zeroed, so this should go in `.bss` and only have pages lazily allocated.
105-
static struct ia2_all_threads_metadata IA2_SHARED_DATA ia2_threads_metadata = {
106-
.lock = PTHREAD_MUTEX_INITIALIZER,
107-
.num_threads = 0,
108-
.thread_metadata = {0},
109-
};
96+
// Moved `ia2_threads_metadata` from here to `ia2_internal.h`
97+
// so that it can be used in `_IA2_INIT_RUNTIME`
98+
// to only initialize the `ia2_threads_metadata` global once.
99+
extern struct ia2_all_threads_metadata ia2_threads_metadata;
110100

111101
struct ia2_thread_metadata *ia2_thread_metadata_get_current_thread(void) {
112102
return ia2_all_threads_metadata_lookup(&ia2_threads_metadata);

runtime/libia2/memory_maps.h

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,9 @@
99
// This reduces the trusted codebase and avoids runtime overhead.
1010
#if IA2_DEBUG_MEMORY
1111

12-
/// The data here is shared, so it should not be trusted for use as a pointer,
13-
/// but it can be used best effort for non-trusted purposes.
14-
struct ia2_thread_metadata {
15-
pid_t tid;
16-
pthread_t thread;
17-
18-
/// The start function passed to `pthread_create`.
19-
void *(*start_fn)(void *arg);
20-
21-
/// The addresses of each compartment's stack for this thread.
22-
uintptr_t stack_addrs[IA2_MAX_COMPARTMENTS];
23-
24-
/// The addresses of each compartment's TLS region for this thread,
25-
/// except for compartment 1, which has split TLS regions (see below).
26-
uintptr_t tls_addrs[IA2_MAX_COMPARTMENTS];
27-
28-
/// The TLS region is split only for the first compartment,
29-
/// so we need two addresses for just that one.
30-
///
31-
/// Compartment 1's TLS region is split because there is a page of
32-
/// unprotected data for `ia2_stackptr_0` (in compartment 0), plus padding,
33-
/// as we don't have a general implementation of shared TLS yet,
34-
/// but `ia2_stackptr_0` is special-cased for now
35-
/// as it must be stored in TLS and unprotected.
36-
uintptr_t tls_addr_compartment1_first;
37-
uintptr_t tls_addr_compartment1_second;
38-
};
12+
// Moved `ia2_thread_metadata` from here to `ia2.h`
13+
// so that it can be used in `ia2_internal.h` within `_IA2_INIT_RUNTIME`
14+
// to only initialize the `ia2_threads_metadata` global once.
3915

4016
/// Find the `struct ia2_thread_metadata*` for the current thread,
4117
/// adding (but not allocating) one if there isn't one yet.

0 commit comments

Comments
 (0)