-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
wiggle: adapt Wiggle guest slices for unsafe
shared use
#5229
wiggle: adapt Wiggle guest slices for unsafe
shared use
#5229
Conversation
Would it make sense to have a method that returns |
Subscribe to Label Actioncc @kubkon
This issue or pull request has been labeled: "wasi"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
e55f9c3
to
4d6ecb5
Compare
I'm open to it; not sure if all of the functions exposed are necessary, though. Let's see what @alexcrichton and @pchickey think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of the Unsafe*
wrapper you added here and I left a comment about how ideally I think we could use that to implement the safe bits and bobs.
Otherwise I think it should be able to implement:
impl<T> Deref for UnsafeGuestSlice<'_, T> {
type Target = [UnsafeCell<T>];
// ...
}
which could actually be relatively convenient to work with.
Thinking about this more, I don't think accessing |
The The only way to interact with the contents of |
Ah, yeah, I see what you mean; this makes more sense. I'm not sure how/when this would be used, though; I guess this would be yet another way to modify a slice besides the |
Oh I don't think the |
This commit is an attempt at improving the safety of using the return value of the `SharedMemory::data` method. Previously this returned `*mut [u8]` which, while correct, is unwieldy and unsafe to work with. The new return value of `&[UnsafeCell<u8>]` has a few advantages: * The lifetime of the returned data is now connected to the `SharedMemory` itself, removing the possibility for a class of errors of accidentally using the prior `*mut [u8]` beyond its original lifetime. * It's not possibly to safely access `.len()` as opposed to requiring an `unsafe` dereference before. * The data internally within the slice is now what retains the `unsafe` bits, namely indicating that accessing any memory inside of the contents returned is `unsafe` but addressing it is safe. I was inspired by the `wiggle`-based discussion on bytecodealliance#5229 and felt it appropriate to apply a similar change here.
This commit is an attempt at improving the safety of using the return value of the `SharedMemory::data` method. Previously this returned `*mut [u8]` which, while correct, is unwieldy and unsafe to work with. The new return value of `&[UnsafeCell<u8>]` has a few advantages: * The lifetime of the returned data is now connected to the `SharedMemory` itself, removing the possibility for a class of errors of accidentally using the prior `*mut [u8]` beyond its original lifetime. * It's not possibly to safely access `.len()` as opposed to requiring an `unsafe` dereference before. * The data internally within the slice is now what retains the `unsafe` bits, namely indicating that accessing any memory inside of the contents returned is `unsafe` but addressing it is safe. I was inspired by the `wiggle`-based discussion on #5229 and felt it appropriate to apply a similar change here.
When multiple threads can concurrently modify a WebAssembly shared memory, the underlying data for a Wiggle `GuestSlice` and `GuestSliceMut` could change due to access from other threads. This breaks Rust guarantees when `&[T]` and `&mut [T]` slices are handed out. This change modifies `GuestPtr` to make `as_slice` and `as_slice_mut` return an `Option` which is `None` when the underlying WebAssembly memory is shared. But WASI implementations still need access to the underlying WebAssembly memory, both to read to it and write from it. This change adds new APIs: - `GuestPtr::to_vec` copies the bytes from WebAssembly memory (from which we can safely take a `&[T]`) - `GuestPtr::as_unsafe_slice_mut` returns a wrapper `struct` from which we can `unsafe`-ly return a mutable slice (users must accept the unsafety of concurrently modifying a `&mut [T]`) This approach allows us to maintain Wiggle's borrow-checking infrastructure, which enforces the guarantee that Wiggle will not modify overlapping regions, e.g. This is important because the underlying system calls may expect this. Though other threads may modify the same underlying region, this is impossible to prevent; at least Wiggle will not be able to do so. Finally, the changes to Wiggle's API are propagated to all WASI implementations in Wasmtime. For now, code locations that attempt to get a guest slice will panic if the underlying memory is shared. Note that Wiggle is not enabled for shared memory (that will come later in something like bytecodealliance#5054), but when it is, these panics will be clear indicators of locations that must be re-implemented in a thread-safe way.
a0a836e
to
a6d8b36
Compare
This is an extension of bytecodealliance#5229 for the `&str` and `&mut str` types. As documented there, we are attempting to maintain Rust guarantees for slices that Wiggle hands out in the presence of WebAssembly shared memory, in which case multiple threads could be modifying the underlying data of the slice. This change changes the API of `GuestPtr` to return an `Option` which is `None` when attempting to view the WebAssembly data as a string and the underlying WebAssembly memory is shared. This reuses the `UnsafeGuestSlice` structure from bytecodealliance#5229 to do so and appropriately marks the region as borrowed in Wiggle's manual borrow checker. Each original call site in this project's WASI implementations is fixed up to `expect` that a non-shared memory is used. (Note that I can find no uses of `GuestStrMut` in the WASI implementations).
* wiggle: adapt Wiggle strings for shared use This is an extension of #5229 for the `&str` and `&mut str` types. As documented there, we are attempting to maintain Rust guarantees for slices that Wiggle hands out in the presence of WebAssembly shared memory, in which case multiple threads could be modifying the underlying data of the slice. This change changes the API of `GuestPtr` to return an `Option` which is `None` when attempting to view the WebAssembly data as a string and the underlying WebAssembly memory is shared. This reuses the `UnsafeGuestSlice` structure from #5229 to do so and appropriately marks the region as borrowed in Wiggle's manual borrow checker. Each original call site in this project's WASI implementations is fixed up to `expect` that a non-shared memory is used. (Note that I can find no uses of `GuestStrMut` in the WASI implementations). * wiggle: make `GuestStr*` containers wrappers of `GuestSlice*` This change makes it possible to reuse the underlying logic in `UnsafeGuestSlice` and the `GuestSlice*` implementations to continue to expose the `GuestStr` and `GuestStrMut` types. These types now are simple wrappers of their `GuestSlice*` variant. The UTF-8 validation that distinguished `GuestStr*` now lives in the `TryFrom` implementations for each type.
`wiggle` looks for an exported `Memory` named `"memory"` to use for its guest slices. This change allows it to use a `SharedMemory` if this is the kind of memory used for the export. It is `unsafe` to use shared memory in Wiggle because of broken Rust guarantees: previously, Wiggle could hand out slices to WebAssembly linear memory that could be concurrently modified by some other thread. With the introduction of Wiggle's new `UnsafeGuestSlice` (bytecodealliance#5225, bytecodealliance#5229, bytecodealliance#5264), Wiggle should now correctly communicate its guarantees through its API.
`wiggle` looks for an exported `Memory` named `"memory"` to use for its guest slices. This change allows it to use a `SharedMemory` if this is the kind of memory used for the export. It is `unsafe` to use shared memory in Wiggle because of broken Rust guarantees: previously, Wiggle could hand out slices to WebAssembly linear memory that could be concurrently modified by some other thread. With the introduction of Wiggle's new `UnsafeGuestSlice` (bytecodealliance#5225, bytecodealliance#5229, bytecodealliance#5264), Wiggle should now correctly communicate its guarantees through its API.
`wiggle` looks for an exported `Memory` named `"memory"` to use for its guest slices. This change allows it to use a `SharedMemory` if this is the kind of memory used for the export. It is `unsafe` to use shared memory in Wiggle because of broken Rust guarantees: previously, Wiggle could hand out slices to WebAssembly linear memory that could be concurrently modified by some other thread. With the introduction of Wiggle's new `UnsafeGuestSlice` (#5225, #5229, #5264), Wiggle should now correctly communicate its guarantees through its API.
Previous Wiggle changes (bytecodealliance#5229, bytecodealliance#5264) made it possible to access slices of WebAssembly linear memory from Wiggle but limited the interface so that slices of shared memory could only be accessed either `unsafe`-ly or via copying (`GuestPtr::to_vec`). This change modifies `fd_write` to unconditionally copy the bytes to be written before passing them to Rust's standard library in an `IoSlice`. This is likely not the optimal solution but enables further `wasi-threads` development. In the future this commit should probably change to conditionally copy the bytes when shared memory is detected and expand to fix up all the `expect` errors of the same kind in `preview_1.rs`.
Previous Wiggle changes (bytecodealliance#5229, bytecodealliance#5264) made it possible to access slices of WebAssembly linear memory from Wiggle but limited the interface so that slices of shared memory could only be accessed either `unsafe`-ly or via copying (`GuestPtr::to_vec`). This change modifies `fd_write` to unconditionally copy the bytes to be written before passing them to Rust's standard library in an `IoSlice`. This is likely not the optimal solution but enables further `wasi-threads` development. In the future this commit should probably change to conditionally copy the bytes when shared memory is detected and expand to fix up all the `expect` errors of the same kind in `preview_1.rs`.
Previous Wiggle changes (bytecodealliance#5229, bytecodealliance#5264) made it possible to access slices of WebAssembly linear memory from Wiggle but limited the interface so that slices of shared memory could only be accessed either `unsafe`-ly or via copying (`GuestPtr::to_vec`). This change modifies `fd_write` to unconditionally copy the bytes to be written before passing them to Rust's standard library in an `IoSlice`. This is likely not the optimal solution but enables further `wasi-threads` development. In the future this commit should probably change to conditionally copy the bytes when shared memory is detected and expand to fix up all the `expect` errors of the same kind in `preview_1.rs`.
Previous Wiggle changes (bytecodealliance#5229, bytecodealliance#5264) made it possible to access slices of WebAssembly linear memory from Wiggle but limited the interface so that slices of shared memory could only be accessed either `unsafe`-ly or via copying (`GuestPtr::to_vec`). This change modifies `fd_write` to unconditionally copy the bytes to be written before passing them to Rust's standard library in an `IoSlice`. This is likely not the optimal solution but enables further `wasi-threads` development. In the future this commit should probably change to conditionally copy the bytes when shared memory is detected and expand to fix up all the `expect` errors of the same kind in `preview_1.rs`.
Previous Wiggle changes (bytecodealliance#5229, bytecodealliance#5264) made it possible to access slices of WebAssembly linear memory from Wiggle but limited the interface so that slices of shared memory could only be accessed either `unsafe`-ly or via copying (`GuestPtr::to_vec`). This change modifies `fd_write` to unconditionally copy the bytes to be written before passing them to Rust's standard library in an `IoSlice`. This is likely not the optimal solution but enables further `wasi-threads` development. In the future this commit should probably change to conditionally copy the bytes when shared memory is detected and expand to fix up all the `expect` errors of the same kind in `preview_1.rs`.
When multiple threads can concurrently modify a WebAssembly shared memory, the underlying data for a Wiggle
GuestSlice
andGuestSliceMut
could change due to access from other threads. This breaks Rust guarantees when&[T]
and&mut [T]
slices are handed out. This change modifiesGuestPtr
to makeas_slice
andas_slice_mut
return anOption
which isNone
when the underlying WebAssembly memory is shared.But WASI implementations still need access to the underlying WebAssembly memory, both to read to it and write from it. This change adds new APIs:
GuestPtr::to_vec
copies the bytes from WebAssembly memory (from which we can safely take a&[T]
)GuestPtr::as_unsafe_slice_mut
returns a wrapperstruct
from which we canunsafe
-ly return a mutable slice (users must accept the unsafety of concurrently modifying a&mut [T]
)This approach allows us to maintain Wiggle's borrow-checking infrastructure, which enforces the guarantee that Wiggle will not modify overlapping regions, e.g. This is important because the underlying system calls may expect this. Other threads may modify the same underlying region and this is impossible to prevent; at least Wiggle will not be able to do so.
Finally, the changes to Wiggle's API are propagated to all WASI implementations in Wasmtime. For now, code locations that attempt to get a guest slice will panic if the underlying memory is shared. Note that Wiggle is not enabled for shared memory (that will come later in something like #5054), but when it is, these panics will be clear indicators of locations that must be re-implemented in a thread-safe way.