diff --git a/README.md b/README.md index fbbbfc7..17c1ada 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,7 @@ This section has been adapted from the official WASI API documentation. - [`uvwasi_fd_filestat_get()`](#fd_filestat_get) - [`uvwasi_fd_filestat_set_size()`](#fd_filestat_set_size) - [`uvwasi_fd_filestat_set_times()`](#fd_filestat_set_times) +- [`uvwasi_fd_permissions_set()`](#fd_permissions_set) - [`uvwasi_fd_pread()`](#fd_pread) - [`uvwasi_fd_prestat_get()`](#fd_prestat_get) - [`uvwasi_fd_prestat_dir_name()`](#fd_prestat_dir_name) @@ -218,6 +219,7 @@ This section has been adapted from the official WASI API documentation. - [`uvwasi_path_filestat_set_times()`](#path_filestat_set_times) - [`uvwasi_path_link()`](#path_link) - [`uvwasi_path_open()`](#path_open) +- [`uvwasi_path_permissions_set()`](#path_permissions_set) - [`uvwasi_path_readlink()`](#path_readlink) - [`uvwasi_path_remove_directory()`](#path_remove_directory) - [`uvwasi_path_rename()`](#path_rename) @@ -512,6 +514,27 @@ Inputs: A bitmask indicating which timestamps to adjust. +### `uvwasi_fd_permissions_set()` + +Set the permissions of a file or directory. + +This sets the permissions associated with a file or directory +in a filesystem at the time it is called. The ability to actually +access a file or directory may depend on additional permissions not +reflected here. + +Note: This is similar `fchmod` in POSIX. + +Inputs: + +- [\_\_wasi\_fd\_t](#fd) fd + + The file descriptor to operate on. + +- [\_\_wasi\_permissions\_t](#permissions) permissions + + The permissions associated with the file. + ### `uvwasi_fd_pread()` Read from a file descriptor, without using and updating the @@ -908,6 +931,10 @@ Inputs: The initial flags of the file descriptor. +- [\_\_wasi\_permissions\_t](#permissions) permissions + + If a file is created, the filesystem permissions to associate with it. + Outputs: - [\_\_wasi\_fd\_t](#fd) fd @@ -915,6 +942,39 @@ Outputs: The file descriptor of the file that has been opened. +### `uvwasi_path_permissions_set()` + +Set the permissions of a file or directory. + +This sets the permissions associated with a file or directory in a +filesystem at the time it is called. The ability to actually access +a file or directory may depend on additional permissions not reflected +here. + +Note: This is similar `fchmodat` in POSIX. + +Unlike POSIX, this doesn't expose a user/group/other distinction; +implementations in POSIX environments are suggested to consult the +umask to determine which of the user/group/other flags to modify. + +Inputs: + +- [\_\_wasi\_fd\_t](#fd) fd + + The file descriptor to operate on. + +- [\_\_wasi\_lookupflags\_t](#lookupflags) flags + + Flags determining the method of how the path is resolved. + +- const char \*path and size\_t path\_len + + The path to a file to query. + +- [\_\_wasi\_permissions\_t](#permissions) permissions + + The permissions associated with the file. + ### `uvwasi_path_readlink()` Read the contents of a symbolic link. @@ -1790,6 +1850,10 @@ Members: File type. +- [\_\_wasi\_permissions\_t](#permissions) permissions + + File permissions. + - [\_\_wasi\_linkcount\_t](#linkcount) st\_nlink Number of hard links to the file. @@ -1952,6 +2016,30 @@ Possible values: Truncate file to size 0. +### `uvwasi_permissions_t` (`uint8_t` bitfield) + +File permissions. This represents the permissions associated with a file in a filesystem, and don't fully reflect all the conditions which determine whether a given WASI program can access the file. + +Possible values: + +- **`UVWASI_PERMISSION_READ`** + + For files, permission to read the file. For directories, permission to do `readdir` and access files within the directory. + + Note: This is similar to the read bit being set on files, and the read *and* execute bits being set on directories, in POSIX. + +- **`UVWASI_PERMISSION_WRITE`** + + For files, permission to mutate the file. For directories, permission to create, remove, and rename items within the directory. + +- **`UVWASI_PERMISSION_EXECUTE`** + + For files, permission to "execute" the file, using whatever concept of "executing" the host filesystem has. This flag is not valid for directories. + +- **`UVWASI_PERMISSION_PRIVATE`** + + For filesystems which have a concept of multiple "users", this flag indicates that the file is only accessible by the effective "user" that the WASI store uses to access the filesystem, and inaccessible to other "users". + ### `uvwasi_riflags_t` (`uint16_t` bitfield) Flags provided to [`uvwasi_sock_recv()`](#sock_recv). @@ -2087,6 +2175,10 @@ Possible values: The right to invoke [`uvwasi_path_filestat_set_times()`](#path_filestat_set_times). +- **`UVWASI_RIGHT_PATH_PERMISSIONS_SET`** + + The right to invoke [`uvwasi_path_filestat_permissions_set()`](#path_filestat_permissions_set). + - **`UVWASI_RIGHT_FD_FILESTAT_GET`** The right to invoke [`uvwasi_fd_filestat_get()`](#fd_filestat_get). @@ -2099,6 +2191,10 @@ Possible values: The right to invoke [`uvwasi_fd_filestat_set_times()`](#fd_filestat_set_times). +- **`UVWASI_RIGHT_FD_PERMISSIONS_SET`** + + The right to invoke [`uvwasi_fd_filestat_permissions_set()`](#fd_filestat_permissions_set). + - **`UVWASI_RIGHT_PATH_SYMLINK`** The right to invoke [`uvwasi_path_symlink()`](#path_symlink). diff --git a/include/uvwasi.h b/include/uvwasi.h index e2b8484..5de5ec3 100644 --- a/include/uvwasi.h +++ b/include/uvwasi.h @@ -123,6 +123,9 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, uvwasi_timestamp_t st_atim, uvwasi_timestamp_t st_mtim, uvwasi_fstflags_t fst_flags); +uvwasi_errno_t uvwasi_fd_permissions_set(uvwasi_t* uvwasi, + uvwasi_fd_t fd, + uvwasi_permissions_t permissions); uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, @@ -205,7 +208,14 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, uvwasi_fdflags_t fs_flags, + uvwasi_permissions_t permissions, uvwasi_fd_t* fd); +uvwasi_errno_t uvwasi_path_permissions_set(uvwasi_t* uvwasi, + uvwasi_fd_t fd, + uvwasi_lookupflags_t flags, + const char* path, + size_t path_len, + uvwasi_permissions_t permissions); uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, diff --git a/include/wasi_types.h b/include/wasi_types.h index ab3cc69..6f83a6c 100644 --- a/include/wasi_types.h +++ b/include/wasi_types.h @@ -213,10 +213,18 @@ typedef uint64_t uvwasi_rights_t; /* Bitfield */ #define UVWASI_RIGHT_PATH_UNLINK_FILE (1 << 26) #define UVWASI_RIGHT_POLL_FD_READWRITE (1 << 27) #define UVWASI_RIGHT_SOCK_SHUTDOWN (1 << 28) +#define UVWASI_RIGHT_PATH_PERMISSIONS_SET (1 << 29) +#define UVWASI_RIGHT_FD_PERMISSIONS_SET (1 << 30) typedef uint16_t uvwasi_roflags_t; /* Bitfield */ #define UVWASI_SOCK_RECV_DATA_TRUNCATED (1 << 0) +typedef uint8_t uvwasi_permissions_t; /* Bitfield */ +#define UVWASI_PERMISSION_READ (1 << 0) +#define UVWASI_PERMISSION_WRITE (1 << 1) +#define UVWASI_PERMISSION_EXECUTE (1 << 2) +#define UVWASI_PERMISSION_PRIVATE (1 << 3) + typedef uint8_t uvwasi_sdflags_t; /* Bitfield */ #define UVWASI_SHUT_RD (1 << 0) #define UVWASI_SHUT_WR (1 << 1) @@ -264,6 +272,7 @@ typedef struct uvwasi_filestat_s { uvwasi_device_t st_dev; uvwasi_inode_t st_ino; uvwasi_filetype_t st_filetype; + uvwasi_permissions_t permissions; uvwasi_linkcount_t st_nlink; uvwasi_filesize_t st_size; uvwasi_timestamp_t st_atim; diff --git a/src/uv_mapping.c b/src/uv_mapping.c index 9314855..4027655 100644 --- a/src/uv_mapping.c +++ b/src/uv_mapping.c @@ -155,6 +155,8 @@ void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs) { fs->st_atim = uvwasi__timespec_to_timestamp(&stat->st_atim); fs->st_mtim = uvwasi__timespec_to_timestamp(&stat->st_mtim); fs->st_ctim = uvwasi__timespec_to_timestamp(&stat->st_ctim); + /* TODO(cjihrig): Permissions are not currently used. */ + fs->permissions = 0; } diff --git a/src/uvwasi.c b/src/uvwasi.c index 2fb195f..bce27ee 100644 --- a/src/uvwasi.c +++ b/src/uvwasi.c @@ -1165,6 +1165,17 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi, } +uvwasi_errno_t uvwasi_fd_permissions_set(uvwasi_t* uvwasi, + uvwasi_fd_t fd, + uvwasi_permissions_t permissions) { + if (uvwasi == NULL) + return UVWASI_EINVAL; + + /* TODO(cjihrig): Implement this. */ + return UVWASI_ENOTSUP; +} + + uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi, uvwasi_fd_t fd, const uvwasi_iovec_t* iovs, @@ -1851,6 +1862,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, uvwasi_rights_t fs_rights_base, uvwasi_rights_t fs_rights_inheriting, uvwasi_fdflags_t fs_flags, + uvwasi_permissions_t permissions, uvwasi_fd_t* fd) { char resolved_path[PATH_MAX_BYTES]; uvwasi_rights_t needed_inheriting; @@ -1867,6 +1879,8 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, int write; int r; + /* TODO(cjihrig): The permissions input is currently not used. */ + if (uvwasi == NULL || path == NULL || fd == NULL) return UVWASI_EINVAL; @@ -1982,6 +1996,20 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, } +uvwasi_errno_t uvwasi_path_permissions_set(uvwasi_t* uvwasi, + uvwasi_fd_t fd, + uvwasi_lookupflags_t flags, + const char* path, + size_t path_len, + uvwasi_permissions_t permissions) { + if (uvwasi == NULL || path == NULL) + return UVWASI_EINVAL; + + /* TODO(cjihrig): Implement this. */ + return UVWASI_ENOTSUP; +} + + uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi, uvwasi_fd_t fd, const char* path, diff --git a/src/wasi_rights.h b/src/wasi_rights.h index 6510bdf..bffeae4 100644 --- a/src/wasi_rights.h +++ b/src/wasi_rights.h @@ -24,9 +24,11 @@ UVWASI_RIGHT_PATH_FILESTAT_GET | \ UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_PATH_PERMISSIONS_SET | \ UVWASI_RIGHT_FD_FILESTAT_GET | \ UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + UVWASI_RIGHT_FD_PERMISSIONS_SET | \ UVWASI_RIGHT_PATH_SYMLINK | \ UVWASI_RIGHT_PATH_UNLINK_FILE | \ UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ @@ -51,6 +53,7 @@ UVWASI_RIGHT_FD_FILESTAT_GET | \ UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \ UVWASI_RIGHT_FD_FILESTAT_SET_TIMES |\ + UVWASI_RIGHT_FD_PERMISSIONS_SET | \ UVWASI_RIGHT_POLL_FD_READWRITE) #define UVWASI__RIGHTS_REGULAR_FILE_INHERITING 0 @@ -69,8 +72,10 @@ UVWASI_RIGHT_PATH_FILESTAT_GET | \ UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_PATH_PERMISSIONS_SET | \ UVWASI_RIGHT_FD_FILESTAT_GET | \ UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + UVWASI_RIGHT_FD_PERMISSIONS_SET | \ UVWASI_RIGHT_PATH_SYMLINK | \ UVWASI_RIGHT_PATH_UNLINK_FILE | \ UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \ diff --git a/test/test-basic-file-io.c b/test/test-basic-file-io.c index d3ad8b8..dda773d 100644 --- a/test/test-basic-file-io.c +++ b/test/test-basic-file-io.c @@ -61,6 +61,7 @@ int main(void) { fs_rights_base, 0, 0, + 0, &fd); assert(err == 0); @@ -79,6 +80,7 @@ int main(void) { assert(stats.st_atim > 0); assert(stats.st_mtim > 0); assert(stats.st_ctim > 0); + assert(stats.permissions == 0); /* Resize the file to 1024 bytes. */ err = uvwasi_fd_filestat_set_size(&uvwasi, fd, 1024); @@ -163,6 +165,7 @@ int main(void) { assert(stats2.st_atim > 0); assert(stats2.st_mtim > 0); assert(stats2.st_ctim > 0); + assert(stats2.permissions == 0); /* Unlink the file. */ err = uvwasi_path_unlink_file(&uvwasi, 3, path, strlen(path) + 1); diff --git a/test/test-ebadf-input-validation.c b/test/test-ebadf-input-validation.c index 46f7d0a..72533bd 100644 --- a/test/test-ebadf-input-validation.c +++ b/test/test-ebadf-input-validation.c @@ -59,7 +59,7 @@ int main(void) { CHECK(uvwasi_path_filestat_get(&uvw, 100, 0, test_str, 5, &test_filestat)); CHECK(uvwasi_path_filestat_set_times(&uvw, 100, 0, test_str, 4, 5, 6, 7)); CHECK(uvwasi_path_link(&uvw, 100, 4, test_str, 5, 100, test_str, 6)); - CHECK(uvwasi_path_open(&uvw, 100, 0, test_str, 4, 5, 6, 7, 8, &test_fd)); + CHECK(uvwasi_path_open(&uvw, 100, 0, test_str, 4, 5, 6, 7, 8, 9, &test_fd)); CHECK(uvwasi_path_readlink(&uvw, 100, test_str, 4, test_str, 5, &test_size)); CHECK(uvwasi_path_remove_directory(&uvw, 99, "x", 2)); CHECK(uvwasi_path_rename(&uvw, 99, test_str, 4, 99, test_str, 5)); diff --git a/test/test-einval-input-validation.c b/test/test-einval-input-validation.c index f4eab44..bd24e6c 100644 --- a/test/test-einval-input-validation.c +++ b/test/test-einval-input-validation.c @@ -74,6 +74,8 @@ int main(void) { CHECK(uvwasi_fd_filestat_set_times(NULL, 3, 0, 0, UVWASI_FILESTAT_SET_ATIM)); + CHECK(uvwasi_fd_permissions_set(NULL, 3, 0)); + CHECK(uvwasi_fd_pread(NULL, 3, &test_iovec, 2, 10, &test_size)); CHECK(uvwasi_fd_pread(&uvw, 3, NULL, 2, 10, &test_size)); CHECK(uvwasi_fd_pread(&uvw, 3, &test_iovec, 2, 10, NULL)); @@ -124,9 +126,12 @@ int main(void) { CHECK(uvwasi_path_link(&uvw, 3, 4, NULL, 5, 3, test_str, 6)); CHECK(uvwasi_path_link(&uvw, 3, 4, test_str, 5, 3, NULL, 6)); - CHECK(uvwasi_path_open(NULL, 3, 0, test_str, 4, 5, 6, 7, 8, &test_fd)); - CHECK(uvwasi_path_open(&uvw, 3, 0, NULL, 4, 5, 6, 7, 8, &test_fd)); - CHECK(uvwasi_path_open(&uvw, 3, 0, test_str, 4, 5, 6, 7, 8, NULL)); + CHECK(uvwasi_path_open(NULL, 3, 0, test_str, 4, 5, 6, 7, 8, 9, &test_fd)); + CHECK(uvwasi_path_open(&uvw, 3, 0, NULL, 4, 5, 6, 7, 8, 9, &test_fd)); + CHECK(uvwasi_path_open(&uvw, 3, 0, test_str, 4, 5, 6, 7, 8, 9, NULL)); + + CHECK(uvwasi_path_permissions_set(NULL, 3, 1, test_str, 4, 5)); + CHECK(uvwasi_path_permissions_set(&uvw, 3, 1, NULL, 4, 5)); CHECK(uvwasi_path_readlink(NULL, 3, test_str, 4, test_str, 5, &test_size)); CHECK(uvwasi_path_readlink(&uvw, 3, NULL, 4, test_str, 5, &test_size));