From 6fe3719e8e84c6b526998d19a2a36452ce7f0c07 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 11 Sep 2019 14:25:53 -0700 Subject: [PATCH 1/2] Add test for closing wasi preopen fd --- .../tests/wasitests/close_preopen_fd.rs | 14 ++++ lib/wasi-tests/tests/wasitests/mod.rs | 1 + lib/wasi-tests/wasitests/close_preopen_fd.out | 3 + lib/wasi-tests/wasitests/close_preopen_fd.rs | 44 ++++++++++++ .../wasitests/close_preopen_fd.wasm | Bin 0 -> 71464 bytes lib/wasi/src/state/mod.rs | 65 ++++++++++++++++-- lib/wasi/src/syscalls/mod.rs | 22 ++---- 7 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 lib/wasi-tests/tests/wasitests/close_preopen_fd.rs create mode 100644 lib/wasi-tests/wasitests/close_preopen_fd.out create mode 100644 lib/wasi-tests/wasitests/close_preopen_fd.rs create mode 100755 lib/wasi-tests/wasitests/close_preopen_fd.wasm diff --git a/lib/wasi-tests/tests/wasitests/close_preopen_fd.rs b/lib/wasi-tests/tests/wasitests/close_preopen_fd.rs new file mode 100644 index 00000000000..616ab1d6e2c --- /dev/null +++ b/lib/wasi-tests/tests/wasitests/close_preopen_fd.rs @@ -0,0 +1,14 @@ +#[test] +fn test_close_preopen_fd() { + assert_wasi_output!( + "../../wasitests/close_preopen_fd.wasm", + "close_preopen_fd", + vec![], + vec![( + "hamlet".to_string(), + ::std::path::PathBuf::from("wasitests/test_fs/hamlet") + ),], + vec![], + "../../wasitests/close_preopen_fd.out" + ); +} diff --git a/lib/wasi-tests/tests/wasitests/mod.rs b/lib/wasi-tests/tests/wasitests/mod.rs index 2849ccd5e68..e469511fdf8 100644 --- a/lib/wasi-tests/tests/wasitests/mod.rs +++ b/lib/wasi-tests/tests/wasitests/mod.rs @@ -5,6 +5,7 @@ // The _common module is not autogenerated. It provides common macros for the wasitests #[macro_use] mod _common; +mod close_preopen_fd; mod create_dir; mod envvar; mod fd_allocate; diff --git a/lib/wasi-tests/wasitests/close_preopen_fd.out b/lib/wasi-tests/wasitests/close_preopen_fd.out new file mode 100644 index 00000000000..e6e9b9f6737 --- /dev/null +++ b/lib/wasi-tests/wasitests/close_preopen_fd.out @@ -0,0 +1,3 @@ +accessing preopen fd was a success +Closing preopen fd was a success +accessing closed preopen fd was an EBADF error: true diff --git a/lib/wasi-tests/wasitests/close_preopen_fd.rs b/lib/wasi-tests/wasitests/close_preopen_fd.rs new file mode 100644 index 00000000000..ba0a875617d --- /dev/null +++ b/lib/wasi-tests/wasitests/close_preopen_fd.rs @@ -0,0 +1,44 @@ +// Args: +// mapdir: hamlet:wasitests/test_fs/hamlet + +use std::fs; +use std::path::PathBuf; + +#[cfg(target_os = "wasi")] +#[link(wasm_import_module = "wasi_unstable")] +extern "C" { + fn fd_close(fd: u32) -> u16; + fn fd_fdstat_set_flags(fd: u32, flags: u16) -> u16; +} + +const FIRST_PREOPEN_FD: u32 = 4; + +fn main() { + #[cfg(target_os = "wasi")] + { + let result = unsafe { fd_fdstat_set_flags(FIRST_PREOPEN_FD, 1 << 2) }; + println!( + "accessing preopen fd was a {}", + if result == 0 { "success" } else { "failure" } + ); + + let result = unsafe { fd_close(FIRST_PREOPEN_FD) }; + println!( + "Closing preopen fd was a {}", + if result == 0 { "success" } else { "failure" } + ); + + let result = unsafe { fd_fdstat_set_flags(FIRST_PREOPEN_FD, 1 << 2) }; + println!( + "accessing closed preopen fd was an EBADF error: {}", + if result == 8 { "true" } else { "false" } + ); + } + + #[cfg(not(target_os = "wasi"))] + { + println!("accessing preopen fd was a success"); + println!("Closing preopen fd was a success"); + println!("accessing closed preopen fd was an EBADF error: true"); + } +} diff --git a/lib/wasi-tests/wasitests/close_preopen_fd.wasm b/lib/wasi-tests/wasitests/close_preopen_fd.wasm new file mode 100755 index 0000000000000000000000000000000000000000..7b69083506e90e95ec1b5cacc5a893d6afd661f9 GIT binary patch literal 71464 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 literal 0 HcmV?d00001 diff --git a/lib/wasi/src/state/mod.rs b/lib/wasi/src/state/mod.rs index 64a5aee84ca..f8a73da3eca 100644 --- a/lib/wasi/src/state/mod.rs +++ b/lib/wasi/src/state/mod.rs @@ -664,7 +664,7 @@ impl WasiFs { // even if it's false, it still follows symlinks, just not the last // symlink so // This will be resolved when we have tests asserting the correct behavior - pub fn get_inode_at_path( + pub(crate) fn get_inode_at_path( &mut self, base: __wasi_fd_t, path: &str, @@ -675,7 +675,7 @@ impl WasiFs { /// Returns the parent Dir or Root that the file at a given path is in and the file name /// stripped off - pub fn get_parent_inode_at_path( + pub(crate) fn get_parent_inode_at_path( &mut self, base: __wasi_fd_t, path: &Path, @@ -787,7 +787,7 @@ impl WasiFs { } /// Creates an inode and inserts it given a Kind and some extra data - pub fn create_inode( + pub(crate) fn create_inode( &mut self, kind: Kind, is_preopened: bool, @@ -805,7 +805,7 @@ impl WasiFs { } /// creates an inode and inserts it given a Kind, does not assume the file exists to - pub fn create_inode_with_default_stat( + pub(crate) fn create_inode_with_default_stat( &mut self, kind: Kind, is_preopened: bool, @@ -849,7 +849,7 @@ impl WasiFs { /// This function is unsafe because it's the caller's responsibility to ensure that /// all refences to the given inode have been removed from the filesystem /// - /// returns true if the inode existed and was removed + /// returns the inode if it existed and was removed pub unsafe fn remove_inode(&mut self, inode: Inode) -> Option { self.inodes.remove(inode) } @@ -941,6 +941,61 @@ impl WasiFs { ..__wasi_filestat_t::default() }) } + + /// Closes an open FD, handling all details such as FD being preopen + pub(crate) fn close_fd(&mut self, fd: __wasi_fd_t) -> Result<(), __wasi_errno_t> { + let inodeval_mut = self.get_inodeval_mut(fd)?; + let is_preopened = inodeval_mut.is_preopened; + + match &mut inodeval_mut.kind { + Kind::File { ref mut handle, .. } => { + let mut empty_handle = None; + std::mem::swap(handle, &mut empty_handle); + } + Kind::Dir { parent, path, .. } => { + debug!("Closing dir {:?}", &path); + let key = path + .file_name() + .ok_or(__WASI_EINVAL)? + .to_string_lossy() + .to_string(); + if let Some(p) = parent.clone() { + match &mut self.inodes[p].kind { + Kind::Dir { entries, .. } | Kind::Root { entries } => { + self.fd_map.remove(&fd).unwrap(); + if is_preopened { + let mut idx = None; + for (i, po_fd) in self.preopen_fds.iter().enumerate() { + if *po_fd == fd { + idx = Some(i); + break; + } + } + if let Some(i) = idx { + // only remove entry properly if this is the original preopen FD + // calling `path_open` can give you an fd to the same inode as a preopen fd + entries.remove(&key); + self.preopen_fds.remove(i); + // Maybe recursively closes fds if og preopen? + } + } + } + _ => unreachable!( + "Fatal internal logic error, directory's parent is not a directory" + ), + } + } else { + // this shouldn't be possible anymore due to Root + debug!("HIT UNREACHABLE CODE! Non-root directory does not have a parent"); + return Err(__WASI_EINVAL); + } + } + Kind::Root { .. } => return Err(__WASI_EACCES), + Kind::Symlink { .. } | Kind::Buffer { .. } => return Err(__WASI_EINVAL), + } + + Ok(()) + } } #[derive(Debug, Serialize, Deserialize)] diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 9801d4ac048..28c7efac4b0 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -374,23 +374,11 @@ pub fn fd_allocate( /// If `fd` is invalid or not open pub fn fd_close(ctx: &mut Ctx, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_close"); - - let memory = ctx.memory(0); let state = get_wasi_state(ctx); - let inode_val = wasi_try!(state.fs.get_inodeval_mut(fd)); - if inode_val.is_preopened { - return __WASI_EACCES; - } - match &mut inode_val.kind { - Kind::File { ref mut handle, .. } => { - let mut empty_handle = None; - std::mem::swap(handle, &mut empty_handle); - } - Kind::Dir { .. } => return __WASI_EISDIR, - Kind::Root { .. } => return __WASI_EACCES, - Kind::Symlink { .. } | Kind::Buffer { .. } => return __WASI_EINVAL, - } + let fd_entry = wasi_try!(state.fs.get_fd(fd)).clone(); + + wasi_try!(state.fs.close_fd(fd)); __WASI_ESUCCESS } @@ -1666,9 +1654,6 @@ pub fn path_open( dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0, ); - if let Ok(m) = maybe_inode { - &state.fs.inodes[m]; - } let mut open_flags = 0; // TODO: traverse rights of dirs properly @@ -1820,6 +1805,7 @@ pub fn path_open( )); fd_cell.set(out_fd); + debug!("wasi::path_open returning fd {}", out_fd); __WASI_ESUCCESS } From 35ee83d5ca27e3d196bd7968aeeebe3b379cfcbc Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 11 Sep 2019 16:31:43 -0700 Subject: [PATCH 2/2] og -> original --- lib/wasi/src/state/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wasi/src/state/mod.rs b/lib/wasi/src/state/mod.rs index f8a73da3eca..aff57ff9a96 100644 --- a/lib/wasi/src/state/mod.rs +++ b/lib/wasi/src/state/mod.rs @@ -976,7 +976,7 @@ impl WasiFs { // calling `path_open` can give you an fd to the same inode as a preopen fd entries.remove(&key); self.preopen_fds.remove(i); - // Maybe recursively closes fds if og preopen? + // Maybe recursively closes fds if original preopen? } } }