From 98501e4fad6657186137f5f4ee19ceab317a614b Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 27 Apr 2023 08:59:50 -0700 Subject: [PATCH] liberate wasi-common from Rights (#6265) * tests: remove all use of rights for anything besides path_open read | write * wasi-common and friends: delete all Caps from FileEntry and DirEntry the sole thing rights are used to determine is whether a path_open is opening for reading and writing. --- .../wasi-tests/src/bin/directory_seek.rs | 25 +- .../wasi-tests/src/bin/fd_advise.rs | 7 +- .../wasi-tests/src/bin/fd_filestat_set.rs | 6 +- .../wasi-tests/src/bin/fd_flags_set.rs | 6 +- .../wasi-tests/src/bin/fd_readdir.rs | 22 +- .../wasi-tests/src/bin/file_allocate.rs | 5 +- .../wasi-tests/src/bin/file_pread_pwrite.rs | 2 +- .../wasi-tests/src/bin/file_seek_tell.rs | 2 +- .../wasi-tests/src/bin/path_filestat.rs | 23 +- .../wasi-tests/src/bin/path_link.rs | 11 +- .../src/bin/path_open_read_without_rights.rs | 75 ---- .../wasi-tests/src/bin/poll_oneoff_files.rs | 14 +- .../src/bin/read_empty_file.rs.disabled | 5 + .../wasi-tests/src/bin/symlink_filestat.rs | 9 +- crates/test-programs/wasi-tests/src/lib.rs | 22 +- crates/wasi-common/cap-std-sync/src/lib.rs | 10 +- crates/wasi-common/src/ctx.rs | 77 +--- crates/wasi-common/src/dir.rs | 115 +---- crates/wasi-common/src/file.rs | 72 +--- crates/wasi-common/src/snapshots/preview_0.rs | 28 +- crates/wasi-common/src/snapshots/preview_1.rs | 402 +++--------------- crates/wasi-common/tokio/src/lib.rs | 12 +- 22 files changed, 136 insertions(+), 814 deletions(-) delete mode 100644 crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs create mode 100644 crates/test-programs/wasi-tests/src/bin/read_empty_file.rs.disabled diff --git a/crates/test-programs/wasi-tests/src/bin/directory_seek.rs b/crates/test-programs/wasi-tests/src/bin/directory_seek.rs index 85b96e6a1099..dc4fd52fb52f 100644 --- a/crates/test-programs/wasi-tests/src/bin/directory_seek.rs +++ b/crates/test-programs/wasi-tests/src/bin/directory_seek.rs @@ -6,16 +6,8 @@ unsafe fn test_directory_seek(dir_fd: wasi::Fd) { wasi::path_create_directory(dir_fd, "dir").expect("failed to make directory"); // Open the directory and attempt to request rights for seeking. - let fd = wasi::path_open( - dir_fd, - 0, - "dir", - wasi::OFLAGS_DIRECTORY, - wasi::RIGHTS_FD_SEEK, - 0, - 0, - ) - .expect("failed to open file"); + let fd = wasi::path_open(dir_fd, 0, "dir", wasi::OFLAGS_DIRECTORY, 0, 0, 0) + .expect("failed to open file"); assert!( fd > libc::STDERR_FILENO as wasi::Fd, "file descriptor range check", @@ -27,19 +19,6 @@ unsafe fn test_directory_seek(dir_fd: wasi::Fd) { wasi::ERRNO_BADF ); - // Check if we obtained the right to seek. - let fdstat = wasi::fd_fdstat_get(fd).expect("failed to fdstat"); - assert_eq!( - fdstat.fs_filetype, - wasi::FILETYPE_DIRECTORY, - "expected the scratch directory to be a directory", - ); - assert_eq!( - (fdstat.fs_rights_base & wasi::RIGHTS_FD_SEEK), - 0, - "directory does NOT have the seek right", - ); - // Clean up. wasi::fd_close(fd).expect("failed to close fd"); wasi::path_remove_directory(dir_fd, "dir").expect("failed to remove dir"); diff --git a/crates/test-programs/wasi-tests/src/bin/fd_advise.rs b/crates/test-programs/wasi-tests/src/bin/fd_advise.rs index d6c37ae776fd..78a048db0f9e 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_advise.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_advise.rs @@ -8,12 +8,7 @@ unsafe fn test_fd_advise(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_ADVISE - | wasi::RIGHTS_FD_FILESTAT_GET - | wasi::RIGHTS_FD_FILESTAT_SET_SIZE - | wasi::RIGHTS_FD_ALLOCATE, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs b/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs index 424831b33c86..de358dfff23e 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs @@ -8,11 +8,7 @@ unsafe fn test_fd_filestat_set(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_FILESTAT_GET - | wasi::RIGHTS_FD_FILESTAT_SET_SIZE - | wasi::RIGHTS_FD_FILESTAT_SET_TIMES, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs b/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs index 17586ef016c6..9a21fc465f42 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_flags_set.rs @@ -10,11 +10,7 @@ unsafe fn test_fd_fdstat_set_flags(dir_fd: wasi::Fd) { 0, FILE_NAME, wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_SEEK - | wasi::RIGHTS_FD_TELL - | wasi::RIGHTS_FD_FDSTAT_SET_FLAGS, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, wasi::FDFLAGS_APPEND, ) diff --git a/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs b/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs index bc4bdd2d8524..83398f6ae119 100644 --- a/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs +++ b/crates/test-programs/wasi-tests/src/bin/fd_readdir.rs @@ -102,10 +102,7 @@ unsafe fn test_fd_readdir(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_READDIR - | wasi::RIGHTS_FD_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) @@ -119,16 +116,8 @@ unsafe fn test_fd_readdir(dir_fd: wasi::Fd) { wasi::fd_close(file_fd).expect("closing a file"); wasi::path_create_directory(dir_fd, "nested").expect("create a directory"); - let nested_fd = wasi::path_open( - dir_fd, - 0, - "nested", - 0, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_READDIR | wasi::RIGHTS_FD_FILESTAT_GET, - 0, - 0, - ) - .expect("failed to open nested directory"); + let nested_fd = + wasi::path_open(dir_fd, 0, "nested", 0, 0, 0, 0).expect("failed to open nested directory"); assert!( nested_fd > file_fd, "nested directory file descriptor range check", @@ -190,10 +179,7 @@ unsafe fn test_fd_readdir_lots(dir_fd: wasi::Fd) { 0, &format!("file.{}", count), wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_READDIR - | wasi::RIGHTS_FD_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/file_allocate.rs b/crates/test-programs/wasi-tests/src/bin/file_allocate.rs index 378caaf31803..356563015b30 100644 --- a/crates/test-programs/wasi-tests/src/bin/file_allocate.rs +++ b/crates/test-programs/wasi-tests/src/bin/file_allocate.rs @@ -8,10 +8,7 @@ unsafe fn test_file_allocate(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ - | wasi::RIGHTS_FD_WRITE - | wasi::RIGHTS_FD_ALLOCATE - | wasi::RIGHTS_FD_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/file_pread_pwrite.rs b/crates/test-programs/wasi-tests/src/bin/file_pread_pwrite.rs index 9df32f3c32f1..918fec842bf1 100644 --- a/crates/test-programs/wasi-tests/src/bin/file_pread_pwrite.rs +++ b/crates/test-programs/wasi-tests/src/bin/file_pread_pwrite.rs @@ -9,7 +9,7 @@ unsafe fn test_file_pread_pwrite(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_WRITE, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs b/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs index a3d3711b95e2..a54fe14ab05c 100644 --- a/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs +++ b/crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs @@ -8,7 +8,7 @@ unsafe fn test_file_seek_tell(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_TELL, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/path_filestat.rs b/crates/test-programs/wasi-tests/src/bin/path_filestat.rs index 2b1629e40a39..2c4b63a93e8c 100644 --- a/crates/test-programs/wasi-tests/src/bin/path_filestat.rs +++ b/crates/test-programs/wasi-tests/src/bin/path_filestat.rs @@ -2,13 +2,6 @@ use std::{env, process}; use wasi_tests::{assert_errno, open_scratch_directory, TESTCONFIG}; unsafe fn test_path_filestat(dir_fd: wasi::Fd) { - let mut fdstat = wasi::fd_fdstat_get(dir_fd).expect("fd_fdstat_get"); - assert_ne!( - fdstat.fs_rights_base & wasi::RIGHTS_PATH_FILESTAT_GET, - 0, - "the scratch directory should have RIGHT_PATH_FILESTAT_GET as base right", - ); - let fdflags = if TESTCONFIG.support_fdflags_sync() { wasi::FDFLAGS_APPEND | wasi::FDFLAGS_SYNC } else { @@ -21,7 +14,7 @@ unsafe fn test_path_filestat(dir_fd: wasi::Fd) { 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_PATH_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, // Pass some flags for later retrieval fdflags, @@ -32,17 +25,7 @@ unsafe fn test_path_filestat(dir_fd: wasi::Fd) { "file descriptor range check", ); - fdstat = wasi::fd_fdstat_get(file_fd).expect("fd_fdstat_get"); - assert_eq!( - fdstat.fs_rights_base & wasi::RIGHTS_PATH_FILESTAT_GET, - 0, - "files shouldn't have rights for path_* syscalls even if manually given", - ); - assert_eq!( - fdstat.fs_rights_inheriting & wasi::RIGHTS_PATH_FILESTAT_GET, - 0, - "files shouldn't have rights for path_* syscalls even if manually given", - ); + let fdstat = wasi::fd_fdstat_get(file_fd).expect("fd_fdstat_get"); assert_eq!( fdstat.fs_flags & wasi::FDFLAGS_APPEND, wasi::FDFLAGS_APPEND, @@ -63,7 +46,7 @@ unsafe fn test_path_filestat(dir_fd: wasi::Fd) { 0, "file", 0, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_PATH_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, wasi::FDFLAGS_SYNC, ) diff --git a/crates/test-programs/wasi-tests/src/bin/path_link.rs b/crates/test-programs/wasi-tests/src/bin/path_link.rs index d229ba8aa5bb..161d865df568 100644 --- a/crates/test-programs/wasi-tests/src/bin/path_link.rs +++ b/crates/test-programs/wasi-tests/src/bin/path_link.rs @@ -1,15 +1,8 @@ use std::{env, process}; use wasi_tests::{assert_errno, create_file, open_scratch_directory, TESTCONFIG}; -const TEST_RIGHTS: wasi::Rights = wasi::RIGHTS_FD_READ - | wasi::RIGHTS_PATH_LINK_SOURCE - | wasi::RIGHTS_PATH_LINK_TARGET - | wasi::RIGHTS_FD_FILESTAT_GET - | wasi::RIGHTS_PATH_OPEN - | wasi::RIGHTS_PATH_UNLINK_FILE; - unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> wasi::Fd { - let file_fd = wasi::path_open(dir_fd, 0, name, flags, TEST_RIGHTS, TEST_RIGHTS, 0) + let file_fd = wasi::path_open(dir_fd, 0, name, flags, 0, 0, 0) .unwrap_or_else(|_| panic!("opening '{}'", name)); assert!( file_fd > libc::STDERR_FILENO as wasi::Fd, @@ -19,7 +12,7 @@ unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> w } unsafe fn open_link(dir_fd: wasi::Fd, name: &str) -> wasi::Fd { - let file_fd = wasi::path_open(dir_fd, 0, name, 0, TEST_RIGHTS, TEST_RIGHTS, 0) + let file_fd = wasi::path_open(dir_fd, 0, name, 0, 0, 0, 0) .unwrap_or_else(|_| panic!("opening a link '{}'", name)); assert!( file_fd > libc::STDERR_FILENO as wasi::Fd, diff --git a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs b/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs deleted file mode 100644 index 5cab9a033e8b..000000000000 --- a/crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::{env, process}; -use wasi_tests::{assert_errno, create_file, drop_rights, fd_get_rights, open_scratch_directory}; - -const TEST_FILENAME: &'static str = "file"; - -unsafe fn try_read_file(dir_fd: wasi::Fd) { - let fd = wasi::path_open(dir_fd, 0, TEST_FILENAME, 0, 0, 0, 0).expect("opening the file"); - - // Check that we don't have the right to exeucute fd_read - let (rbase, rinher) = fd_get_rights(fd); - assert_eq!( - rbase & wasi::RIGHTS_FD_READ, - 0, - "should not have base RIGHTS_FD_READ" - ); - assert_eq!( - rinher & wasi::RIGHTS_FD_READ, - 0, - "should not have inheriting RIGHTS_FD_READ" - ); - - let contents = &mut [0u8; 1]; - let iovec = wasi::Iovec { - buf: contents.as_mut_ptr() as *mut _, - buf_len: contents.len(), - }; - // Since we no longer have the right to fd_read, trying to read a file - // should be an error. - assert_errno!( - wasi::fd_read(fd, &[iovec]).expect_err("reading bytes from file should fail"), - wasi::ERRNO_BADF - ); -} - -unsafe fn test_read_rights(dir_fd: wasi::Fd) { - create_file(dir_fd, TEST_FILENAME); - drop_rights(dir_fd, wasi::RIGHTS_FD_READ, wasi::RIGHTS_FD_READ); - - let (rbase, rinher) = fd_get_rights(dir_fd); - assert_eq!( - rbase & wasi::RIGHTS_FD_READ, - 0, - "dir should not have base RIGHTS_FD_READ" - ); - assert_eq!( - rinher & wasi::RIGHTS_FD_READ, - 0, - "dir should not have inheriting RIGHTS_FD_READ" - ); - - try_read_file(dir_fd); -} - -fn main() { - let mut args = env::args(); - let prog = args.next().unwrap(); - let arg = if let Some(arg) = args.next() { - arg - } else { - eprintln!("usage: {} ", prog); - process::exit(1); - }; - - // Open scratch directory - let dir_fd = match open_scratch_directory(&arg) { - Ok(dir_fd) => dir_fd, - Err(err) => { - eprintln!("{}", err); - process::exit(1) - } - }; - - // Run the tests. - unsafe { test_read_rights(dir_fd) } -} diff --git a/crates/test-programs/wasi-tests/src/bin/poll_oneoff_files.rs b/crates/test-programs/wasi-tests/src/bin/poll_oneoff_files.rs index 8709fd8603d4..03539ea35de5 100644 --- a/crates/test-programs/wasi-tests/src/bin/poll_oneoff_files.rs +++ b/crates/test-programs/wasi-tests/src/bin/poll_oneoff_files.rs @@ -197,16 +197,8 @@ unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi::Fd) { wasi::fd_close(nonempty_file).expect("close"); // Now open the file for reading - let readable_fd = wasi::path_open( - dir_fd, - 0, - "readable_file", - 0, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_POLL_FD_READWRITE, - 0, - 0, - ) - .expect("opening a readable file"); + let readable_fd = wasi::path_open(dir_fd, 0, "readable_file", 0, wasi::RIGHTS_FD_READ, 0, 0) + .expect("opening a readable file"); assert!( readable_fd > libc::STDERR_FILENO as wasi::Fd, @@ -218,7 +210,7 @@ unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi::Fd) { 0, "writable_file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_POLL_FD_READWRITE, + wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/bin/read_empty_file.rs.disabled b/crates/test-programs/wasi-tests/src/bin/read_empty_file.rs.disabled new file mode 100644 index 000000000000..510466eaefe0 --- /dev/null +++ b/crates/test-programs/wasi-tests/src/bin/read_empty_file.rs.disabled @@ -0,0 +1,5 @@ +fn main() { + let mut file = std::fs::File::open("").unwrap(); + let mut buffer = Vec::new(); + std::io::Read::read_to_end(&mut file, &mut buffer).unwrap(); +} diff --git a/crates/test-programs/wasi-tests/src/bin/symlink_filestat.rs b/crates/test-programs/wasi-tests/src/bin/symlink_filestat.rs index f588149bfd50..cad9dcd6c034 100644 --- a/crates/test-programs/wasi-tests/src/bin/symlink_filestat.rs +++ b/crates/test-programs/wasi-tests/src/bin/symlink_filestat.rs @@ -2,20 +2,13 @@ use std::{env, process}; use wasi_tests::open_scratch_directory; unsafe fn test_path_filestat(dir_fd: wasi::Fd) { - let fdstat = wasi::fd_fdstat_get(dir_fd).expect("fd_fdstat_get"); - assert_ne!( - fdstat.fs_rights_base & wasi::RIGHTS_PATH_FILESTAT_GET, - 0, - "the scratch directory should have RIGHT_PATH_FILESTAT_GET as base right", - ); - // Create a file in the scratch directory. let file_fd = wasi::path_open( dir_fd, 0, "file", wasi::OFLAGS_CREAT, - wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_PATH_FILESTAT_GET, + wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE, 0, 0, ) diff --git a/crates/test-programs/wasi-tests/src/lib.rs b/crates/test-programs/wasi-tests/src/lib.rs index da6faf00e0c6..31174f12031d 100644 --- a/crates/test-programs/wasi-tests/src/lib.rs +++ b/crates/test-programs/wasi-tests/src/lib.rs @@ -27,11 +27,8 @@ pub fn open_scratch_directory(path: &str) -> Result { } dst.set_len(stat.u.dir.pr_name_len); if dst == path.as_bytes() { - let (base, inherit) = fd_get_rights(i); - return Ok( - wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0) - .expect("failed to open dir"), - ); + return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, 0, 0, 0) + .expect("failed to open dir")); } } @@ -49,21 +46,6 @@ pub unsafe fn create_file(dir_fd: wasi::Fd, filename: &str) { wasi::fd_close(file_fd).expect("closing a file"); } -// Returns: (rights_base, rights_inheriting) -pub unsafe fn fd_get_rights(fd: wasi::Fd) -> (wasi::Rights, wasi::Rights) { - let fdstat = wasi::fd_fdstat_get(fd).expect("fd_fdstat_get failed"); - (fdstat.fs_rights_base, fdstat.fs_rights_inheriting) -} - -pub unsafe fn drop_rights(fd: wasi::Fd, drop_base: wasi::Rights, drop_inheriting: wasi::Rights) { - let (current_base, current_inheriting) = fd_get_rights(fd); - - let new_base = current_base & !drop_base; - let new_inheriting = current_inheriting & !drop_inheriting; - - wasi::fd_fdstat_set_rights(fd, new_base, new_inheriting).expect("dropping fd rights"); -} - #[macro_export] macro_rules! assert_errno { ($s:expr, windows => $i:expr, $( $rest:tt )+) => { diff --git a/crates/wasi-common/cap-std-sync/src/lib.rs b/crates/wasi-common/cap-std-sync/src/lib.rs index fbaa7bbbd9d9..d26d25efb279 100644 --- a/crates/wasi-common/cap-std-sync/src/lib.rs +++ b/crates/wasi-common/cap-std-sync/src/lib.rs @@ -49,7 +49,7 @@ pub use sched::sched_ctx; use crate::net::Socket; use cap_rand::{Rng, RngCore, SeedableRng}; use std::path::Path; -use wasi_common::{file::FileCaps, table::Table, Error, WasiCtx, WasiFile}; +use wasi_common::{table::Table, Error, WasiCtx, WasiFile}; pub struct WasiCtxBuilder(WasiCtx); @@ -126,13 +126,7 @@ impl WasiCtxBuilder { pub fn preopened_socket(self, fd: u32, socket: impl Into) -> Result { let socket: Socket = socket.into(); let file: Box = socket.into(); - - let caps = FileCaps::FDSTAT_SET_FLAGS - | FileCaps::FILESTAT_GET - | FileCaps::READ - | FileCaps::POLL_READWRITE; - - self.0.insert_file(fd, file, caps); + self.0.insert_file(fd, file); Ok(self) } pub fn build(self) -> WasiCtx { diff --git a/crates/wasi-common/src/ctx.rs b/crates/wasi-common/src/ctx.rs index 6eabaa1fdee5..4b6bc8f6392f 100644 --- a/crates/wasi-common/src/ctx.rs +++ b/crates/wasi-common/src/ctx.rs @@ -1,6 +1,6 @@ use crate::clocks::WasiClocks; -use crate::dir::{DirCaps, DirEntry, WasiDir}; -use crate::file::{FileCaps, FileEntry, WasiFile}; +use crate::dir::{DirEntry, WasiDir}; +use crate::file::{FileEntry, WasiFile}; use crate::sched::WasiSched; use crate::string_array::StringArray; use crate::table::Table; @@ -51,38 +51,21 @@ impl WasiCtx { s } - pub fn insert_file(&self, fd: u32, file: Box, caps: FileCaps) { - self.table() - .insert_at(fd, Arc::new(FileEntry::new(caps, file))); + pub fn insert_file(&self, fd: u32, file: Box) { + self.table().insert_at(fd, Arc::new(FileEntry::new(file))); } - pub fn push_file(&self, file: Box, caps: FileCaps) -> Result { - self.table().push(Arc::new(FileEntry::new(caps, file))) + pub fn push_file(&self, file: Box) -> Result { + self.table().push(Arc::new(FileEntry::new(file))) } - pub fn insert_dir( - &self, - fd: u32, - dir: Box, - caps: DirCaps, - file_caps: FileCaps, - path: PathBuf, - ) { - self.table().insert_at( - fd, - Arc::new(DirEntry::new(caps, file_caps, Some(path), dir)), - ); + pub fn insert_dir(&self, fd: u32, dir: Box, path: PathBuf) { + self.table() + .insert_at(fd, Arc::new(DirEntry::new(Some(path), dir))); } - pub fn push_dir( - &self, - dir: Box, - caps: DirCaps, - file_caps: FileCaps, - path: PathBuf, - ) -> Result { - self.table() - .push(Arc::new(DirEntry::new(caps, file_caps, Some(path), dir))) + pub fn push_dir(&self, dir: Box, path: PathBuf) -> Result { + self.table().push(Arc::new(DirEntry::new(Some(path), dir))) } pub fn table(&self) -> &Table { @@ -108,32 +91,16 @@ impl WasiCtx { Ok(()) } - pub fn set_stdin(&self, mut f: Box) { - let rights = Self::stdio_rights(&mut *f); - self.insert_file(0, f, rights); - } - - pub fn set_stdout(&self, mut f: Box) { - let rights = Self::stdio_rights(&mut *f); - self.insert_file(1, f, rights); + pub fn set_stdin(&self, f: Box) { + self.insert_file(0, f); } - pub fn set_stderr(&self, mut f: Box) { - let rights = Self::stdio_rights(&mut *f); - self.insert_file(2, f, rights); + pub fn set_stdout(&self, f: Box) { + self.insert_file(1, f); } - fn stdio_rights(f: &mut dyn WasiFile) -> FileCaps { - let mut rights = FileCaps::all(); - - // If `f` is a tty, restrict the `tell` and `seek` capabilities, so - // that wasi-libc's `isatty` correctly detects the file descriptor - // as a tty. - if f.isatty() { - rights &= !(FileCaps::TELL | FileCaps::SEEK); - } - - rights + pub fn set_stderr(&self, f: Box) { + self.insert_file(2, f); } pub fn push_preopened_dir( @@ -141,14 +108,8 @@ impl WasiCtx { dir: Box, path: impl AsRef, ) -> Result<(), Error> { - let caps = DirCaps::all(); - let file_caps = FileCaps::all(); - self.table().push(Arc::new(DirEntry::new( - caps, - file_caps, - Some(path.as_ref().to_owned()), - dir, - )))?; + self.table() + .push(Arc::new(DirEntry::new(Some(path.as_ref().to_owned()), dir)))?; Ok(()) } } diff --git a/crates/wasi-common/src/dir.rs b/crates/wasi-common/src/dir.rs index f4e0cd1f1e35..e861d5316f74 100644 --- a/crates/wasi-common/src/dir.rs +++ b/crates/wasi-common/src/dir.rs @@ -1,9 +1,8 @@ -use crate::file::{FdFlags, FileCaps, FileType, Filestat, OFlags, WasiFile}; +use crate::file::{FdFlags, FileType, Filestat, OFlags, WasiFile}; use crate::{Error, ErrorExt, SystemTimeSpec}; -use bitflags::bitflags; use std::any::Any; use std::path::PathBuf; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; pub enum OpenResult { File(Box), @@ -96,123 +95,19 @@ pub trait WasiDir: Send + Sync { } pub(crate) struct DirEntry { - caps: RwLock, preopen_path: Option, // precondition: PathBuf is valid unicode - dir: Box, + pub dir: Box, } impl DirEntry { - pub fn new( - dir_caps: DirCaps, - file_caps: FileCaps, - preopen_path: Option, - dir: Box, - ) -> Self { - DirEntry { - caps: RwLock::new(DirFdStat { - dir_caps, - file_caps, - }), - preopen_path, - dir, - } - } - pub fn capable_of_dir(&self, caps: DirCaps) -> Result<(), Error> { - let fdstat = self.caps.read().unwrap(); - fdstat.capable_of_dir(caps) - } - - pub fn drop_caps_to(&self, dir_caps: DirCaps, file_caps: FileCaps) -> Result<(), Error> { - let mut fdstat = self.caps.write().unwrap(); - fdstat.capable_of_dir(dir_caps)?; - fdstat.capable_of_file(file_caps)?; - *fdstat = DirFdStat { - dir_caps, - file_caps, - }; - Ok(()) - } - pub fn child_dir_caps(&self, desired_caps: DirCaps) -> DirCaps { - self.caps.read().unwrap().dir_caps & desired_caps - } - pub fn child_file_caps(&self, desired_caps: FileCaps) -> FileCaps { - self.caps.read().unwrap().file_caps & desired_caps - } - pub fn get_dir_fdstat(&self) -> DirFdStat { - self.caps.read().unwrap().clone() + pub fn new(preopen_path: Option, dir: Box) -> Self { + DirEntry { preopen_path, dir } } pub fn preopen_path(&self) -> &Option { &self.preopen_path } } -pub trait DirEntryExt { - fn get_cap(&self, caps: DirCaps) -> Result<&dyn WasiDir, Error>; -} - -impl DirEntryExt for DirEntry { - fn get_cap(&self, caps: DirCaps) -> Result<&dyn WasiDir, Error> { - self.capable_of_dir(caps)?; - Ok(&*self.dir) - } -} - -bitflags! { - pub struct DirCaps: u32 { - const CREATE_DIRECTORY = 0b1; - const CREATE_FILE = 0b10; - const LINK_SOURCE = 0b100; - const LINK_TARGET = 0b1000; - const OPEN = 0b10000; - const READDIR = 0b100000; - const READLINK = 0b1000000; - const RENAME_SOURCE = 0b10000000; - const RENAME_TARGET = 0b100000000; - const SYMLINK = 0b1000000000; - const REMOVE_DIRECTORY = 0b10000000000; - const UNLINK_FILE = 0b100000000000; - const PATH_FILESTAT_GET = 0b1000000000000; - const PATH_FILESTAT_SET_TIMES = 0b10000000000000; - const FILESTAT_GET = 0b100000000000000; - const FILESTAT_SET_TIMES = 0b1000000000000000; - } -} - -#[derive(Debug, Clone)] -pub struct DirFdStat { - pub file_caps: FileCaps, - pub dir_caps: DirCaps, -} - -impl DirFdStat { - pub fn capable_of_dir(&self, caps: DirCaps) -> Result<(), Error> { - if self.dir_caps.contains(caps) { - Ok(()) - } else { - let missing = caps & !self.dir_caps; - let err = if missing.intersects(DirCaps::READDIR) { - Error::not_dir() - } else { - Error::perm() - }; - Err(err.context(format!( - "desired rights {:?}, has {:?}", - caps, self.dir_caps - ))) - } - } - pub fn capable_of_file(&self, caps: FileCaps) -> Result<(), Error> { - if self.file_caps.contains(caps) { - Ok(()) - } else { - Err(Error::perm().context(format!( - "desired rights {:?}, has {:?}", - caps, self.file_caps - ))) - } - } -} - pub(crate) trait TableDirExt { fn get_dir(&self, fd: u32) -> Result, Error>; } diff --git a/crates/wasi-common/src/file.rs b/crates/wasi-common/src/file.rs index 04ca215bcab6..8086a4ea6928 100644 --- a/crates/wasi-common/src/file.rs +++ b/crates/wasi-common/src/file.rs @@ -1,7 +1,7 @@ use crate::{Error, ErrorExt, SystemTimeSpec}; use bitflags::bitflags; use std::any::Any; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; #[wiggle::async_trait] pub trait WasiFile: Send + Sync { @@ -219,89 +219,25 @@ impl TableFileExt for crate::table::Table { } pub(crate) struct FileEntry { - caps: RwLock, - file: Box, + pub file: Box, } impl FileEntry { - pub fn new(caps: FileCaps, file: Box) -> Self { - FileEntry { - caps: RwLock::new(caps), - file, - } - } - - pub fn capable_of(&self, caps: FileCaps) -> Result<(), Error> { - if self.caps.read().unwrap().contains(caps) { - Ok(()) - } else { - let missing = caps & !(*self.caps.read().unwrap()); - let err = if missing.intersects(FileCaps::READ | FileCaps::WRITE) { - // `EBADF` is a little surprising here because it's also used - // for unknown-file-descriptor errors, but it's what POSIX uses - // in this situation. - Error::badf() - } else { - Error::perm() - }; - Err(err.context(format!("desired rights {:?}, has {:?}", caps, self.caps))) - } - } - - pub fn drop_caps_to(&self, caps: FileCaps) -> Result<(), Error> { - self.capable_of(caps)?; - *self.caps.write().unwrap() = caps; - Ok(()) + pub fn new(file: Box) -> Self { + FileEntry { file } } pub async fn get_fdstat(&self) -> Result { - let caps = self.caps.read().unwrap().clone(); Ok(FdStat { filetype: self.file.get_filetype().await?, - caps, flags: self.file.get_fdflags().await?, }) } } -pub trait FileEntryExt { - fn get_cap(&self, caps: FileCaps) -> Result<&dyn WasiFile, Error>; - fn get_cap_mut(&mut self, caps: FileCaps) -> Result<&mut dyn WasiFile, Error>; -} - -impl FileEntryExt for FileEntry { - fn get_cap(&self, caps: FileCaps) -> Result<&dyn WasiFile, Error> { - self.capable_of(caps)?; - Ok(&*self.file) - } - fn get_cap_mut(&mut self, caps: FileCaps) -> Result<&mut dyn WasiFile, Error> { - self.capable_of(caps)?; - Ok(&mut *self.file) - } -} - -bitflags! { - pub struct FileCaps : u32 { - const DATASYNC = 0b1; - const READ = 0b10; - const SEEK = 0b100; - const FDSTAT_SET_FLAGS = 0b1000; - const SYNC = 0b10000; - const TELL = 0b100000; - const WRITE = 0b1000000; - const ADVISE = 0b10000000; - const ALLOCATE = 0b100000000; - const FILESTAT_GET = 0b1000000000; - const FILESTAT_SET_SIZE = 0b10000000000; - const FILESTAT_SET_TIMES = 0b100000000000; - const POLL_READWRITE = 0b1000000000000; - } -} - #[derive(Debug, Clone)] pub struct FdStat { pub filetype: FileType, - pub caps: FileCaps, pub flags: FdFlags, } diff --git a/crates/wasi-common/src/snapshots/preview_0.rs b/crates/wasi-common/src/snapshots/preview_0.rs index 55dc08bd135a..d84ba5f3b715 100644 --- a/crates/wasi-common/src/snapshots/preview_0.rs +++ b/crates/wasi-common/src/snapshots/preview_0.rs @@ -1,4 +1,4 @@ -use crate::file::{FileCaps, FileEntryExt, TableFileExt}; +use crate::file::TableFileExt; use crate::sched::{ subscription::{RwEventFlags, SubscriptionResult}, Poll, Userdata, @@ -529,7 +529,6 @@ impl wasi_unstable::WasiUnstable for WasiCtx { iovs: &types::IovecArray<'a>, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ)?; let iovs: Vec> = iovs .iter() @@ -564,7 +563,10 @@ impl wasi_unstable::WasiUnstable for WasiCtx { let iov = iovs.into_iter().next(); if let Some(iov) = iov { let mut buffer = vec![0; (iov.len() as usize).min(MAX_SHARED_BUFFER_SIZE)]; - let bytes_read = f.read_vectored(&mut [IoSliceMut::new(&mut buffer)]).await?; + let bytes_read = f + .file + .read_vectored(&mut [IoSliceMut::new(&mut buffer)]) + .await?; iov.get_range(0..bytes_read.try_into()?) .expect("it should always be possible to slice the iov smaller") .copy_from_slice(&buffer[0..bytes_read.try_into()?])?; @@ -587,7 +589,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter_mut() .map(|s| IoSliceMut::new(&mut *s)) .collect(); - f.read_vectored(&mut ioslices).await? + f.file.read_vectored(&mut ioslices).await? }; Ok(types::Size::try_from(bytes_read)?) @@ -600,7 +602,6 @@ impl wasi_unstable::WasiUnstable for WasiCtx { offset: types::Filesize, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ | FileCaps::SEEK)?; let iovs: Vec> = iovs .iter() @@ -636,6 +637,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { if let Some(iov) = iov { let mut buffer = vec![0; (iov.len() as usize).min(MAX_SHARED_BUFFER_SIZE)]; let bytes_read = f + .file .read_vectored_at(&mut [IoSliceMut::new(&mut buffer)], offset) .await?; iov.get_range(0..bytes_read.try_into()?) @@ -660,7 +662,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter_mut() .map(|s| IoSliceMut::new(&mut *s)) .collect(); - f.read_vectored_at(&mut ioslices, offset).await? + f.file.read_vectored_at(&mut ioslices, offset).await? }; Ok(types::Size::try_from(bytes_read)?) @@ -672,7 +674,6 @@ impl wasi_unstable::WasiUnstable for WasiCtx { ciovs: &types::CiovecArray<'a>, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::WRITE)?; let guest_slices: Vec> = ciovs .iter() @@ -687,7 +688,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored(&ioslices).await?; + let bytes_written = f.file.write_vectored(&ioslices).await?; Ok(types::Size::try_from(bytes_written)?) } @@ -699,7 +700,6 @@ impl wasi_unstable::WasiUnstable for WasiCtx { offset: types::Filesize, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::WRITE | FileCaps::SEEK)?; let guest_slices: Vec> = ciovs .iter() @@ -714,7 +714,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored_at(&ioslices, offset).await?; + let bytes_written = f.file.write_vectored_at(&ioslices, offset).await?; Ok(types::Size::try_from(bytes_written)?) } @@ -991,9 +991,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { } else { sub_fds.insert(fd); } - table - .get_file(u32::from(fd))? - .get_cap(FileCaps::POLL_READWRITE)?; + table.get_file(u32::from(fd))?; reads.push((u32::from(fd), sub.userdata.into())); } types::SubscriptionU::FdWrite(writesub) => { @@ -1004,9 +1002,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { } else { sub_fds.insert(fd); } - table - .get_file(u32::from(fd))? - .get_cap(FileCaps::POLL_READWRITE)?; + table.get_file(u32::from(fd))?; writes.push((u32::from(fd), sub.userdata.into())); } } diff --git a/crates/wasi-common/src/snapshots/preview_1.rs b/crates/wasi-common/src/snapshots/preview_1.rs index dcda64d06ab2..ef54c0e448cc 100644 --- a/crates/wasi-common/src/snapshots/preview_1.rs +++ b/crates/wasi-common/src/snapshots/preview_1.rs @@ -1,11 +1,8 @@ use crate::{ - dir::{ - DirCaps, DirEntry, DirEntryExt, DirFdStat, OpenResult, ReaddirCursor, ReaddirEntity, - TableDirExt, - }, + dir::{DirEntry, OpenResult, ReaddirCursor, ReaddirEntity, TableDirExt}, file::{ - Advice, FdFlags, FdStat, FileCaps, FileEntry, FileEntryExt, FileType, Filestat, OFlags, - RiFlags, RoFlags, SdFlags, SiFlags, TableFileExt, WasiFile, + Advice, FdFlags, FdStat, FileEntry, FileType, Filestat, OFlags, RiFlags, RoFlags, SdFlags, + SiFlags, TableFileExt, WasiFile, }, sched::{ subscription::{RwEventFlags, SubscriptionResult}, @@ -117,7 +114,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_file(u32::from(fd))? - .get_cap(FileCaps::ADVISE)? + .file .advise(offset, len, advice.into()) .await?; Ok(()) @@ -131,10 +128,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { // Check if fd is a file, and has rights, just to reject those cases // with the errors expected: - let _ = self - .table() - .get_file(u32::from(fd))? - .get_cap(FileCaps::ALLOCATE)?; + let _ = self.table().get_file(u32::from(fd))?; // This operation from cloudabi is linux-specific, isn't even // supported across all linux filesystems, and has no support on macos // or windows. Rather than ship spotty support, it has been removed @@ -166,7 +160,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { async fn fd_datasync(&mut self, fd: types::Fd) -> Result<(), Error> { self.table() .get_file(u32::from(fd))? - .get_cap(FileCaps::DATASYNC)? + .file .datasync() .await?; Ok(()) @@ -180,9 +174,14 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let fdstat = file_entry.get_fdstat().await?; Ok(types::Fdstat::from(&fdstat)) } else if table.is::(fd) { - let dir_entry: Arc = table.get(fd)?; - let dir_fdstat = dir_entry.get_dir_fdstat(); - Ok(types::Fdstat::from(&dir_fdstat)) + let _dir_entry: Arc = table.get(fd)?; + let dir_fdstat = types::Fdstat { + fs_filetype: types::Filetype::Directory, + fs_rights_base: types::Rights::empty(), + fs_rights_inheriting: types::Rights::empty(), + fs_flags: types::Fdflags::empty(), + }; + Ok(dir_fdstat) } else { Err(Error::badf()) } @@ -196,7 +195,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { if let Some(table) = self.table_mut() { table .get_file_mut(u32::from(fd))? - .get_cap_mut(FileCaps::FDSTAT_SET_FLAGS)? + .file .set_fdflags(FdFlags::from(flags)) .await } else { @@ -208,20 +207,17 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { async fn fd_fdstat_set_rights( &mut self, fd: types::Fd, - fs_rights_base: types::Rights, - fs_rights_inheriting: types::Rights, + _fs_rights_base: types::Rights, + _fs_rights_inheriting: types::Rights, ) -> Result<(), Error> { let table = self.table(); let fd = u32::from(fd); if table.is::(fd) { - let file_entry: Arc = table.get(fd)?; - let file_caps = FileCaps::from(&fs_rights_base); - file_entry.drop_caps_to(file_caps) + let _file_entry: Arc = table.get(fd)?; + Ok(()) } else if table.is::(fd) { - let dir_entry: Arc = table.get(fd)?; - let dir_caps = DirCaps::from(&fs_rights_base); - let file_caps = FileCaps::from(&fs_rights_inheriting); - dir_entry.drop_caps_to(dir_caps, file_caps) + let _dir_entry: Arc = table.get(fd)?; + Ok(()) } else { Err(Error::badf()) } @@ -231,18 +227,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let table = self.table(); let fd = u32::from(fd); if table.is::(fd) { - let filestat = table - .get_file(fd)? - .get_cap(FileCaps::FILESTAT_GET)? - .get_filestat() - .await?; + let filestat = table.get_file(fd)?.file.get_filestat().await?; Ok(filestat.into()) } else if table.is::(fd) { - let filestat = table - .get_dir(fd)? - .get_cap(DirCaps::FILESTAT_GET)? - .get_filestat() - .await?; + let filestat = table.get_dir(fd)?.dir.get_filestat().await?; Ok(filestat.into()) } else { Err(Error::badf()) @@ -256,7 +244,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_file(u32::from(fd))? - .get_cap(FileCaps::FILESTAT_SET_SIZE)? + .file .set_filestat_size(size) .await?; Ok(()) @@ -284,14 +272,14 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { table .get_file(fd) .expect("checked that entry is file") - .get_cap(FileCaps::FILESTAT_SET_TIMES)? + .file .set_times(atim, mtim) .await } else if table.is::(fd) { table .get_dir(fd) .expect("checked that entry is dir") - .get_cap(DirCaps::FILESTAT_SET_TIMES)? + .dir .set_times(".", atim, mtim, false) .await } else { @@ -305,7 +293,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { iovs: &types::IovecArray<'a>, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ)?; + let f = &f.file; let iovs: Vec> = iovs .iter() @@ -376,7 +364,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { offset: types::Filesize, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ | FileCaps::SEEK)?; + let f = &f.file; let iovs: Vec> = iovs .iter() @@ -448,7 +436,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ciovs: &types::CiovecArray<'a>, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::WRITE)?; + let f = &f.file; let guest_slices: Vec> = ciovs .iter() @@ -475,7 +463,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { offset: types::Filesize, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::WRITE | FileCaps::SEEK)?; + let f = &f.file; let guest_slices: Vec> = ciovs .iter() @@ -547,13 +535,6 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { whence: types::Whence, ) -> Result { use std::io::SeekFrom; - - let required_caps = if offset == 0 && whence == types::Whence::Cur { - FileCaps::TELL - } else { - FileCaps::TELL | FileCaps::SEEK - }; - let whence = match whence { types::Whence::Cur => SeekFrom::Current(offset), types::Whence::End => SeekFrom::End(offset), @@ -562,27 +543,22 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let newoffset = self .table() .get_file(u32::from(fd))? - .get_cap(required_caps)? + .file .seek(whence) .await?; Ok(newoffset) } async fn fd_sync(&mut self, fd: types::Fd) -> Result<(), Error> { - self.table() - .get_file(u32::from(fd))? - .get_cap(FileCaps::SYNC)? - .sync() - .await?; + self.table().get_file(u32::from(fd))?.file.sync().await?; Ok(()) } async fn fd_tell(&mut self, fd: types::Fd) -> Result { - // XXX should this be stream_position? let offset = self .table() .get_file(u32::from(fd))? - .get_cap(FileCaps::TELL)? + .file .seek(std::io::SeekFrom::Current(0)) .await?; Ok(offset) @@ -600,7 +576,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { for entity in self .table() .get_dir(u32::from(fd))? - .get_cap(DirCaps::READDIR)? + .dir .readdir(ReaddirCursor::from(cookie)) .await? { @@ -649,7 +625,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::CREATE_DIRECTORY)? + .dir .create_dir(path.as_cow()?.deref()) .await } @@ -663,7 +639,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let filestat = self .table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::PATH_FILESTAT_GET)? + .dir .get_path_filestat( path.as_cow()?.deref(), flags.contains(types::Lookupflags::SYMLINK_FOLLOW), @@ -690,7 +666,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let mtim = systimespec(set_mtim, mtim, set_mtim_now).map_err(|e| e.context("mtim"))?; self.table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)? + .dir .set_times( path.as_cow()?.deref(), atim, @@ -710,9 +686,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { let table = self.table(); let src_dir = table.get_dir(u32::from(src_fd))?; - let src_dir = src_dir.get_cap(DirCaps::LINK_SOURCE)?; let target_dir = table.get_dir(u32::from(target_fd))?; - let target_dir = target_dir.get_cap(DirCaps::LINK_TARGET)?; let symlink_follow = src_flags.contains(types::Lookupflags::SYMLINK_FOLLOW); if symlink_follow { return Err(Error::invalid_argument() @@ -720,9 +694,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { } src_dir + .dir .hard_link( src_path.as_cow()?.deref(), - target_dir.deref(), + target_dir.dir.deref(), target_path.as_cow()?.deref(), ) .await @@ -735,7 +710,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { path: &GuestPtr<'a, str>, oflags: types::Oflags, fs_rights_base: types::Rights, - fs_rights_inheriting: types::Rights, + _fs_rights_inheriting: types::Rights, fdflags: types::Fdflags, ) -> Result { let table = self.table(); @@ -751,33 +726,17 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let fdflags = FdFlags::from(fdflags); let path = path.as_cow()?; - let mut required_caps = DirCaps::OPEN; - if oflags.contains(OFlags::CREATE) { - required_caps = required_caps | DirCaps::CREATE_FILE; - } - - let dir_dir_caps = dir_entry.child_dir_caps(DirCaps::from(&fs_rights_base)); - let dir_file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_inheriting)); - let file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_base)); - - let dir = dir_entry.get_cap(required_caps)?; - let read = file_caps.contains(FileCaps::READ); - let write = file_caps.contains(FileCaps::WRITE) - || file_caps.contains(FileCaps::ALLOCATE) - || file_caps.contains(FileCaps::FILESTAT_SET_SIZE); - let file = dir + let read = fs_rights_base.contains(types::Rights::FD_READ); + let write = fs_rights_base.contains(types::Rights::FD_WRITE); + let file = dir_entry + .dir .open_file(symlink_follow, path.deref(), oflags, read, write, fdflags) .await?; - drop(dir); + drop(dir_entry); let fd = match file { - OpenResult::File(file) => table.push(Arc::new(FileEntry::new(file_caps, file)))?, - OpenResult::Dir(child_dir) => table.push(Arc::new(DirEntry::new( - dir_dir_caps, - dir_file_caps, - None, - child_dir, - )))?, + OpenResult::File(file) => table.push(Arc::new(FileEntry::new(file)))?, + OpenResult::Dir(child_dir) => table.push(Arc::new(DirEntry::new(None, child_dir)))?, }; Ok(types::Fd::from(fd)) } @@ -792,7 +751,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let link = self .table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::READLINK)? + .dir .read_link(path.as_cow()?.deref()) .await? .into_os_string() @@ -814,7 +773,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::REMOVE_DIRECTORY)? + .dir .remove_dir(path.as_cow()?.deref()) .await } @@ -828,13 +787,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { let table = self.table(); let src_dir = table.get_dir(u32::from(src_fd))?; - let src_dir = src_dir.get_cap(DirCaps::RENAME_SOURCE)?; let dest_dir = table.get_dir(u32::from(dest_fd))?; - let dest_dir = dest_dir.get_cap(DirCaps::RENAME_TARGET)?; src_dir + .dir .rename( src_path.as_cow()?.deref(), - dest_dir.deref(), + dest_dir.dir.deref(), dest_path.as_cow()?.deref(), ) .await @@ -848,7 +806,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::SYMLINK)? + .dir .symlink(src_path.as_cow()?.deref(), dest_path.as_cow()?.deref()) .await } @@ -860,7 +818,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result<(), Error> { self.table() .get_dir(u32::from(dirfd))? - .get_cap(DirCaps::UNLINK_FILE)? + .dir .unlink_file(path.as_cow()?.deref()) .await } @@ -969,14 +927,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { types::SubscriptionU::FdRead(readsub) => { let fd = readsub.file_descriptor; let file_ref = table.get_file(u32::from(fd))?; - let _file = file_ref.get_cap(FileCaps::POLL_READWRITE)?; - read_refs.push((file_ref, Some(sub.userdata.into()))); } types::SubscriptionU::FdWrite(writesub) => { let fd = writesub.file_descriptor; let file_ref = table.get_file(u32::from(fd))?; - let _file = file_ref.get_cap(FileCaps::POLL_READWRITE)?; write_refs.push((file_ref, Some(sub.userdata.into()))); } } @@ -984,8 +939,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let mut read_mut_refs: Vec<(&dyn WasiFile, Userdata)> = Vec::new(); for (file_lock, userdata) in read_refs.iter_mut() { - let file = file_lock.get_cap(FileCaps::POLL_READWRITE)?; - read_mut_refs.push((file, userdata.take().unwrap())); + read_mut_refs.push((file_lock.file.deref(), userdata.take().unwrap())); } for (f, ud) in read_mut_refs.iter_mut() { @@ -994,8 +948,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let mut write_mut_refs: Vec<(&dyn WasiFile, Userdata)> = Vec::new(); for (file_lock, userdata) in write_refs.iter_mut() { - let file = file_lock.get_cap(FileCaps::POLL_READWRITE)?; - write_mut_refs.push((file, userdata.take().unwrap())); + write_mut_refs.push((file_lock.file.deref(), userdata.take().unwrap())); } for (f, ud) in write_mut_refs.iter_mut() { @@ -1133,16 +1086,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ) -> Result { let table = self.table(); let f = table.get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ)?; - - let file = f.sock_accept(FdFlags::from(flags)).await?; - let file_caps = FileCaps::READ - | FileCaps::WRITE - | FileCaps::FDSTAT_SET_FLAGS - | FileCaps::POLL_READWRITE - | FileCaps::FILESTAT_GET; - - let fd = table.push(Arc::new(FileEntry::new(file_caps, file)))?; + let file = f.file.sock_accept(FdFlags::from(flags)).await?; + let fd = table.push(Arc::new(FileEntry::new(file)))?; Ok(types::Fd::from(fd)) } @@ -1153,7 +1098,6 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { ri_flags: types::Riflags, ) -> Result<(types::Size, types::Roflags), Error> { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::READ)?; let iovs: Vec> = ri_data .iter() @@ -1189,6 +1133,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { if let Some(iov) = iov { let mut buffer = vec![0; (iov.len() as usize).min(MAX_SHARED_BUFFER_SIZE)]; let (bytes_read, ro_flags) = f + .file .sock_recv(&mut [IoSliceMut::new(&mut buffer)], RiFlags::from(ri_flags)) .await?; iov.get_range(0..bytes_read.try_into()?) @@ -1213,7 +1158,9 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .iter_mut() .map(|s| IoSliceMut::new(&mut *s)) .collect(); - f.sock_recv(&mut ioslices, RiFlags::from(ri_flags)).await? + f.file + .sock_recv(&mut ioslices, RiFlags::from(ri_flags)) + .await? }; Ok((types::Size::try_from(bytes_read)?, ro_flags.into())) @@ -1226,7 +1173,6 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { _si_flags: types::Siflags, ) -> Result { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::WRITE)?; let guest_slices: Vec> = si_data .iter() @@ -1241,16 +1187,15 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.sock_send(&ioslices, SiFlags::empty()).await?; + let bytes_written = f.file.sock_send(&ioslices, SiFlags::empty()).await?; Ok(types::Size::try_from(bytes_written)?) } async fn sock_shutdown(&mut self, fd: types::Fd, how: types::Sdflags) -> Result<(), Error> { let f = self.table().get_file(u32::from(fd))?; - let f = f.get_cap(FileCaps::FDSTAT_SET_FLAGS)?; - f.sock_shutdown(SdFlags::from(how)).await + f.file.sock_shutdown(SdFlags::from(how)).await } } @@ -1271,232 +1216,13 @@ impl From<&FdStat> for types::Fdstat { fn from(fdstat: &FdStat) -> types::Fdstat { types::Fdstat { fs_filetype: types::Filetype::from(&fdstat.filetype), - fs_rights_base: types::Rights::from(&fdstat.caps), + fs_rights_base: types::Rights::empty(), fs_rights_inheriting: types::Rights::empty(), fs_flags: types::Fdflags::from(fdstat.flags), } } } -impl From<&DirFdStat> for types::Fdstat { - fn from(dirstat: &DirFdStat) -> types::Fdstat { - let fs_rights_base = types::Rights::from(&dirstat.dir_caps); - let fs_rights_inheriting = types::Rights::from(&dirstat.file_caps) | fs_rights_base; - types::Fdstat { - fs_filetype: types::Filetype::Directory, - fs_rights_base, - fs_rights_inheriting, - fs_flags: types::Fdflags::empty(), - } - } -} - -// FileCaps can always be represented as wasi Rights -impl From<&FileCaps> for types::Rights { - fn from(caps: &FileCaps) -> types::Rights { - let mut rights = types::Rights::empty(); - if caps.contains(FileCaps::DATASYNC) { - rights = rights | types::Rights::FD_DATASYNC; - } - if caps.contains(FileCaps::READ) { - rights = rights | types::Rights::FD_READ; - } - if caps.contains(FileCaps::SEEK) { - rights = rights | types::Rights::FD_SEEK; - } - if caps.contains(FileCaps::FDSTAT_SET_FLAGS) { - rights = rights | types::Rights::FD_FDSTAT_SET_FLAGS; - } - if caps.contains(FileCaps::SYNC) { - rights = rights | types::Rights::FD_SYNC; - } - if caps.contains(FileCaps::TELL) { - rights = rights | types::Rights::FD_TELL; - } - if caps.contains(FileCaps::WRITE) { - rights = rights | types::Rights::FD_WRITE; - } - if caps.contains(FileCaps::ADVISE) { - rights = rights | types::Rights::FD_ADVISE; - } - if caps.contains(FileCaps::ALLOCATE) { - rights = rights | types::Rights::FD_ALLOCATE; - } - if caps.contains(FileCaps::FILESTAT_GET) { - rights = rights | types::Rights::FD_FILESTAT_GET; - } - if caps.contains(FileCaps::FILESTAT_SET_SIZE) { - rights = rights | types::Rights::FD_FILESTAT_SET_SIZE; - } - if caps.contains(FileCaps::FILESTAT_SET_TIMES) { - rights = rights | types::Rights::FD_FILESTAT_SET_TIMES; - } - if caps.contains(FileCaps::POLL_READWRITE) { - rights = rights | types::Rights::POLL_FD_READWRITE; - } - rights - } -} - -// FileCaps are a subset of wasi Rights - not all Rights have a valid representation as FileCaps -impl From<&types::Rights> for FileCaps { - fn from(rights: &types::Rights) -> FileCaps { - let mut caps = FileCaps::empty(); - if rights.contains(types::Rights::FD_DATASYNC) { - caps = caps | FileCaps::DATASYNC; - } - if rights.contains(types::Rights::FD_READ) { - caps = caps | FileCaps::READ; - } - if rights.contains(types::Rights::FD_SEEK) { - caps = caps | FileCaps::SEEK; - } - if rights.contains(types::Rights::FD_FDSTAT_SET_FLAGS) { - caps = caps | FileCaps::FDSTAT_SET_FLAGS; - } - if rights.contains(types::Rights::FD_SYNC) { - caps = caps | FileCaps::SYNC; - } - if rights.contains(types::Rights::FD_TELL) { - caps = caps | FileCaps::TELL; - } - if rights.contains(types::Rights::FD_WRITE) { - caps = caps | FileCaps::WRITE; - } - if rights.contains(types::Rights::FD_ADVISE) { - caps = caps | FileCaps::ADVISE; - } - if rights.contains(types::Rights::FD_ALLOCATE) { - caps = caps | FileCaps::ALLOCATE; - } - if rights.contains(types::Rights::FD_FILESTAT_GET) { - caps = caps | FileCaps::FILESTAT_GET; - } - if rights.contains(types::Rights::FD_FILESTAT_SET_SIZE) { - caps = caps | FileCaps::FILESTAT_SET_SIZE; - } - if rights.contains(types::Rights::FD_FILESTAT_SET_TIMES) { - caps = caps | FileCaps::FILESTAT_SET_TIMES; - } - if rights.contains(types::Rights::POLL_FD_READWRITE) { - caps = caps | FileCaps::POLL_READWRITE; - } - caps - } -} - -// DirCaps can always be represented as wasi Rights -impl From<&DirCaps> for types::Rights { - fn from(caps: &DirCaps) -> types::Rights { - let mut rights = types::Rights::empty(); - if caps.contains(DirCaps::CREATE_DIRECTORY) { - rights = rights | types::Rights::PATH_CREATE_DIRECTORY; - } - if caps.contains(DirCaps::CREATE_FILE) { - rights = rights | types::Rights::PATH_CREATE_FILE; - } - if caps.contains(DirCaps::LINK_SOURCE) { - rights = rights | types::Rights::PATH_LINK_SOURCE; - } - if caps.contains(DirCaps::LINK_TARGET) { - rights = rights | types::Rights::PATH_LINK_TARGET; - } - if caps.contains(DirCaps::OPEN) { - rights = rights | types::Rights::PATH_OPEN; - } - if caps.contains(DirCaps::READDIR) { - rights = rights | types::Rights::FD_READDIR; - } - if caps.contains(DirCaps::READLINK) { - rights = rights | types::Rights::PATH_READLINK; - } - if caps.contains(DirCaps::RENAME_SOURCE) { - rights = rights | types::Rights::PATH_RENAME_SOURCE; - } - if caps.contains(DirCaps::RENAME_TARGET) { - rights = rights | types::Rights::PATH_RENAME_TARGET; - } - if caps.contains(DirCaps::SYMLINK) { - rights = rights | types::Rights::PATH_SYMLINK; - } - if caps.contains(DirCaps::REMOVE_DIRECTORY) { - rights = rights | types::Rights::PATH_REMOVE_DIRECTORY; - } - if caps.contains(DirCaps::UNLINK_FILE) { - rights = rights | types::Rights::PATH_UNLINK_FILE; - } - if caps.contains(DirCaps::PATH_FILESTAT_GET) { - rights = rights | types::Rights::PATH_FILESTAT_GET; - } - if caps.contains(DirCaps::PATH_FILESTAT_SET_TIMES) { - rights = rights | types::Rights::PATH_FILESTAT_SET_TIMES; - } - if caps.contains(DirCaps::FILESTAT_GET) { - rights = rights | types::Rights::FD_FILESTAT_GET; - } - if caps.contains(DirCaps::FILESTAT_SET_TIMES) { - rights = rights | types::Rights::FD_FILESTAT_SET_TIMES; - } - rights - } -} - -// DirCaps are a subset of wasi Rights - not all Rights have a valid representation as DirCaps -impl From<&types::Rights> for DirCaps { - fn from(rights: &types::Rights) -> DirCaps { - let mut caps = DirCaps::empty(); - if rights.contains(types::Rights::PATH_CREATE_DIRECTORY) { - caps = caps | DirCaps::CREATE_DIRECTORY; - } - if rights.contains(types::Rights::PATH_CREATE_FILE) { - caps = caps | DirCaps::CREATE_FILE; - } - if rights.contains(types::Rights::PATH_LINK_SOURCE) { - caps = caps | DirCaps::LINK_SOURCE; - } - if rights.contains(types::Rights::PATH_LINK_TARGET) { - caps = caps | DirCaps::LINK_TARGET; - } - if rights.contains(types::Rights::PATH_OPEN) { - caps = caps | DirCaps::OPEN; - } - if rights.contains(types::Rights::FD_READDIR) { - caps = caps | DirCaps::READDIR; - } - if rights.contains(types::Rights::PATH_READLINK) { - caps = caps | DirCaps::READLINK; - } - if rights.contains(types::Rights::PATH_RENAME_SOURCE) { - caps = caps | DirCaps::RENAME_SOURCE; - } - if rights.contains(types::Rights::PATH_RENAME_TARGET) { - caps = caps | DirCaps::RENAME_TARGET; - } - if rights.contains(types::Rights::PATH_SYMLINK) { - caps = caps | DirCaps::SYMLINK; - } - if rights.contains(types::Rights::PATH_REMOVE_DIRECTORY) { - caps = caps | DirCaps::REMOVE_DIRECTORY; - } - if rights.contains(types::Rights::PATH_UNLINK_FILE) { - caps = caps | DirCaps::UNLINK_FILE; - } - if rights.contains(types::Rights::PATH_FILESTAT_GET) { - caps = caps | DirCaps::PATH_FILESTAT_GET; - } - if rights.contains(types::Rights::PATH_FILESTAT_SET_TIMES) { - caps = caps | DirCaps::PATH_FILESTAT_SET_TIMES; - } - if rights.contains(types::Rights::FD_FILESTAT_GET) { - caps = caps | DirCaps::FILESTAT_GET; - } - if rights.contains(types::Rights::FD_FILESTAT_SET_TIMES) { - caps = caps | DirCaps::FILESTAT_SET_TIMES; - } - caps - } -} - impl From<&FileType> for types::Filetype { fn from(ft: &FileType) -> types::Filetype { match ft { diff --git a/crates/wasi-common/tokio/src/lib.rs b/crates/wasi-common/tokio/src/lib.rs index 1c7a1decb300..5a17b17816bb 100644 --- a/crates/wasi-common/tokio/src/lib.rs +++ b/crates/wasi-common/tokio/src/lib.rs @@ -11,13 +11,11 @@ use std::path::Path; pub use wasi_cap_std_sync::{clocks_ctx, random_ctx}; use wasi_common::{Error, Table, WasiCtx, WasiFile}; +use crate::sched::sched_ctx; pub use dir::Dir; pub use file::File; pub use net::*; use wasi_cap_std_sync::net::Socket; -use wasi_common::file::FileCaps; - -use crate::sched::sched_ctx; pub struct WasiCtxBuilder(WasiCtx); @@ -98,13 +96,7 @@ impl WasiCtxBuilder { pub fn preopened_socket(self, fd: u32, socket: impl Into) -> Result { let socket: Socket = socket.into(); let file: Box = socket.into(); - - let caps = FileCaps::FDSTAT_SET_FLAGS - | FileCaps::FILESTAT_GET - | FileCaps::READ - | FileCaps::POLL_READWRITE; - - self.0.insert_file(fd, file, caps); + self.0.insert_file(fd, file); Ok(self) }