-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Suggestion: treat WASI preopen dirs as path prefixes #82339
Comments
My initial thought is, the preopen path mechanism is a libc abstraction, so instead of exposing more details about how it works, we should ideally either extend the abstraction so that applications don't need to know about it, or give applications better ways to skip the abstraction and work in terms of WASI concepts directly. If code is using preopens and finding things that don't work, can we identify features we could add to support such code? You mention crossing boundaries, resolving relative paths, and symlinks; could you say more about what things you're looking to do that don't work? For application code that wants to take WASI into consideration, one possible approach is to pursue the WASI port (currently under development) of cap-std. That way, instead of thinking about paths and prefixes, which are still just libc abstractions, code can use Do either of those approaches sound feasible here? |
The latest example of such conversation was when I was adding
So I thought we might want to still expose some API that allows such split-up. More generally, I'm also worried about All the libc APIs in wasi-libc currently don't allow such crossings and you can't perform e.g. Treating preopen dir as a |
I actually think the security model is ok with allowing applications to My main question is how this impacts the ABI, and to what it extent it creates conventions that applications may come to depend on. One of the things I'm interested in for WASI is blinding for host paths. That is, if I pass If applications come to depend on having preopen paths living at known locations relative to other preopen paths in the hierarchical namespace, it would complicate this kind of blinding, limiting our options to evolve in this direction in the future. That said, host path blinding is a theoretical feature, and not necessarily a requirement. If |
Isn't the host blinding you describe essentially same as
I guess if it's not part of the security model, that would work too. I just want userland and system APIs to be consistent in path handling. But I thought I saw your comments on symlinks (or was it just hardlinks?) where you said it wasn't desirable to allow crossings from one preopen to another. Is that no longer the case?
Just to provide one example (since that's the one I'm most familiar with) - cases of "shells" like https://wasi.rreverser.com/. By default, there's a mounted dir
In principle, it's possible to solve in userland code of a particular app, but I'd prefer to be consistent with rest of WASI - if WASI doesn't allow relative paths from one mount to another, then app shouldn't either, and vice versa. This applies not only to shells, but also to e.g. any manipulations that produce intermediate relative paths |
Yeah,
That's still mostly the case. Symlinks are resolved by the "OS", rather than libc, so they don't go through the preopen mechanism. If we really wanted to support cross-handle symlinks, there are a few ways we could make it work. I think we're still in the phase of looking for the real-world use cases that would help shape this.
Shells are special :-). An assumption of applying capability model to filesystems is that most applications and libraries will only need limited access to the hierarchical namespace, but shells tend to want to be able to roam freely throughout the namespace. Also, shell users may type
Some of this kind of thing works today, if we ignore |
Right, but we can't really ignore those :) A function to get relative path between The rest of what you're describing makes sense, but I hope that this kind of usecases is not ignored completely just because they're special :) The general question about the direction of path handling still stands I think: do we want Rust path manipulation API to match what libc does today, and treat preopen dir as a "root" that can't be crossed via normal Path APIs, or do we want to change libc to support resolving paths across those preopen dirs. Regardless of the specific usecase, the current mismatch in behaviour seems tricky to navigate. |
Another reason I'm asking is that I want to implement I have partial implementation (modulo symlinks) in a branch, but for now I've restricted it to return error on any attempt to cross boundaries, which should be still good enough for most use-cases, but if we do want to allow such "crossings", then the implementation can be quite a bit simpler. |
These are good questions, and I myself don't have a complete vision for how this should all work :-}. Big-picture WASI wants to use handles instead of paths, so path support is all about finding the right balance between compatibility for porting code and preserving desirable properties of the capability system where possible. A I've been thinking more |
Yeah, totally - for now my suggestion above was based on the assumption that preopens will remain static, but if we add ability to add them dynamically, such behaviour might become more confusing indeed. |
Sounds reasonable to me. Worst case we'll hear from people for whom it's not enough. Thanks. |
Rust stdlib already has a concept of path prefixes (
std::path::Prefix
,std::path::PrefixComponent
etc.), although they are applied only to Windows paths.WASI paths are currently treated as starting with a root
/
(e.g.path.components()
returns each level starting fromComponent::RootDir
aka/
), even though WASI recognises only paths starting with a specific prefix that matches one of the preopen directories specified at startup. The levels above those prefixes don't "exist", and most APIs under WASI don't permit crossing boundaries and resolving relative paths or symlinks from a path rooted under one preopen directory to another.The question of exposing an API corresponding to the (currently private)
open_parent
arisen several times in the past, as it's important to split the preopen dir from the relative path whenever dealing with lower-level WASI syscalls.Given the above, I feel like there is a lot of conceptual similarity between WASI preopen dirs and the
std::path::Prefix
, and the latter would be a natural API to use for exposing the former. We'd only need to add another variant tostd::path::Prefix
as well as check against the preopened dirs when splittingPath
intocomponents
.@alexcrichton @sunfishcode would love your thoughts on this idea.
The text was updated successfully, but these errors were encountered: