Stream: wasm

Topic: WASI's path_open


view this post on Zulip Dominic Elm (Aug 22 2023 at 13:23):

I am looking at the spec for path_open and I don't see anything regarding whether it resolves symlinks or not when it internally calls open. Node.js doesn't seem to call open with O_FOLLOW and that flag doesn't seem to be checked at all whereas wasmtime and wasmer seem to respect that flag. What is the correct behavior? Am I missing something from the spec?

Resolution to the host path can resolve symlinks but if you say that it should not follow symlinks then the host path will point e.g. to the symlink itself but then the open call would resolve it. I am not sure what the correct behavior is here.

view this post on Zulip Dan Gohman (Aug 22 2023 at 13:25):

https://github.com/WebAssembly/wasi-filesystem/pull/127 is a PR adding documentation about this.

Add a new path-resolution.md document describing CloudABI-style path resolution behavior. wit/types.wit previously had a brief description of this behavior, however this new document presents it in...

view this post on Zulip Dominic Elm (Aug 22 2023 at 13:26):

Oh! Interesting, thanks for sharing that

view this post on Zulip Dominic Elm (Aug 22 2023 at 13:32):

So if I understand correctly it means that symlinks in the middle are resolved and the last is not resolved if the last component is a symlink?

view this post on Zulip Dan Gohman (Aug 22 2023 at 13:33):

From the perspective of a user of wasi-filesystem, symlinks are resolved in all positions, just like in Unix.

view this post on Zulip Dan Gohman (Aug 22 2023 at 13:34):

In the implementation, unless we have optimizations like Linux's RESOLVE_BENEATH, we disable host symlink resolution and do it "in userspace" to enforce sandboxing.

view this post on Zulip Dominic Elm (Aug 22 2023 at 13:59):

Hm interesting, that means that Node.js behaves correctly in that it resolves all symlinks in all components but wasmer doesn't I guess.

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:15):

wasmtime seems to take into account O_NOFOLLOW for the open call whereas Node.js does not.

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:21):

And if you try to open a file with O_NOFOLLOW wasmtime throws with "symbolic link loop"

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:21):

How do I open a symlink then without resolving it?

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:22):

Just using lstat then in C?

view this post on Zulip Lann Martin (Aug 22 2023 at 14:24):

You can't "open" a symlink itself, only the file it points to

view this post on Zulip Lann Martin (Aug 22 2023 at 14:25):

You might want readlink?

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:25):

Hm ok got it. Is that default posix behavior?

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:25):

That you can't open a symlink only the target?

view this post on Zulip Lann Martin (Aug 22 2023 at 14:26):

Oh sorry, that was a terrible explanation :sweat_smile:

view this post on Zulip Lann Martin (Aug 22 2023 at 14:27):

wasi-libc should open the file pointed to by a symlink by default, I believe

view this post on Zulip Lann Martin (Aug 22 2023 at 14:28):

When I say "you can't open a symlink itself" I mean for example if the symlink doesn't point at an existing file then there isn't anything to open

view this post on Zulip Lann Martin (Aug 22 2023 at 14:29):

If your platform isn't following symlinks by default, one option is to resolve them yourself, and a POSIXy way to do that is readlink

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:30):

Yea that makes sense

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:30):

Ah right

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:31):

Cause POSIX will also return with an ELOOP if the last component is a symlink and O_NOFOLLOW was specified

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:31):

Right

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:31):

So you can't really open a symlink

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:31):

Thanks!

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:32):

So the difference here than with Node.js is that it just doesn't even pass along O_NOFOLLOW whereas wasmtime does which is why it throws with a "symbolic link loop"

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:32):

But Node doesn't because it never passes O_NOFOLLOW

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:32):

What is the right behavior then?

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:33):

Cause here it also doesn't mention anything of O_NOFOLLOW https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#fdflags

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:33):

And those are the flags that Node also passes along

view this post on Zulip Lann Martin (Aug 22 2023 at 14:37):

Its on lookupflags: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-lookupflags-record

view this post on Zulip Lann Martin (Aug 22 2023 at 14:38):

(path-flags in preview2)

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:39):

Yes, but that only determines the resolution to the host path no?

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:39):

So in case you'd specify O_NOFOLLOW then the host path will not be the symlink target but the symlink itself

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:39):

And that path is then passed to open which will basically resolve the symlink

view this post on Zulip Dominic Elm (Aug 22 2023 at 14:39):

Cause O_NOFOLLOW is not passed to open as well.

view this post on Zulip Lann Martin (Aug 22 2023 at 14:47):

The host gets to decide how to map a host filesystem into a wasi guest filesystem. The most obvious thing to do with symlinks is to convert them into guest symlinks, but this is tricky since a host symlink may try to "escape" the source directory of your mapping, which is why wasmtime does its own symlink resolution

view this post on Zulip Lann Martin (Aug 22 2023 at 14:49):

The guest doesn't get to decide what the host does, only whether or not to follow what the host has presented as a symlink

view this post on Zulip Lann Martin (Aug 22 2023 at 14:51):

So I guess the answer to "What is the right behavior?" is that the host gets to decide, as long as any symlinks it presents to the guest behave correctly

view this post on Zulip Dominic Elm (Aug 22 2023 at 17:35):

Ok, so saying that resolving to a host path would not resolve the symlink when O_NOFOLLOW is passed, but open would resolve it then is also "correct" behavior then?

view this post on Zulip Dominic Elm (Aug 22 2023 at 17:35):

Cause it's up to the host?

view this post on Zulip Dominic Elm (Aug 22 2023 at 17:35):

Is that somewhere in the spec that this is up to the host?

view this post on Zulip Dan Gohman (Aug 22 2023 at 17:48):

It kind of just flows from the big picture with WASI. wasi-filesystem isn't giving you access to "The Filesystem"; it's giving you access to something that can be presented as a filesystem. That might be "The Filesystem" on the host, or it might be something that's not a filesystem at all, or it might be an attenuated version of the host filesystem where everything is presented as readonly, or, indeed, it could even be a view where symlinks are presented as non-symlinks.

view this post on Zulip Dominic Elm (Aug 23 2023 at 07:05):

Ah okay got it. So the bottom line is that it's really up to the host then?

view this post on Zulip Dominic Elm (Aug 23 2023 at 18:33):

Thanks all!


Last updated: Dec 23 2024 at 12:05 UTC