Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion include/fd_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,24 @@ 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);
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__ */
67 changes: 49 additions & 18 deletions src/fd_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down Expand Up @@ -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;
}
106 changes: 56 additions & 50 deletions src/uvwasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down