mirror of
https://github.com/fluencelabs/wasmer
synced 2025-05-29 01:51:18 +00:00
Merge #463
463: Prevent parent directory from being opened without being preopened wasi r=MarkMcCaskey a=MarkMcCaskey resolves #462 Because the logic of opening a directory and traversing the tree are separate, we allowed one level of `..` to be opened beyond what was preopened The diff on github isn't clear, but this adds an if and then puts the previous logic in an else block Co-authored-by: Mark McCaskey <mark@wasmer.io>
This commit is contained in:
commit
dcf0a7cc4b
@ -6,6 +6,7 @@ Blocks of changes will separated by version increments.
|
|||||||
|
|
||||||
## **[Unreleased]**
|
## **[Unreleased]**
|
||||||
|
|
||||||
|
- [#463](https://github.com/wasmerio/wasmer/pull/463) Fix bug in WASI path_open allowing one level above preopened dir to be accessed
|
||||||
- [#461](https://github.com/wasmerio/wasmer/pull/461) Prevent passing negative lengths in various places in the runtime C API
|
- [#461](https://github.com/wasmerio/wasmer/pull/461) Prevent passing negative lengths in various places in the runtime C API
|
||||||
- [#459](https://github.com/wasmerio/wasmer/pull/459) Add monotonic and real time clocks for wasi on windows
|
- [#459](https://github.com/wasmerio/wasmer/pull/459) Add monotonic and real time clocks for wasi on windows
|
||||||
- [#447](https://github.com/wasmerio/wasmer/pull/447) Add trace macro (`--features trace`) for more verbose debug statements
|
- [#447](https://github.com/wasmerio/wasmer/pull/447) Add trace macro (`--features trace`) for more verbose debug statements
|
||||||
|
@ -1463,97 +1463,117 @@ pub fn path_open(
|
|||||||
"Looking for file {} in directory {:#?}",
|
"Looking for file {} in directory {:#?}",
|
||||||
file_name, cumulative_path
|
file_name, cumulative_path
|
||||||
);
|
);
|
||||||
|
|
||||||
cumulative_path.push(file_name);
|
cumulative_path.push(file_name);
|
||||||
let file_path = cumulative_path;
|
let file_path = cumulative_path;
|
||||||
|
|
||||||
let out_fd = if let Kind::Dir { entries, .. } = &mut state.fs.inodes[cur_dir_inode].kind {
|
let out_fd = if let Kind::Dir {
|
||||||
if let Some(child) = entries.get(file_name).cloned() {
|
entries, parent, ..
|
||||||
let child_inode_val = &state.fs.inodes[child];
|
} = &mut state.fs.inodes[cur_dir_inode].kind
|
||||||
// early return based on flags
|
{
|
||||||
if o_flags & __WASI_O_EXCL != 0 {
|
// short circuit logic if attempting to get parent
|
||||||
return __WASI_EEXIST;
|
if file_name == ".." {
|
||||||
}
|
if let Some(p) = parent {
|
||||||
if o_flags & __WASI_O_DIRECTORY != 0 {
|
let parent_inode = *p;
|
||||||
match &child_inode_val.kind {
|
wasi_try!(state.fs.create_fd(
|
||||||
Kind::Dir { .. } => (),
|
fs_rights_base,
|
||||||
Kind::Symlink { .. } => {
|
fs_rights_inheriting,
|
||||||
unimplemented!("Symlinks not yet supported in path_open")
|
fs_flags,
|
||||||
}
|
parent_inode
|
||||||
_ => return __WASI_ENOTDIR,
|
))
|
||||||
}
|
|
||||||
}
|
|
||||||
// do logic on child
|
|
||||||
wasi_try!(state
|
|
||||||
.fs
|
|
||||||
.create_fd(fs_rights_base, fs_rights_inheriting, fs_flags, child))
|
|
||||||
} else {
|
|
||||||
debug!("Attempting to load file from host system");
|
|
||||||
let file_metadata = file_path.metadata();
|
|
||||||
// if entry does not exist in parent directory, try to lazily
|
|
||||||
// load it; possibly creating or truncating it if flags set
|
|
||||||
let kind = if file_metadata.is_ok() && file_metadata.unwrap().is_dir() {
|
|
||||||
// special dir logic
|
|
||||||
Kind::Dir {
|
|
||||||
parent: Some(cur_dir_inode),
|
|
||||||
path: file_path.clone(),
|
|
||||||
entries: Default::default(),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// file is not a dir
|
return __WASI_EACCES;
|
||||||
let real_opened_file = {
|
|
||||||
let mut open_options = std::fs::OpenOptions::new();
|
|
||||||
let open_options = open_options.read(true);
|
|
||||||
let open_options = if fs_rights_base & __WASI_RIGHT_FD_WRITE != 0 {
|
|
||||||
open_options.write(true)
|
|
||||||
} else {
|
|
||||||
open_options
|
|
||||||
};
|
|
||||||
let open_options = if o_flags & __WASI_O_CREAT != 0 {
|
|
||||||
debug!(
|
|
||||||
"File {:?} may be created when opened if it does not exist",
|
|
||||||
&file_path
|
|
||||||
);
|
|
||||||
open_options.create(true)
|
|
||||||
} else {
|
|
||||||
open_options
|
|
||||||
};
|
|
||||||
let open_options = if o_flags & __WASI_O_TRUNC != 0 {
|
|
||||||
debug!("File {:?} will be truncated when opened", &file_path);
|
|
||||||
open_options.truncate(true)
|
|
||||||
} else {
|
|
||||||
open_options
|
|
||||||
};
|
|
||||||
debug!("Opening host file {:?}", &file_path);
|
|
||||||
let real_open_file =
|
|
||||||
wasi_try!(open_options.open(&file_path).map_err(|_| __WASI_EIO));
|
|
||||||
|
|
||||||
real_open_file
|
|
||||||
};
|
|
||||||
Kind::File {
|
|
||||||
handle: WasiFile::HostFile(real_opened_file),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// record lazily loaded or newly created fd
|
|
||||||
let new_inode = state.fs.inodes.insert(InodeVal {
|
|
||||||
stat: wasi_try!(get_stat_for_kind(&kind).ok_or(__WASI_EIO)),
|
|
||||||
is_preopened: false,
|
|
||||||
name: file_name.clone(),
|
|
||||||
kind,
|
|
||||||
});
|
|
||||||
|
|
||||||
// reborrow to insert entry
|
|
||||||
if let Kind::Dir { entries, .. } = &mut state.fs.inodes[working_dir.inode].kind {
|
|
||||||
entries.insert(file_name.clone(), new_inode);
|
|
||||||
}
|
}
|
||||||
let new_fd = wasi_try!(state.fs.create_fd(
|
} else {
|
||||||
fs_rights_base,
|
if let Some(child) = entries.get(file_name).cloned() {
|
||||||
fs_rights_inheriting,
|
let child_inode_val = &state.fs.inodes[child];
|
||||||
fs_flags,
|
// early return based on flags
|
||||||
new_inode,
|
if o_flags & __WASI_O_EXCL != 0 {
|
||||||
));
|
return __WASI_EEXIST;
|
||||||
|
}
|
||||||
|
if o_flags & __WASI_O_DIRECTORY != 0 {
|
||||||
|
match &child_inode_val.kind {
|
||||||
|
Kind::Dir { .. } => (),
|
||||||
|
Kind::Symlink { .. } => {
|
||||||
|
unimplemented!("Symlinks not yet supported in path_open")
|
||||||
|
}
|
||||||
|
_ => return __WASI_ENOTDIR,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// do logic on child
|
||||||
|
wasi_try!(state
|
||||||
|
.fs
|
||||||
|
.create_fd(fs_rights_base, fs_rights_inheriting, fs_flags, child))
|
||||||
|
} else {
|
||||||
|
debug!("Attempting to load file from host system");
|
||||||
|
|
||||||
new_fd
|
let file_metadata = file_path.metadata();
|
||||||
|
// if entry does not exist in parent directory, try to lazily
|
||||||
|
// load it; possibly creating or truncating it if flags set
|
||||||
|
let kind = if file_metadata.is_ok() && file_metadata.unwrap().is_dir() {
|
||||||
|
// special dir logic
|
||||||
|
Kind::Dir {
|
||||||
|
parent: Some(cur_dir_inode),
|
||||||
|
path: file_path.clone(),
|
||||||
|
entries: Default::default(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// file is not a dir
|
||||||
|
let real_opened_file = {
|
||||||
|
let mut open_options = std::fs::OpenOptions::new();
|
||||||
|
let open_options = open_options.read(true);
|
||||||
|
let open_options = if fs_rights_base & __WASI_RIGHT_FD_WRITE != 0 {
|
||||||
|
open_options.write(true)
|
||||||
|
} else {
|
||||||
|
open_options
|
||||||
|
};
|
||||||
|
let open_options = if o_flags & __WASI_O_CREAT != 0 {
|
||||||
|
debug!(
|
||||||
|
"File {:?} may be created when opened if it does not exist",
|
||||||
|
&file_path
|
||||||
|
);
|
||||||
|
open_options.create(true)
|
||||||
|
} else {
|
||||||
|
open_options
|
||||||
|
};
|
||||||
|
let open_options = if o_flags & __WASI_O_TRUNC != 0 {
|
||||||
|
debug!("File {:?} will be truncated when opened", &file_path);
|
||||||
|
open_options.truncate(true)
|
||||||
|
} else {
|
||||||
|
open_options
|
||||||
|
};
|
||||||
|
debug!("Opening host file {:?}", &file_path);
|
||||||
|
let real_open_file =
|
||||||
|
wasi_try!(open_options.open(&file_path).map_err(|_| __WASI_EIO));
|
||||||
|
|
||||||
|
real_open_file
|
||||||
|
};
|
||||||
|
Kind::File {
|
||||||
|
handle: WasiFile::HostFile(real_opened_file),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// record lazily loaded or newly created fd
|
||||||
|
let new_inode = state.fs.inodes.insert(InodeVal {
|
||||||
|
stat: wasi_try!(get_stat_for_kind(&kind).ok_or(__WASI_EIO)),
|
||||||
|
is_preopened: false,
|
||||||
|
name: file_name.clone(),
|
||||||
|
kind,
|
||||||
|
});
|
||||||
|
|
||||||
|
// reborrow to insert entry
|
||||||
|
if let Kind::Dir { entries, .. } = &mut state.fs.inodes[working_dir.inode].kind {
|
||||||
|
entries.insert(file_name.clone(), new_inode);
|
||||||
|
}
|
||||||
|
let new_fd = wasi_try!(state.fs.create_fd(
|
||||||
|
fs_rights_base,
|
||||||
|
fs_rights_inheriting,
|
||||||
|
fs_flags,
|
||||||
|
new_inode,
|
||||||
|
));
|
||||||
|
|
||||||
|
new_fd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// working_dir did not match on Kind::Dir
|
// working_dir did not match on Kind::Dir
|
||||||
|
9
lib/wasi/tests/wasitests/fs_sandbox_test.rs
Normal file
9
lib/wasi/tests/wasitests/fs_sandbox_test.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#[test]
|
||||||
|
fn test_fs_sandbox_test() {
|
||||||
|
assert_wasi_output!(
|
||||||
|
"../../wasitests/fs_sandbox_test.wasm",
|
||||||
|
"fs_sandbox_test",
|
||||||
|
vec![],
|
||||||
|
"../../wasitests/fs_sandbox_test.out"
|
||||||
|
);
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
mod _common;
|
mod _common;
|
||||||
mod create_dir;
|
mod create_dir;
|
||||||
mod file_metadata;
|
mod file_metadata;
|
||||||
|
mod fs_sandbox_test;
|
||||||
mod hello;
|
mod hello;
|
||||||
mod mapdir;
|
mod mapdir;
|
||||||
mod quine;
|
mod quine;
|
||||||
|
BIN
lib/wasi/wasitests/fs_sandbox_test
Executable file
BIN
lib/wasi/wasitests/fs_sandbox_test
Executable file
Binary file not shown.
1
lib/wasi/wasitests/fs_sandbox_test.out
Normal file
1
lib/wasi/wasitests/fs_sandbox_test.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
Reading the parent directory was okay? false
|
10
lib/wasi/wasitests/fs_sandbox_test.rs
Normal file
10
lib/wasi/wasitests/fs_sandbox_test.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
fn main() {
|
||||||
|
#[cfg(target = "wasi")]
|
||||||
|
let result = std::fs::read_dir("..");
|
||||||
|
#[cfg(not(target = "wasi"))]
|
||||||
|
let result: Result<(), String> = Err("placeholder".to_string());
|
||||||
|
println!(
|
||||||
|
"Reading the parent directory was okay? {:?}",
|
||||||
|
result.is_ok()
|
||||||
|
);
|
||||||
|
}
|
BIN
lib/wasi/wasitests/fs_sandbox_test.wasm
Executable file
BIN
lib/wasi/wasitests/fs_sandbox_test.wasm
Executable file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user