Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit af251b9

Browse files
committedJul 28, 2022
Protect preopens.c against concurrent access
1 parent 23a4b6e commit af251b9

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed
 

‎libc-bottom-half/sources/preopens.c

+15-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22
//! environment, with associated path prefixes, which can be used to map
33
//! absolute paths to capabilities with relative paths.
44

5-
#ifdef _REENTRANT
6-
//#error "__wasilibc_register_preopened_fd doesn't yet support multiple threads"
7-
#endif
8-
95
#include <assert.h>
106
#include <errno.h>
117
#include <fcntl.h>
128
#include <limits.h>
9+
#include <lock.h>
1310
#include <stdbool.h>
1411
#include <stdlib.h>
1512
#include <string.h>
@@ -32,6 +29,10 @@ static preopen *preopens;
3229
static size_t num_preopens;
3330
static size_t preopen_capacity;
3431

32+
/// Access to the the above preopen must be protected in the presence of
33+
/// threads.
34+
static volatile int lock[1];
35+
3536
#ifdef NDEBUG
3637
#define assert_invariants() // assertions disabled
3738
#else
@@ -55,13 +56,15 @@ static void assert_invariants(void) {
5556

5657
/// Allocate space for more preopens. Returns 0 on success and -1 on failure.
5758
static int resize(void) {
59+
LOCK(lock);
5860
size_t start_capacity = 4;
5961
size_t old_capacity = preopen_capacity;
6062
size_t new_capacity = old_capacity == 0 ? start_capacity : old_capacity * 2;
6163

6264
preopen *old_preopens = preopens;
6365
preopen *new_preopens = calloc(sizeof(preopen), new_capacity);
6466
if (new_preopens == NULL)
67+
UNLOCK(lock);
6568
return -1;
6669

6770
memcpy(new_preopens, old_preopens, num_preopens * sizeof(preopen));
@@ -70,6 +73,7 @@ static int resize(void) {
7073
free(old_preopens);
7174

7275
assert_invariants();
76+
UNLOCK(lock);
7377
return 0;
7478
}
7579

@@ -97,21 +101,26 @@ static const char *strip_prefixes(const char *path) {
97101
///
98102
/// This function takes ownership of `prefix`.
99103
static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) {
104+
LOCK(lock);
105+
100106
// Check preconditions.
101107
assert_invariants();
102108
assert(fd != AT_FDCWD);
103109
assert(fd != -1);
104110
assert(relprefix != NULL);
105111

106112
if (num_preopens == preopen_capacity && resize() != 0)
113+
UNLOCK(lock);
107114
return -1;
108115

109116
char *prefix = strdup(strip_prefixes(relprefix));
110117
if (prefix == NULL)
118+
UNLOCK(lock);
111119
return -1;
112120
preopens[num_preopens++] = (preopen) { prefix, fd, };
113121

114122
assert_invariants();
123+
UNLOCK(lock);
115124
return 0;
116125
}
117126

@@ -166,6 +175,7 @@ int __wasilibc_find_abspath(const char *path,
166175
// recently added preopens take precedence over less recently addded ones.
167176
size_t match_len = 0;
168177
int fd = -1;
178+
LOCK(lock);
169179
for (size_t i = num_preopens; i > 0; --i) {
170180
const preopen *pre = &preopens[i - 1];
171181
const char *prefix = pre->prefix;
@@ -182,6 +192,7 @@ int __wasilibc_find_abspath(const char *path,
182192
*abs_prefix = prefix;
183193
}
184194
}
195+
UNLOCK(lock);
185196

186197
if (fd == -1) {
187198
errno = ENOENT;

0 commit comments

Comments
 (0)
Please sign in to comment.