Skip to content

Commit 36b975c

Browse files
committed
Add tests that backslashes in symlinks don't lead to sandbox escape
1 parent 83501b9 commit 36b975c

1 file changed

Lines changed: 41 additions & 3 deletions

File tree

tests/rust/wasm32-wasip3/src/bin/filesystem-symbolic-links.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use wasi::filesystem::types::Descriptor;
2020
use wasi::filesystem::types::{DescriptorFlags, ErrorCode, OpenFlags, PathFlags};
2121

2222
async fn test_symbolic_links(dir: &Descriptor) {
23+
// symlink-at: async func(old-path: string, new-path: string) -> result<_, error-code>;
2324
let ln_s = |from: &str, to: &str| -> _ { dir.symlink_at(from.to_string(), to.to_string()) };
25+
// readlink-at: async func(path: string) -> result<string, error-code>;
2426
let readlink = |path: &str| dir.readlink_at(path.to_string());
2527
let stat_with_flags = |flags: PathFlags, path: &str| dir.stat_at(flags, path.to_string());
2628
let stat_follow = |path: &str| stat_with_flags(PathFlags::SYMLINK_FOLLOW, path);
@@ -42,7 +44,6 @@ async fn test_symbolic_links(dir: &Descriptor) {
4244
};
4345
let rm = |path: &str| dir.unlink_file_at(path.to_string());
4446

45-
// readlink-at: async func(path: string) -> result<string, error-code>;
4647
assert_eq!(readlink("").await, Err(ErrorCode::NoEntry));
4748
assert_eq!(readlink(".").await, Err(ErrorCode::Invalid));
4849
assert_eq!(readlink("a.txt").await, Err(ErrorCode::Invalid));
@@ -58,7 +59,7 @@ async fn test_symbolic_links(dir: &Descriptor) {
5859
Err(ErrorCode::NotDirectory)
5960
);
6061

61-
// https://github.com/WebAssembly/wasi-filesystem/issues/186
62+
// https://github.com/WebAssembly/WASI/issues/718
6263
assert_eq!(
6364
open_r("parent")
6465
.await
@@ -90,7 +91,44 @@ async fn test_symbolic_links(dir: &Descriptor) {
9091

9192
assert_eq!(ln_s("whatever", "").await, Err(ErrorCode::NoEntry));
9293
assert_eq!(ln_s("", "whatever").await, Err(ErrorCode::NoEntry));
93-
// symlink-at: async func(old-path: string, new-path: string) -> result<_, error-code>;
94+
95+
ln_s("..\\.", "parent-link").await.unwrap();
96+
assert_eq!(open_r("parent-link").await.unwrap_err(), ErrorCode::Loop);
97+
match open_r_follow("parent-link/fs-tests.dir").await {
98+
// Backslashes are not separators.
99+
Err(ErrorCode::NoEntry) => (),
100+
// Backslashes are separators.
101+
Err(ErrorCode::NotPermitted) => {
102+
assert_eq!(stat_follow("parent-link").await.unwrap_err(),
103+
ErrorCode::NotPermitted);
104+
assert_eq!(open_r("parent-link/fs-tests.dir/a.txt").await.unwrap_err(),
105+
ErrorCode::NotPermitted);
106+
assert_eq!(ln_s("a.txt", "parent-link/fs-tests.dir/q.txt").await,
107+
Err(ErrorCode::NotPermitted));
108+
},
109+
Err(e) => panic!("unexpected error: {}", e),
110+
Ok(_) => panic!("unexpected success"),
111+
}
112+
rm("parent-link").await.unwrap();
113+
114+
ln_s("..\\fs-tests.dir", "self-link").await.unwrap();
115+
assert_eq!(open_r("self-link").await.unwrap_err(), ErrorCode::Loop);
116+
match open_r_follow("self-link").await {
117+
// Backslashes are not separators.
118+
Err(ErrorCode::NoEntry) => (),
119+
// Backslashes are separators.
120+
Err(ErrorCode::NotPermitted) => {
121+
assert_eq!(stat_follow("self-link").await.unwrap_err(),
122+
ErrorCode::NotPermitted);
123+
assert_eq!(open_r("self-link/a.txt").await.unwrap_err(),
124+
ErrorCode::NotPermitted);
125+
assert_eq!(ln_s("a.txt", "self-link/q.txt").await,
126+
Err(ErrorCode::NotPermitted));
127+
},
128+
Err(e) => panic!("unexpected error: {}", e),
129+
Ok(_) => panic!("unexpected success"),
130+
}
131+
rm("self-link").await.unwrap();
94132
}
95133

96134
struct Component;

0 commit comments

Comments
 (0)