Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarifying path normalization, or lack thereof #27

Open
MaulingMonkey opened this issue Mar 10, 2021 · 1 comment
Open

Clarifying path normalization, or lack thereof #27

MaulingMonkey opened this issue Mar 10, 2021 · 1 comment

Comments

@MaulingMonkey
Copy link
Contributor

Any WASI runtime acting as any sort of sandbox should restrict access to unmapped paths. However, through path normalization, a path might end up "within" the sandbox. The question is, should WASI implementations be expected to implement such normalization, or is it safe to assume callers should normalize their own paths if they want that behavior?

That is, given:

let root : Fd = 4; // ...preopened directory fd...

Which of these, if any, should reasonably be expected to succeed? And in the case of symlinks, should ".." navigate to the parent based on the path before the symlinks resolve, or after?

let root2 : Fd = path_open(root,  ..., ".",  ...).unwrap();
let root2 : Fd = path_open(root,  ..., "existing/..",  ...).unwrap();
let root2 : Fd = path_open(root,  ..., "symlink/..",  ...).unwrap();
let root2 : Fd = path_open(root,  ..., "nonexistant/..",  ...).unwrap();
let dir   : Fd = path_open(root, ..., "existing", ...).unwrap();
let root2 : Fd = path_open(dir,  ..., "..",  ...).unwrap();
let dir   : Fd = path_open(root, ..., "symlink", ...).unwrap();
let root2 : Fd = path_open(dir,  ..., "..",  ...).unwrap();
@sunfishcode
Copy link
Member

The high-level view (which we should document better) is:

  • Path resolution shouldn't ever be influenced by the existence or non-existence, or accessibility or non-accessibility, of anything outside of the root.
  • Otherwise, follow .. and symlinks in the usual way.

With that:

. and existing/.. should succeed.

For symlink/.., it depends on where the symlink points. If the symlink points to somewhere where .. is still within the root, it succeeds. If the symlink points to ., an absolute path, .., etc., then symlink/.. fails.

nonexistant/.. turns out to be tricky because on Windows, .. resolution is done ahead of time, so we have a choice in either requiring implementations on Windows to emulate POSIX behavior, or saying that whether nonexistent/.. succeeds is nondeterministic. I've now filed #26 to track this.

let dir : Fd = path_open(root, ..., "existing", ...).unwrap();
let root2 : Fd = path_open(dir, ..., "..", ...).unwrap();

This should succeed.

let dir : Fd = path_open(root, ..., "symlink", ...).unwrap();
let root2 : Fd = path_open(dir, ..., "..", ...).unwrap();

This should succeed or fail in the same way that symlink/.. does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants