diff --git a/deps/uvwasi/include/fd_table.h b/deps/uvwasi/include/fd_table.h index 5380502a1e4e5f..23a3bf52f42c8b 100644 --- a/deps/uvwasi/include/fd_table.h +++ b/deps/uvwasi/include/fd_table.h @@ -31,19 +31,21 @@ uvwasi_errno_t uvwasi_fd_table_init(struct uvwasi_s* uvwasi, uint32_t init_size); void uvwasi_fd_table_free(struct uvwasi_s* uvwasi, struct uvwasi_fd_table_t* table); +uvwasi_errno_t uvwasi_fd_table_insert(struct uvwasi_s* uvwasi, + struct uvwasi_fd_table_t* table, + uv_file fd, + const char* mapped_path, + const char* real_path, + uvwasi_filetype_t type, + uvwasi_rights_t rights_base, + uvwasi_rights_t rights_inheriting, + int preopen, + struct uvwasi_fd_wrap_t** wrap); uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_s* uvwasi, struct uvwasi_fd_table_t* table, const uv_file fd, const char* path, const char* real_path); -uvwasi_errno_t uvwasi_fd_table_insert_fd(struct uvwasi_s* uvwasi, - struct uvwasi_fd_table_t* table, - const uv_file fd, - const int flags, - const char* path, - uvwasi_rights_t rights_base, - uvwasi_rights_t rights_inheriting, - struct uvwasi_fd_wrap_t* wrap); uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table, const uvwasi_fd_t id, struct uvwasi_fd_wrap_t** wrap, @@ -52,5 +54,9 @@ uvwasi_errno_t uvwasi_fd_table_get(const struct uvwasi_fd_table_t* table, 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); #endif /* __UVWASI_FD_TABLE_H__ */ diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h index e32c335b101bf3..9ca30459e23a73 100644 --- a/deps/uvwasi/include/uvwasi.h +++ b/deps/uvwasi/include/uvwasi.h @@ -11,7 +11,7 @@ extern "C" { #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 4 +#define UVWASI_VERSION_PATCH 5 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c index f3855d4da54dbe..b6a43f0370e1e2 100644 --- a/deps/uvwasi/src/fd_table.c +++ b/deps/uvwasi/src/fd_table.c @@ -9,183 +9,21 @@ #include "uv.h" #include "fd_table.h" #include "wasi_types.h" +#include "wasi_rights.h" #include "uv_mapping.h" #include "uvwasi_alloc.h" -#define UVWASI__RIGHTS_ALL (UVWASI_RIGHT_FD_DATASYNC | \ - UVWASI_RIGHT_FD_READ | \ - UVWASI_RIGHT_FD_SEEK | \ - UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ - UVWASI_RIGHT_FD_SYNC | \ - UVWASI_RIGHT_FD_TELL | \ - UVWASI_RIGHT_FD_WRITE | \ - UVWASI_RIGHT_FD_ADVISE | \ - UVWASI_RIGHT_FD_ALLOCATE | \ - UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \ - UVWASI_RIGHT_PATH_CREATE_FILE | \ - UVWASI_RIGHT_PATH_LINK_SOURCE | \ - UVWASI_RIGHT_PATH_LINK_TARGET | \ - UVWASI_RIGHT_PATH_OPEN | \ - UVWASI_RIGHT_FD_READDIR | \ - UVWASI_RIGHT_PATH_READLINK | \ - UVWASI_RIGHT_PATH_RENAME_SOURCE | \ - UVWASI_RIGHT_PATH_RENAME_TARGET | \ - UVWASI_RIGHT_PATH_FILESTAT_GET | \ - UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ - UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ - UVWASI_RIGHT_FD_FILESTAT_GET | \ - UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ - UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ - UVWASI_RIGHT_PATH_SYMLINK | \ - UVWASI_RIGHT_PATH_UNLINK_FILE | \ - UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ - UVWASI_RIGHT_POLL_FD_READWRITE | \ - UVWASI_RIGHT_SOCK_SHUTDOWN) - -#define UVWASI__RIGHTS_BLOCK_DEVICE_BASE UVWASI__RIGHTS_ALL -#define UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING UVWASI__RIGHTS_ALL - -#define UVWASI__RIGHTS_CHARACTER_DEVICE_BASE UVWASI__RIGHTS_ALL -#define UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING UVWASI__RIGHTS_ALL - -#define UVWASI__RIGHTS_REGULAR_FILE_BASE (UVWASI_RIGHT_FD_DATASYNC | \ - UVWASI_RIGHT_FD_READ | \ - UVWASI_RIGHT_FD_SEEK | \ - UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ - UVWASI_RIGHT_FD_SYNC | \ - UVWASI_RIGHT_FD_TELL | \ - UVWASI_RIGHT_FD_WRITE | \ - UVWASI_RIGHT_FD_ADVISE | \ - UVWASI_RIGHT_FD_ALLOCATE | \ - UVWASI_RIGHT_FD_FILESTAT_GET | \ - UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ - UVWASI_RIGHT_FD_FILESTAT_SET_TIMES |\ - UVWASI_RIGHT_POLL_FD_READWRITE) -#define UVWASI__RIGHTS_REGULAR_FILE_INHERITING 0 - -#define UVWASI__RIGHTS_DIRECTORY_BASE (UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ - UVWASI_RIGHT_FD_SYNC | \ - UVWASI_RIGHT_FD_ADVISE | \ - UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \ - UVWASI_RIGHT_PATH_CREATE_FILE | \ - UVWASI_RIGHT_PATH_LINK_SOURCE | \ - UVWASI_RIGHT_PATH_LINK_TARGET | \ - UVWASI_RIGHT_PATH_OPEN | \ - UVWASI_RIGHT_FD_READDIR | \ - UVWASI_RIGHT_PATH_READLINK | \ - UVWASI_RIGHT_PATH_RENAME_SOURCE | \ - UVWASI_RIGHT_PATH_RENAME_TARGET | \ - UVWASI_RIGHT_PATH_FILESTAT_GET | \ - UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ - UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ - UVWASI_RIGHT_FD_FILESTAT_GET | \ - UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ - UVWASI_RIGHT_PATH_SYMLINK | \ - UVWASI_RIGHT_PATH_UNLINK_FILE | \ - UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ - UVWASI_RIGHT_POLL_FD_READWRITE) -#define UVWASI__RIGHTS_DIRECTORY_INHERITING (UVWASI__RIGHTS_DIRECTORY_BASE | \ - UVWASI__RIGHTS_REGULAR_FILE_BASE) - -#define UVWASI__RIGHTS_SOCKET_BASE (UVWASI_RIGHT_FD_READ | \ - UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ - UVWASI_RIGHT_FD_WRITE | \ - UVWASI_RIGHT_FD_FILESTAT_GET | \ - UVWASI_RIGHT_POLL_FD_READWRITE | \ - UVWASI_RIGHT_SOCK_SHUTDOWN) -#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL; - -#define UVWASI__RIGHTS_TTY_BASE (UVWASI_RIGHT_FD_READ | \ - UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ - UVWASI_RIGHT_FD_WRITE | \ - UVWASI_RIGHT_FD_FILESTAT_GET | \ - UVWASI_RIGHT_POLL_FD_READWRITE) -#define UVWASI__RIGHTS_TTY_INHERITING 0 - -static uvwasi_errno_t uvwasi__get_type_and_rights(uv_file fd, - int flags, - uvwasi_filetype_t* type, - uvwasi_rights_t* rights_base, - uvwasi_rights_t* rights_inheriting) { - uv_fs_t req; - uvwasi_filetype_t filetype; - int read_or_write_only; - int r; - - r = uv_fs_fstat(NULL, &req, fd, NULL); - filetype = uvwasi__stat_to_filetype(&req.statbuf); - uv_fs_req_cleanup(&req); - if (r != 0) - return uvwasi__translate_uv_error(r); - - *type = filetype; - switch (filetype) { - case UVWASI_FILETYPE_REGULAR_FILE: - *rights_base = UVWASI__RIGHTS_REGULAR_FILE_BASE; - *rights_inheriting = UVWASI__RIGHTS_REGULAR_FILE_INHERITING; - break; - - case UVWASI_FILETYPE_DIRECTORY: - *rights_base = UVWASI__RIGHTS_DIRECTORY_BASE; - *rights_inheriting = UVWASI__RIGHTS_DIRECTORY_INHERITING; - break; - - /* uvwasi__stat_to_filetype() cannot differentiate socket types. It only - returns UVWASI_FILETYPE_SOCKET_STREAM. */ - case UVWASI_FILETYPE_SOCKET_STREAM: - if (uv_guess_handle(fd) == UV_UDP) - *type = UVWASI_FILETYPE_SOCKET_DGRAM; - - *rights_base = UVWASI__RIGHTS_SOCKET_BASE; - *rights_inheriting = UVWASI__RIGHTS_SOCKET_INHERITING; - break; - - case UVWASI_FILETYPE_CHARACTER_DEVICE: - if (uv_guess_handle(fd) == UV_TTY) { - *rights_base = UVWASI__RIGHTS_TTY_BASE; - *rights_inheriting = UVWASI__RIGHTS_TTY_INHERITING; - } else { - *rights_base = UVWASI__RIGHTS_CHARACTER_DEVICE_BASE; - *rights_inheriting = UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING; - } - break; - - case UVWASI_FILETYPE_BLOCK_DEVICE: - *rights_base = UVWASI__RIGHTS_BLOCK_DEVICE_BASE; - *rights_inheriting = UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING; - break; - - default: - *rights_base = 0; - *rights_inheriting = 0; - } - - if (*type == UVWASI_FILETYPE_UNKNOWN) - return UVWASI_EINVAL; - - /* Disable read/write bits depending on access mode. */ - read_or_write_only = flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); - - if (read_or_write_only == UV_FS_O_RDONLY) - *rights_base &= ~UVWASI_RIGHT_FD_WRITE; - else if (read_or_write_only == UV_FS_O_WRONLY) - *rights_base &= ~UVWASI_RIGHT_FD_READ; - - return UVWASI_ESUCCESS; -} - - -static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi, - struct uvwasi_fd_table_t* table, - uv_file fd, - const char* mapped_path, - const char* real_path, - uvwasi_filetype_t type, - uvwasi_rights_t rights_base, - uvwasi_rights_t rights_inheriting, - int preopen, - struct uvwasi_fd_wrap_t** wrap) { +uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, + struct uvwasi_fd_table_t* table, + uv_file fd, + const char* mapped_path, + const char* real_path, + uvwasi_filetype_t type, + uvwasi_rights_t rights_base, + uvwasi_rights_t rights_inheriting, + int preopen, + struct uvwasi_fd_wrap_t** wrap) { struct uvwasi_fd_wrap_t* entry; struct uvwasi_fd_wrap_t** new_fds; uvwasi_errno_t err; @@ -263,11 +101,13 @@ static uvwasi_errno_t uvwasi__fd_table_insert(uvwasi_t* uvwasi, entry->rights_base = rights_base; entry->rights_inheriting = rights_inheriting; entry->preopen = preopen; - table->used++; - if (wrap != NULL) + if (wrap != NULL) { + uv_mutex_lock(&entry->mutex); *wrap = entry; + } + table->used++; err = UVWASI_ESUCCESS; exit: uv_rwlock_wrunlock(&table->rwlock); @@ -314,28 +154,30 @@ uvwasi_errno_t uvwasi_fd_table_init(uvwasi_t* uvwasi, /* Create the stdio FDs. */ for (i = 0; i < 3; ++i) { - err = uvwasi__get_type_and_rights(i, - UV_FS_O_RDWR, - &type, - &base, - &inheriting); + err = uvwasi__get_filetype_by_fd(i, &type); + if (err != UVWASI_ESUCCESS) + goto error_exit; + + err = uvwasi__get_rights(i, UV_FS_O_RDWR, type, &base, &inheriting); if (err != UVWASI_ESUCCESS) goto error_exit; - err = uvwasi__fd_table_insert(uvwasi, - table, - i, - "", - "", - type, - base, - inheriting, - 0, - &wrap); + err = uvwasi_fd_table_insert(uvwasi, + table, + i, + "", + "", + type, + base, + inheriting, + 0, + &wrap); if (err != UVWASI_ESUCCESS) goto error_exit; - if (wrap->id != i || wrap->id != (uvwasi_fd_t) wrap->fd) { + r = wrap->id != i || wrap->id != (uvwasi_fd_t) wrap->fd; + uv_mutex_unlock(&wrap->mutex); + if (r) { err = UVWASI_EBADF; goto error_exit; } @@ -386,14 +228,18 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi, if (table == NULL || path == NULL || real_path == NULL) return UVWASI_EINVAL; - err = uvwasi__get_type_and_rights(fd, 0, &type, &base, &inheriting); + err = uvwasi__get_filetype_by_fd(fd, &type); if (err != UVWASI_ESUCCESS) return err; if (type != UVWASI_FILETYPE_DIRECTORY) return UVWASI_ENOTDIR; - err = uvwasi__fd_table_insert(uvwasi, + err = uvwasi__get_rights(fd, 0, type, &base, &inheriting); + if (err != UVWASI_ESUCCESS) + return err; + + return uvwasi_fd_table_insert(uvwasi, table, fd, path, @@ -403,49 +249,6 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi, UVWASI__RIGHTS_DIRECTORY_INHERITING, 1, NULL); - if (err != UVWASI_ESUCCESS) - return err; - - return UVWASI_ESUCCESS; -} - - -uvwasi_errno_t uvwasi_fd_table_insert_fd(uvwasi_t* uvwasi, - struct uvwasi_fd_table_t* table, - const uv_file fd, - const int flags, - const char* path, - uvwasi_rights_t rights_base, - uvwasi_rights_t rights_inheriting, - struct uvwasi_fd_wrap_t* wrap) { - struct uvwasi_fd_wrap_t* fd_wrap; - uvwasi_filetype_t type; - uvwasi_rights_t max_base; - uvwasi_rights_t max_inheriting; - uvwasi_errno_t r; - - if (table == NULL || path == NULL || wrap == NULL) - return UVWASI_EINVAL; - - r = uvwasi__get_type_and_rights(fd, flags, &type, &max_base, &max_inheriting); - if (r != UVWASI_ESUCCESS) - return r; - - r = uvwasi__fd_table_insert(uvwasi, - table, - fd, - path, - path, - type, - rights_base & max_base, - rights_inheriting & max_inheriting, - 0, - &fd_wrap); - if (r != UVWASI_ESUCCESS) - return r; - - *wrap = *fd_wrap; - return UVWASI_ESUCCESS; } @@ -522,3 +325,67 @@ uvwasi_errno_t uvwasi_fd_table_remove(uvwasi_t* uvwasi, uv_rwlock_wrunlock(&table->rwlock); return err; } + + +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) { + struct uvwasi_fd_wrap_t* dst_entry; + struct uvwasi_fd_wrap_t* src_entry; + uv_fs_t req; + uvwasi_errno_t err; + int r; + + if (uvwasi == NULL || table == NULL) + return UVWASI_EINVAL; + + if (dst == src) + return UVWASI_ESUCCESS; + + uv_rwlock_wrlock(&table->rwlock); + + if (dst >= table->size || src >= table->size) { + err = UVWASI_EBADF; + goto exit; + } + + dst_entry = table->fds[dst]; + src_entry = table->fds[src]; + + if (dst_entry == NULL || dst_entry->id != dst || + src_entry == NULL || src_entry->id != src) { + err = UVWASI_EBADF; + goto exit; + } + + uv_mutex_lock(&dst_entry->mutex); + uv_mutex_lock(&src_entry->mutex); + + /* Close the existing destination descriptor. */ + r = uv_fs_close(NULL, &req, dst_entry->fd, NULL); + uv_fs_req_cleanup(&req); + if (r != 0) { + uv_mutex_unlock(&dst_entry->mutex); + uv_mutex_unlock(&src_entry->mutex); + err = uvwasi__translate_uv_error(r); + goto exit; + } + + /* Move the source entry to the destination slot in the table. */ + table->fds[dst] = table->fds[src]; + table->fds[dst]->id = dst; + uv_mutex_unlock(&table->fds[dst]->mutex); + table->fds[src] = NULL; + table->used--; + + /* Clean up what's left of the old destination entry. */ + uv_mutex_unlock(&dst_entry->mutex); + uv_mutex_destroy(&dst_entry->mutex); + uvwasi__free(uvwasi, dst_entry); + + err = UVWASI_ESUCCESS; +exit: + uv_rwlock_wrunlock(&table->rwlock); + return err; +} diff --git a/deps/uvwasi/src/uv_mapping.c b/deps/uvwasi/src/uv_mapping.c index 846dcedbeb6b4f..297fdf5b75176f 100644 --- a/deps/uvwasi/src/uv_mapping.c +++ b/deps/uvwasi/src/uv_mapping.c @@ -241,3 +241,26 @@ void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs) { fs->st_mtim = uvwasi__timespec_to_timestamp(&stat->st_mtim); fs->st_ctim = uvwasi__timespec_to_timestamp(&stat->st_ctim); } + + +uvwasi_errno_t uvwasi__get_filetype_by_fd(uv_file fd, uvwasi_filetype_t* type) { + uv_fs_t req; + int r; + + r = uv_fs_fstat(NULL, &req, fd, NULL); + if (r != 0) { + *type = UVWASI_FILETYPE_UNKNOWN; + uv_fs_req_cleanup(&req); + return uvwasi__translate_uv_error(r); + } + + *type = uvwasi__stat_to_filetype(&req.statbuf); + uv_fs_req_cleanup(&req); + + if (*type == UVWASI_FILETYPE_SOCKET_STREAM && + uv_guess_handle(fd) == UV_UDP) { + *type = UVWASI_FILETYPE_SOCKET_DGRAM; + } + + return UVWASI_ESUCCESS; +} diff --git a/deps/uvwasi/src/uv_mapping.h b/deps/uvwasi/src/uv_mapping.h index d835ca507a4856..5a0542afb4dd8b 100644 --- a/deps/uvwasi/src/uv_mapping.h +++ b/deps/uvwasi/src/uv_mapping.h @@ -11,5 +11,6 @@ int uvwasi__translate_to_uv_signal(uvwasi_signal_t sig); uvwasi_timestamp_t uvwasi__timespec_to_timestamp(const uv_timespec_t* ts); uvwasi_filetype_t uvwasi__stat_to_filetype(const uv_stat_t* stat); void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs); +uvwasi_errno_t uvwasi__get_filetype_by_fd(uv_file fd, uvwasi_filetype_t* type); #endif /* __UVWASI_UV_MAPPING_H__ */ diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index e5d210657ce8b1..5a73bfee777e0a 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -22,6 +22,7 @@ #include "uv_mapping.h" #include "fd_table.h" #include "clocks.h" +#include "wasi_rights.h" /* TODO(cjihrig): PATH_MAX_BYTES shouldn't be stack allocated. On Windows, paths can be 32k long, and this PATH_MAX_BYTES is an artificial limitation. */ @@ -1485,41 +1486,10 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_renumber(uvwasi_t* uvwasi, uvwasi_fd_t from, uvwasi_fd_t to) { - struct uvwasi_fd_wrap_t* to_wrap; - struct uvwasi_fd_wrap_t* from_wrap; - uv_fs_t req; - uvwasi_errno_t err; - int r; - if (uvwasi == NULL) return UVWASI_EINVAL; - if (from == to) - return UVWASI_ESUCCESS; - - err = uvwasi_fd_table_get(&uvwasi->fds, from, &from_wrap, 0, 0); - if (err != UVWASI_ESUCCESS) - return err; - - err = uvwasi_fd_table_get(&uvwasi->fds, to, &to_wrap, 0, 0); - if (err != UVWASI_ESUCCESS) { - uv_mutex_unlock(&from_wrap->mutex); - return err; - } - - r = uv_fs_close(NULL, &req, to_wrap->fd, NULL); - uv_fs_req_cleanup(&req); - if (r != 0) { - uv_mutex_unlock(&from_wrap->mutex); - uv_mutex_unlock(&to_wrap->mutex); - return uvwasi__translate_uv_error(r); - } - - memcpy(to_wrap, from_wrap, sizeof(*to_wrap)); - to_wrap->id = to; - uv_mutex_unlock(&from_wrap->mutex); - uv_mutex_unlock(&to_wrap->mutex); - return uvwasi_fd_table_remove(uvwasi, &uvwasi->fds, from); + return uvwasi_fd_table_renumber(uvwasi, &uvwasi->fds, to, from); } @@ -1871,8 +1841,11 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, char resolved_path[PATH_MAX_BYTES]; uvwasi_rights_t needed_inheriting; uvwasi_rights_t needed_base; + uvwasi_rights_t max_base; + uvwasi_rights_t max_inheriting; struct uvwasi_fd_wrap_t* dirfd_wrap; - struct uvwasi_fd_wrap_t wrap; + struct uvwasi_fd_wrap_t *wrap; + uvwasi_filetype_t filetype; uvwasi_errno_t err; uv_fs_t req; int flags; @@ -1956,33 +1929,42 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, return uvwasi__translate_uv_error(r); } - err = uvwasi_fd_table_insert_fd(uvwasi, - &uvwasi->fds, - r, - flags, - resolved_path, - fs_rights_base, - fs_rights_inheriting, - &wrap); - if (err != UVWASI_ESUCCESS) { - uv_mutex_unlock(&dirfd_wrap->mutex); + /* Not all platforms support UV_FS_O_DIRECTORY, so get the file type and check + it here. */ + err = uvwasi__get_filetype_by_fd(r, &filetype); + if (err != UVWASI_ESUCCESS) goto close_file_and_error_exit; - } - /* Not all platforms support UV_FS_O_DIRECTORY, so enforce it here as well. */ if ((o_flags & UVWASI_O_DIRECTORY) != 0 && - wrap.type != UVWASI_FILETYPE_DIRECTORY) { - uv_mutex_unlock(&dirfd_wrap->mutex); - uvwasi_fd_table_remove(uvwasi, &uvwasi->fds, wrap.id); + filetype != UVWASI_FILETYPE_DIRECTORY) { err = UVWASI_ENOTDIR; goto close_file_and_error_exit; } - *fd = wrap.id; + err = uvwasi__get_rights(r, flags, filetype, &max_base, &max_inheriting); + if (err != UVWASI_ESUCCESS) + goto close_file_and_error_exit; + + err = uvwasi_fd_table_insert(uvwasi, + &uvwasi->fds, + r, + resolved_path, + resolved_path, + filetype, + fs_rights_base & max_base, + fs_rights_inheriting & max_inheriting, + 0, + &wrap); + if (err != UVWASI_ESUCCESS) + goto close_file_and_error_exit; + + *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; diff --git a/deps/uvwasi/src/wasi_rights.c b/deps/uvwasi/src/wasi_rights.c new file mode 100644 index 00000000000000..79d0338086a244 --- /dev/null +++ b/deps/uvwasi/src/wasi_rights.c @@ -0,0 +1,62 @@ +#include "uv.h" +#include "wasi_rights.h" +#include "wasi_types.h" + + +uvwasi_errno_t uvwasi__get_rights(uv_file fd, + int flags, + uvwasi_filetype_t type, + uvwasi_rights_t* rights_base, + uvwasi_rights_t* rights_inheriting) { + int read_or_write_only; + + if (type == UVWASI_FILETYPE_UNKNOWN) + return UVWASI_EINVAL; + + switch (type) { + case UVWASI_FILETYPE_REGULAR_FILE: + *rights_base = UVWASI__RIGHTS_REGULAR_FILE_BASE; + *rights_inheriting = UVWASI__RIGHTS_REGULAR_FILE_INHERITING; + break; + + case UVWASI_FILETYPE_DIRECTORY: + *rights_base = UVWASI__RIGHTS_DIRECTORY_BASE; + *rights_inheriting = UVWASI__RIGHTS_DIRECTORY_INHERITING; + break; + + case UVWASI_FILETYPE_SOCKET_STREAM: + case UVWASI_FILETYPE_SOCKET_DGRAM: + *rights_base = UVWASI__RIGHTS_SOCKET_BASE; + *rights_inheriting = UVWASI__RIGHTS_SOCKET_INHERITING; + break; + + case UVWASI_FILETYPE_CHARACTER_DEVICE: + if (uv_guess_handle(fd) == UV_TTY) { + *rights_base = UVWASI__RIGHTS_TTY_BASE; + *rights_inheriting = UVWASI__RIGHTS_TTY_INHERITING; + } else { + *rights_base = UVWASI__RIGHTS_CHARACTER_DEVICE_BASE; + *rights_inheriting = UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING; + } + break; + + case UVWASI_FILETYPE_BLOCK_DEVICE: + *rights_base = UVWASI__RIGHTS_BLOCK_DEVICE_BASE; + *rights_inheriting = UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING; + break; + + default: + *rights_base = 0; + *rights_inheriting = 0; + } + + /* Disable read/write bits depending on access mode. */ + read_or_write_only = flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); + + if (read_or_write_only == UV_FS_O_RDONLY) + *rights_base &= ~UVWASI_RIGHT_FD_WRITE; + else if (read_or_write_only == UV_FS_O_WRONLY) + *rights_base &= ~UVWASI_RIGHT_FD_READ; + + return UVWASI_ESUCCESS; +} diff --git a/deps/uvwasi/src/wasi_rights.h b/deps/uvwasi/src/wasi_rights.h new file mode 100644 index 00000000000000..fb19bd0a00e74e --- /dev/null +++ b/deps/uvwasi/src/wasi_rights.h @@ -0,0 +1,104 @@ +#ifndef __UVWASI_WASI_RIGHTS_H__ +#define __UVWASI_WASI_RIGHTS_H__ + +#include "wasi_types.h" + +#define UVWASI__RIGHTS_ALL (UVWASI_RIGHT_FD_DATASYNC | \ + UVWASI_RIGHT_FD_READ | \ + UVWASI_RIGHT_FD_SEEK | \ + UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + UVWASI_RIGHT_FD_SYNC | \ + UVWASI_RIGHT_FD_TELL | \ + UVWASI_RIGHT_FD_WRITE | \ + UVWASI_RIGHT_FD_ADVISE | \ + UVWASI_RIGHT_FD_ALLOCATE | \ + UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \ + UVWASI_RIGHT_PATH_CREATE_FILE | \ + UVWASI_RIGHT_PATH_LINK_SOURCE | \ + UVWASI_RIGHT_PATH_LINK_TARGET | \ + UVWASI_RIGHT_PATH_OPEN | \ + UVWASI_RIGHT_FD_READDIR | \ + UVWASI_RIGHT_PATH_READLINK | \ + UVWASI_RIGHT_PATH_RENAME_SOURCE | \ + UVWASI_RIGHT_PATH_RENAME_TARGET | \ + UVWASI_RIGHT_PATH_FILESTAT_GET | \ + UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_FD_FILESTAT_GET | \ + UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + UVWASI_RIGHT_PATH_SYMLINK | \ + UVWASI_RIGHT_PATH_UNLINK_FILE | \ + UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + UVWASI_RIGHT_POLL_FD_READWRITE | \ + UVWASI_RIGHT_SOCK_SHUTDOWN) + +#define UVWASI__RIGHTS_BLOCK_DEVICE_BASE UVWASI__RIGHTS_ALL +#define UVWASI__RIGHTS_BLOCK_DEVICE_INHERITING UVWASI__RIGHTS_ALL + +#define UVWASI__RIGHTS_CHARACTER_DEVICE_BASE UVWASI__RIGHTS_ALL +#define UVWASI__RIGHTS_CHARACTER_DEVICE_INHERITING UVWASI__RIGHTS_ALL + +#define UVWASI__RIGHTS_REGULAR_FILE_BASE (UVWASI_RIGHT_FD_DATASYNC | \ + UVWASI_RIGHT_FD_READ | \ + UVWASI_RIGHT_FD_SEEK | \ + UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + UVWASI_RIGHT_FD_SYNC | \ + UVWASI_RIGHT_FD_TELL | \ + UVWASI_RIGHT_FD_WRITE | \ + UVWASI_RIGHT_FD_ADVISE | \ + UVWASI_RIGHT_FD_ALLOCATE | \ + UVWASI_RIGHT_FD_FILESTAT_GET | \ + UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + UVWASI_RIGHT_FD_FILESTAT_SET_TIMES |\ + UVWASI_RIGHT_POLL_FD_READWRITE) +#define UVWASI__RIGHTS_REGULAR_FILE_INHERITING 0 + +#define UVWASI__RIGHTS_DIRECTORY_BASE (UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + UVWASI_RIGHT_FD_SYNC | \ + UVWASI_RIGHT_FD_ADVISE | \ + UVWASI_RIGHT_PATH_CREATE_DIRECTORY | \ + UVWASI_RIGHT_PATH_CREATE_FILE | \ + UVWASI_RIGHT_PATH_LINK_SOURCE | \ + UVWASI_RIGHT_PATH_LINK_TARGET | \ + UVWASI_RIGHT_PATH_OPEN | \ + UVWASI_RIGHT_FD_READDIR | \ + UVWASI_RIGHT_PATH_READLINK | \ + UVWASI_RIGHT_PATH_RENAME_SOURCE | \ + UVWASI_RIGHT_PATH_RENAME_TARGET | \ + UVWASI_RIGHT_PATH_FILESTAT_GET | \ + UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_FD_FILESTAT_GET | \ + UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_PATH_SYMLINK | \ + UVWASI_RIGHT_PATH_UNLINK_FILE | \ + UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + UVWASI_RIGHT_POLL_FD_READWRITE) +#define UVWASI__RIGHTS_DIRECTORY_INHERITING (UVWASI__RIGHTS_DIRECTORY_BASE | \ + UVWASI__RIGHTS_REGULAR_FILE_BASE) + +#define UVWASI__RIGHTS_SOCKET_BASE (UVWASI_RIGHT_FD_READ | \ + UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + UVWASI_RIGHT_FD_WRITE | \ + UVWASI_RIGHT_FD_FILESTAT_GET | \ + UVWASI_RIGHT_POLL_FD_READWRITE | \ + UVWASI_RIGHT_SOCK_SHUTDOWN) +#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL; + +#define UVWASI__RIGHTS_TTY_BASE (UVWASI_RIGHT_FD_READ | \ + UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + UVWASI_RIGHT_FD_WRITE | \ + UVWASI_RIGHT_FD_FILESTAT_GET | \ + UVWASI_RIGHT_POLL_FD_READWRITE) +#define UVWASI__RIGHTS_TTY_INHERITING 0 + + +uvwasi_errno_t uvwasi__get_rights(uv_file fd, + int flags, + uvwasi_filetype_t type, + uvwasi_rights_t* rights_base, + uvwasi_rights_t* rights_inheriting); + + +#endif /* __UVWASI_WASI_RIGHTS_H__ */ diff --git a/deps/uvwasi/uvwasi.gyp b/deps/uvwasi/uvwasi.gyp index 21ac35cdfc11ad..6963cbf20a7923 100644 --- a/deps/uvwasi/uvwasi.gyp +++ b/deps/uvwasi/uvwasi.gyp @@ -13,6 +13,7 @@ 'src/fd_table.c', 'src/uv_mapping.c', 'src/uvwasi.c', + 'src/wasi_rights.c', ], 'dependencies': [ '../uv/uv.gyp:libuv',