From 69fd76af104007a5b2be5444ea88f70e78a2c2c2 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 4 Mar 2020 11:48:32 -0800 Subject: [PATCH] Improve support for preopened directories in WASI syscalls Also filters our default logging more and improves some debug statements --- CHANGELOG.md | 1 + lib/wasi/src/state/mod.rs | 9 +++++++ lib/wasi/src/syscalls/mod.rs | 50 ++++++++++++++++++++++++++---------- src/logging.rs | 6 ++++- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b13ac7a7a..29cb90abf1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## **[Unreleased]** +- [#1263](https://github.com/wasmerio/wasmer/pull/1263) Changed the behavior of some WASI syscalls to now handle preopened directories more properly. Changed default `--debug` logging to only show Wasmer-related messages. - [#1217](https://github.com/wasmerio/wasmer/pull/1217) Polymorphic host functions based on dynamic trampoline generation. - [#1252](https://github.com/wasmerio/wasmer/pull/1252) Allow `/` in wasi `--mapdir` wasm path. - [#1212](https://github.com/wasmerio/wasmer/pull/1212) Add support for GDB JIT debugging: diff --git a/lib/wasi/src/state/mod.rs b/lib/wasi/src/state/mod.rs index f05c44b9124..5acf250b80e 100644 --- a/lib/wasi/src/state/mod.rs +++ b/lib/wasi/src/state/mod.rs @@ -1077,6 +1077,15 @@ impl WasiFs { fs_rights_inheriting: 0, }) } + VIRTUAL_ROOT_FD => { + return Ok(__wasi_fdstat_t { + fs_filetype: __WASI_FILETYPE_DIRECTORY, + fs_flags: 0, + // TODO: fix this + fs_rights_base: ALL_RIGHTS, + fs_rights_inheriting: ALL_RIGHTS, + }); + } _ => (), } let fd = self.get_fd(fd)?; diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index ea253968cc1..f8216afdb0e 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -370,8 +370,7 @@ pub fn fd_allocate( /// - `__WASI_EBADF` /// 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"); - debug!("=> fd={}", fd); + debug!("wasi::fd_close: fd={}", fd); let (memory, state) = get_memory_and_wasi_state(ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); @@ -649,7 +648,7 @@ pub fn fd_pread( offset: __wasi_filesize_t, nread: WasmPtr, ) -> __wasi_errno_t { - debug!("wasi::fd_pread"); + debug!("wasi::fd_pread: fd={}, offset={}", fd, offset); let (memory, state) = get_memory_and_wasi_state(ctx, 0); let iov_cells = wasi_try!(iovs.deref(memory, 0, iovs_len)); @@ -674,6 +673,10 @@ pub fn fd_pread( if !(has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) && has_rights(fd_entry.rights, __WASI_RIGHT_FD_SEEK)) { + debug!( + "Invalid rights on {:X}: expected READ and SEEK", + fd_entry.rights + ); return __WASI_EACCES; } match &mut state.fs.inodes[inode].kind { @@ -699,6 +702,7 @@ pub fn fd_pread( }; nread_cell.set(bytes_read); + debug!("Success: {} bytes read", bytes_read); __WASI_ESUCCESS } @@ -971,24 +975,38 @@ pub fn fd_readdir( let mut cur_cookie = cookie; let mut buf_idx = 0; - let entries = match &state.fs.inodes[working_dir.inode].kind { - Kind::Dir { path, .. } => { + let entries: Vec<(String, u8, u64)> = match &state.fs.inodes[working_dir.inode].kind { + Kind::Dir { path, entries, .. } => { // TODO: refactor this code // we need to support multiple calls, // simple and obviously correct implementation for now: // maintain consistent order via lexacographic sorting - let mut entries = wasi_try!(wasi_try!(std::fs::read_dir(path).map_err(|_| __WASI_EIO)) - .collect::, _>>() + let fs_info = wasi_try!(wasi_try!(std::fs::read_dir(path).map_err(|_| __WASI_EIO)) + .collect::, _>>() .map_err(|_| __WASI_EIO)); - entries.sort_by(|a, b| a.file_name().cmp(&b.file_name())); - wasi_try!(entries + let mut entry_vec = wasi_try!(fs_info .into_iter() .map(|entry| Ok(( entry.file_name().to_string_lossy().to_string(), host_file_type_to_wasi_file_type(entry.file_type().map_err(|_| __WASI_EIO)?), 0, // TODO: inode ))) - .collect::, __wasi_errno_t>>()) + .collect::, _>>()); + entry_vec.extend( + entries + .iter() + .filter(|(_, inode)| state.fs.inodes[**inode].is_preopened) + .map(|(name, inode)| { + let entry = &state.fs.inodes[*inode]; + ( + format!("{}", entry.name), + entry.stat.st_filetype, + entry.stat.st_ino, + ) + }), + ); + entry_vec.sort_by(|a, b| a.0.cmp(&b.0)); + entry_vec } Kind::Root { entries } => { let sorted_entries = { @@ -1435,10 +1453,14 @@ pub fn path_filestat_get( path_string, flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0, )); - let stat = wasi_try!(state - .fs - .get_stat_for_kind(&state.fs.inodes[file_inode].kind) - .ok_or(__WASI_EIO)); + let stat = if state.fs.inodes[file_inode].is_preopened { + state.fs.inodes[file_inode].stat.clone() + } else { + wasi_try!(state + .fs + .get_stat_for_kind(&state.fs.inodes[file_inode].kind) + .ok_or(__WASI_EIO)) + }; let buf_cell = wasi_try!(buf.deref(memory)); buf_cell.set(stat); diff --git a/src/logging.rs b/src/logging.rs index e9f8dbb6a02..0cc1530e4df 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -46,7 +46,11 @@ pub fn set_up_logging() -> Result<(), String> { }) }; - base.chain(std::io::stdout()) + base + .filter(|metadata| { + metadata.target().starts_with("wasmer") + }) + .chain(std::io::stdout()) }); dispatch.apply().map_err(|e| format!("{}", e))?;