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

Review safety of all functions #8

Closed
newpavlov opened this issue Aug 21, 2019 · 14 comments · Fixed by #5
Closed

Review safety of all functions #8

newpavlov opened this issue Aug 21, 2019 · 14 comments · Fixed by #5

Comments

@newpavlov
Copy link
Contributor

Are we sure what all Core API functions can be wrapped in a safe interface?

@sunfishcode
Copy link
Member

We haven't done any formal proofs or fuzzing, but other than possible implementation bugs, I'm not aware of anything in WASI which could cause unsafety in the Rust sense.

@newpavlov
Copy link
Contributor Author

I have this question because from_raw_fd is an unsafe function. For example what will happen if user will call fd_close(25) and it is a valid file descriptor? Will we get an IO error if we'll try to do something with this FD? Is it guaranteed that FDs are not getting reused?

@sunfishcode
Copy link
Member

It's a good question. Yes, you can fd_close an arbitrary file descriptor, even one held by libstd. And file descriptors can get reused. It could cause I/O errors or potentially lost data. It could route data intended for one stream into another. But it shouldn't cause undefined behavior. Does that justify unsafe?

It justifies documentation, in any case :-).

@newpavlov
Copy link
Contributor Author

Does that justify unsafe?

I don't know. :)

@RalfJung
Can you help us here?

@RalfJung
Copy link

That's kind of an arbitrary call that the ecosystem as a whole has to agree on -- both options work, as long as they are done consistently.

But judging from things like rust-lang/rust#39575, Rust seems to be on the side of "messing with other people's file descriptors is unsafe".

@RalfJung
Copy link

But it shouldn't cause undefined behavior.

It doesn't cause UB on its own, but if other code relies on privacy of its file descriptors, that could then in combination lead to UB. So the question is if we allow other code to assume that its file descriptors are private. And I think we do, with the issue mentioned above (and unsafe from_raw_fd) being an indication, but I don't think this has been officially resolved.

@sunfishcode
Copy link
Member

That's a good point. And if we let code assume file descriptors are private, one could argue that even non-mutating functions, like fd_fdstat_get (WASI's fstat), should be unsafe, because they could leak potentially sensitive information. So maybe everything that takes a file descriptor argument (which is most of the API) should be unsafe.

That's inconvenient, but ideally, we shouldn't have lots of people using the wasi crate directly anyway, as people should usually prefer libstd and libc. So I think I could be ok making most things in this repo unsafe, to err on the side of caution.

@newpavlov
Copy link
Contributor Author

@sunfishcode
I think we can be conservative and mark all functions unsafe except the "obviously" safe: clock_res_get, clock_time_get, proc_exit, random_get, sched_yield. Other functions can be made safe in a backwards compatible manner after a better model of safety around file descriptors will get worked out.

If you want, I can add these changes to #5.

@sunfishcode
Copy link
Member

Yes, that'd be great.

Looking forward, clock and random APIs at least will likely move to requiring file descriptors, but until they do, it's fine to leave them safe. It's interesting that access to ambient authorities is aligning with unsafe.

@marmistrz
Copy link

That's kind of an arbitrary call that the ecosystem as a whole has to agree on -- both options work, as long as they are done consistently.

But judging from things like rust-lang/rust#39575, Rust seems to be on the side of "messing with other people's file descriptors is unsafe".

Related: https://users.rust-lang.org/t/when-should-we-mark-our-functions-unsafe/11834/3

@newpavlov
Copy link
Contributor Author

BTW I think it should be fine to remove unsafe for "read-only" functions like fd_prestat_get, fd_prestat_dir_name and probably others. So it may be worth to reopen this issue or create a new one.

@RalfJung
Copy link

Even read access can still be abstraction-breaking, and abstraction is what we use to tame unsafe in Rust.

We require unsafe code to read from private Copy fields of structs in other modules, even though this could be made a safe operation. I think we should follow the same line for read access to other potentially private state.

@newpavlov
Copy link
Contributor Author

In v0.8 all functions are now safe, is it intentional? Even if we'll leave FD stuff out, signatures like this are definitely smell trouble in my opinion.

sunfishcode added a commit that referenced this issue Nov 23, 2019
Following @RalfJung's comment here:

#8 (comment)

as long as the functions are still taking integer file descriptor
arguments, we should mark the APIs here `unsafe`.

This is particularly interesting in the context of WASI, as it aligns with
the OCap security model -- Rust's `std::fs::File` is an unforgeable
handle in safe Rust. So while there are still integer file descriptors at
the wasm level for now, programs compiled from safe Rust still have
fine-grained isolation (with the caveat that until reference types are
possible, this property isn't encoded in wasm in a verifiable way).
@sunfishcode
Copy link
Member

@newpavlov Thanks for spotting that -- I've now opened #24 to reintroduce the unsafe annotations.

alexcrichton pushed a commit that referenced this issue Nov 23, 2019
Following @RalfJung's comment here:

#8 (comment)

as long as the functions are still taking integer file descriptor
arguments, we should mark the APIs here `unsafe`.

This is particularly interesting in the context of WASI, as it aligns with
the OCap security model -- Rust's `std::fs::File` is an unforgeable
handle in safe Rust. So while there are still integer file descriptors at
the wasm level for now, programs compiled from safe Rust still have
fine-grained isolation (with the caveat that until reference types are
possible, this property isn't encoded in wasm in a verifiable way).
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

Successfully merging a pull request may close this issue.

4 participants