diff --git a/deps/uvwasi/include/fd_table.h b/deps/uvwasi/include/fd_table.h index 23a3bf52f42c8b..9d88628e22c62d 100644 --- a/deps/uvwasi/include/fd_table.h +++ b/deps/uvwasi/include/fd_table.h @@ -46,11 +46,16 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_s* uvwasi, const uv_file fd, const char* path, const char* real_path); -uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table, +uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table, const uvwasi_fd_t id, struct uvwasi_fd_wrap_t** wrap, uvwasi_rights_t rights_base, uvwasi_rights_t rights_inheriting); +uvwasi_errno_t uvwasi_fd_table_get_nolock(struct uvwasi_fd_table_t* table, + const uvwasi_fd_t id, + struct uvwasi_fd_wrap_t** wrap, + uvwasi_rights_t rights_base, + uvwasi_rights_t rights_inheriting); uvwasi_errno_t uvwasi_fd_table_remove(struct uvwasi_s* uvwasi, struct uvwasi_fd_table_t* table, const uvwasi_fd_t id); @@ -58,5 +63,7 @@ uvwasi_errno_t uvwasi_fd_table_renumber(struct uvwasi_s* uvwasi, struct uvwasi_fd_table_t* table, const uvwasi_fd_t dst, const uvwasi_fd_t src); +uvwasi_errno_t uvwasi_fd_table_lock(struct uvwasi_fd_table_t* table); +uvwasi_errno_t uvwasi_fd_table_unlock(struct uvwasi_fd_table_t* table); #endif /* __UVWASI_FD_TABLE_H__ */ diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index e4897769d987e1..c15ea09257506c 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -252,44 +252,57 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi, } -uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table, +uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table, const uvwasi_fd_t id, struct uvwasi_fd_wrap_t** wrap, uvwasi_rights_t rights_base, uvwasi_rights_t rights_inheriting) { - struct uvwasi_fd_wrap_t* entry; uvwasi_errno_t err; - if (table == NULL || wrap == NULL) + if (table == NULL) return UVWASI_EINVAL; - uv_rwlock_rdlock((uv_rwlock_t *)&table->rwlock); + uv_rwlock_wrlock(&table->rwlock); + err = uvwasi_fd_table_get_nolock(table, + id, + wrap, + rights_base, + rights_inheriting); + uv_rwlock_wrunlock(&table->rwlock); + return err; +} - if (id >= table->size) { - err = UVWASI_EBADF; - goto exit; - } + +/* uvwasi_fd_table_get_nolock() retrieves a file descriptor and locks its mutex, + but does not lock the file descriptor table like uvwasi_fd_table_get() does. +*/ +uvwasi_errno_t uvwasi_fd_table_get_nolock(struct uvwasi_fd_table_t* table, + const uvwasi_fd_t id, + struct uvwasi_fd_wrap_t** wrap, + uvwasi_rights_t rights_base, + uvwasi_rights_t rights_inheriting) { + struct uvwasi_fd_wrap_t* entry; + + if (table == NULL || wrap == NULL) + return UVWASI_EINVAL; + + if (id >= table->size) + return UVWASI_EBADF; entry = table->fds[id]; - if (entry == NULL || entry->id != id) { - err = UVWASI_EBADF; - goto exit; - } + if (entry == NULL || entry->id != id) + return UVWASI_EBADF; /* Validate that the fd has the necessary rights. */ if ((~entry->rights_base & rights_base) != 0 || (~entry->rights_inheriting & rights_inheriting) != 0) { - err = UVWASI_ENOTCAPABLE; - goto exit; + return UVWASI_ENOTCAPABLE; } uv_mutex_lock(&entry->mutex); *wrap = entry; - err = UVWASI_ESUCCESS; -exit: - uv_rwlock_rdunlock((uv_rwlock_t *)&table->rwlock); - return err; + return UVWASI_ESUCCESS; } @@ -389,3 +402,21 @@ uvwasi_errno_t uvwasi_fd_table_renumber(struct uvwasi_s* uvwasi, uv_rwlock_wrunlock(&table->rwlock); return err; } + + +uvwasi_errno_t uvwasi_fd_table_lock(struct uvwasi_fd_table_t* table) { + if (table == NULL) + return UVWASI_EINVAL; + + uv_rwlock_wrlock(&table->rwlock); + return UVWASI_ESUCCESS; +} + + +uvwasi_errno_t uvwasi_fd_table_unlock(struct uvwasi_fd_table_t* table) { + if (table == NULL) + return UVWASI_EINVAL; + + uv_rwlock_wrunlock(&table->rwlock); + return UVWASI_ESUCCESS; +} diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index e4c2ac6e3b0dd1..9fa4db8a521111 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -1763,37 +1763,41 @@ uvwasi_errno_t uvwasi_path_link(uvwasi_t* uvwasi, if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; - if (old_fd == new_fd) { - err = uvwasi_fd_table_get(&uvwasi->fds, - old_fd, - &old_wrap, - UVWASI_RIGHT_PATH_LINK_SOURCE | - UVWASI_RIGHT_PATH_LINK_TARGET, - 0); - if (err != UVWASI_ESUCCESS) - return err; + uvwasi_fd_table_lock(&uvwasi->fds); + if (old_fd == new_fd) { + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + old_fd, + &old_wrap, + UVWASI_RIGHT_PATH_LINK_SOURCE | + UVWASI_RIGHT_PATH_LINK_TARGET, + 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get(&uvwasi->fds, - old_fd, - &old_wrap, - UVWASI_RIGHT_PATH_LINK_SOURCE, - 0); - if (err != UVWASI_ESUCCESS) - return err; - - err = uvwasi_fd_table_get(&uvwasi->fds, - new_fd, - &new_wrap, - UVWASI_RIGHT_PATH_LINK_TARGET, - 0); + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + old_fd, + &old_wrap, + UVWASI_RIGHT_PATH_LINK_SOURCE, + 0); if (err != UVWASI_ESUCCESS) { - uv_mutex_unlock(&old_wrap->mutex); + uvwasi_fd_table_unlock(&uvwasi->fds); return err; } + + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + new_fd, + &new_wrap, + UVWASI_RIGHT_PATH_LINK_TARGET, + 0); + if (err != UVWASI_ESUCCESS) + uv_mutex_unlock(&old_wrap->mutex); } + uvwasi_fd_table_unlock(&uvwasi->fds); + + if (err != UVWASI_ESUCCESS) + return err; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path, @@ -1922,12 +1926,11 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, } r = uv_fs_open(NULL, &req, resolved_path, flags, 0666, NULL); + uv_mutex_unlock(&dirfd_wrap->mutex); uv_fs_req_cleanup(&req); - if (r < 0) { - uv_mutex_unlock(&dirfd_wrap->mutex); + if (r < 0) return uvwasi__translate_uv_error(r); - } /* Not all platforms support UV_FS_O_DIRECTORY, so get the file type and check it here. */ @@ -1960,11 +1963,9 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, *fd = wrap->id; uv_mutex_unlock(&wrap->mutex); - uv_mutex_unlock(&dirfd_wrap->mutex); return UVWASI_ESUCCESS; close_file_and_error_exit: - uv_mutex_unlock(&dirfd_wrap->mutex); uv_fs_close(NULL, &req, r, NULL); uv_fs_req_cleanup(&req); return err; @@ -2079,36 +2080,41 @@ uvwasi_errno_t uvwasi_path_rename(uvwasi_t* uvwasi, if (uvwasi == NULL || old_path == NULL || new_path == NULL) return UVWASI_EINVAL; + uvwasi_fd_table_lock(&uvwasi->fds); + if (old_fd == new_fd) { - err = uvwasi_fd_table_get(&uvwasi->fds, - old_fd, - &old_wrap, - UVWASI_RIGHT_PATH_RENAME_SOURCE | - UVWASI_RIGHT_PATH_RENAME_TARGET, - 0); - if (err != UVWASI_ESUCCESS) - return err; + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + old_fd, + &old_wrap, + UVWASI_RIGHT_PATH_RENAME_SOURCE | + UVWASI_RIGHT_PATH_RENAME_TARGET, + 0); new_wrap = old_wrap; } else { - err = uvwasi_fd_table_get(&uvwasi->fds, - old_fd, - &old_wrap, - UVWASI_RIGHT_PATH_RENAME_SOURCE, - 0); - if (err != UVWASI_ESUCCESS) - return err; - - err = uvwasi_fd_table_get(&uvwasi->fds, - new_fd, - &new_wrap, - UVWASI_RIGHT_PATH_RENAME_TARGET, - 0); + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + old_fd, + &old_wrap, + UVWASI_RIGHT_PATH_RENAME_SOURCE, + 0); if (err != UVWASI_ESUCCESS) { - uv_mutex_unlock(&old_wrap->mutex); + uvwasi_fd_table_unlock(&uvwasi->fds); return err; } + + err = uvwasi_fd_table_get_nolock(&uvwasi->fds, + new_fd, + &new_wrap, + UVWASI_RIGHT_PATH_RENAME_TARGET, + 0); + if (err != UVWASI_ESUCCESS) + uv_mutex_unlock(&old_wrap->mutex); } + uvwasi_fd_table_unlock(&uvwasi->fds); + + if (err != UVWASI_ESUCCESS) + return err; + err = uvwasi__resolve_path(uvwasi, old_wrap, old_path,