Skip to content

Commit aa9b5c0

Browse files
authored
Make make_absolute thread-local in chdir.c (#781)
`make_absolute` previously used a process-wide static buffer to assemble absolute paths for relative path resolution. In `_REENTRANT` builds, concurrent calls could overwrite or reallocate that shared buffer while another thread was still using it, leading to races and potentially invalid pointers. Related #474
1 parent d65bee2 commit aa9b5c0

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

libc-bottom-half/sources/chdir.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <errno.h>
22
#include <fcntl.h>
33
#include <limits.h>
4+
#include <lock.h>
45
#include <stdlib.h>
56
#include <string.h>
67
#include <sys/stat.h>
@@ -11,6 +12,7 @@
1112
#ifdef _REENTRANT
1213
void __wasilibc_cwd_lock(void);
1314
void __wasilibc_cwd_unlock(void);
15+
static volatile int lock[1];
1416
#else
1517
#define __wasilibc_cwd_lock() (void)0
1618
#define __wasilibc_cwd_unlock() (void)0
@@ -133,9 +135,12 @@ static const char *make_absolute(const char *path) {
133135
int __wasilibc_find_relpath_alloc(const char *path, const char **abs_prefix,
134136
char **relative_buf, size_t *relative_buf_len,
135137
int can_realloc) {
138+
LOCK(lock);
139+
136140
// First, make our path absolute taking the cwd into account.
137141
const char *abspath = make_absolute(path);
138142
if (abspath == NULL) {
143+
UNLOCK(lock);
139144
errno = ENOMEM;
140145
return -1;
141146
}
@@ -145,23 +150,28 @@ int __wasilibc_find_relpath_alloc(const char *path, const char **abs_prefix,
145150
// into `relative_buf`.
146151
const char *rel;
147152
int fd = __wasilibc_find_abspath(abspath, abs_prefix, &rel);
148-
if (fd == -1)
153+
if (fd == -1) {
154+
UNLOCK(lock);
149155
return -1;
156+
}
150157

151158
size_t rel_len = strlen(rel);
152159
if (*relative_buf_len < rel_len + 1) {
153160
if (!can_realloc) {
161+
UNLOCK(lock);
154162
errno = ERANGE;
155163
return -1;
156164
}
157165
char *tmp = realloc(*relative_buf, rel_len + 1);
158166
if (tmp == NULL) {
167+
UNLOCK(lock);
159168
errno = ENOMEM;
160169
return -1;
161170
}
162171
*relative_buf = tmp;
163172
*relative_buf_len = rel_len + 1;
164173
}
165174
strcpy(*relative_buf, rel);
175+
UNLOCK(lock);
166176
return fd;
167177
}

0 commit comments

Comments
 (0)