-
Notifications
You must be signed in to change notification settings - Fork 107
Update vm-memory dependency to 0.18.0 #379
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
base: main
Are you sure you want to change the base?
Conversation
To verify whether a given memory region is accessible, use `check_range()` instead of `check_address()`: - First, it just makes sense to check the full range instead of a single byte. (There is no difference in the virtio-blk status byte case, though.) - Second, vm-memory 0.18 has changed its `GuestMemory` type to a much more restricted interface so it can properly represent virtual memory. This new version only has `check_range()`, not `check_address()`, so switching to the former will facilitate updating our vm-memory dependency. Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
There is no reason to go through the `GuestMemoryRegion` to get a slice in guest memory, we can just use `GuestMemory::get_slice()` directly. This is not least in preparation for a vm-memory update that makes `GuestMemory` potentially represent virtual memory, in which case we will no longer be able to easily translate memory addresses into `GuestMemoryRegion`s. Another change that will come with that is that `get_slice()` will be removed in favor of an iterating `get_slices()`. This would require us replacing `.map()` with `.flat_map()`, but with us generating errors on both iterator levels (in the `chain.readable()`/`chain.writable()` iterator, and in the `.get_slices()` iterator), this is quite hard to represent in this functional style. So just use a `for .. in` loop with `.push_back()` into the `VecDeque`. Given that none of our iterators has a `.size_hint()` implementation, it doesn’t make a difference in performance anyway. And while at it, we may as well already use `get_slices()` rather than `get_slice()`. (And similarly, push the slices in a `for .. in` loop because there is no `Vec::try_extend()`.) Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
vm-memory is deprecating `get_slice()` in favor of `get_slices()`. Add a helper function to virtio-vsock/src/packet.rs to translate a guest memory range into a single slice, returning an error if the range is fragmented. This should not change anything for non-virtual guest memory (unless requesting memory ranges across `GuestMemoryRegion` boundaries, which should have always required handling scatter-gather slices), so I think it is a reasonable band-aid for now. To properly support fragmented virtual memory, `VsockPacket`’s interface would need to be changed, removing `header_slice()` and `data_slice()`, replaced by methods that return some form of scatter-gather lists for both. Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Add a function that retrieves a guest memory region’s base host pointer. With vm-memory’s changes to `GuestMemory`, `.get_host_address()` is no longer going to work. (The `rx_tx` parameter is unused for now, but will be evaluated in a follow-up patch to determine the necessary access permissions to get the host slice.) Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Like in virtio-vsock/src/packet.rs, add a `get_mem_ptr()` function in the test module to replace `.get_host_address()`. Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
402d1ac to
7a1db2b
Compare
|
Sorry, kani fails: I’ll try to find out how to fix this, but probably only at the start of next year. I’m not really sure whether it can even be fixed inside of vm-virtio alone. As far as I understand so far, it doesn’t seem to be anything in the fn next(&mut self) -> Option<Self::Item> {
if self.count == 0 {
return None;
}
let count = self.count;
self.count = 0;
Some(
self.mem
.to_region_addr(self.addr)
.ok_or(Error::InvalidGuestAddress(self.addr))
.and_then(|(r, addr)| r.get_slice(addr, count))
)
}But limiting fn check_range(&self, base: GuestAddress, len: usize) -> bool {
// get_slices() ensures that if no error happens, the cumulative length of all slices
// equal `len`.
self.get_slices(base, len).take(1).all(|r| r.is_ok())
}With |
Don't worry at all, take your time, and thank you very much for this PR! |
The main change is that `GuestMemory` can now handle virtual memory, which requires passing the needed access permissions. The previous `GuestMemory` is now called `GuestMemoryBackend`, so we need to use that in the kani verification code. We also need to override the provided `check_range()` method because of some problem with iterating over the `get_slices()` result. As for getting the memory’s bitmap type, we need to use `GuestMemory::Bitmap` instead of going through the region type. Finally, there is no longer a `GuestMemory::get_slice()` (only `get_slices()`), but the previous commits have already prepared for that. Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
7a1db2b to
c48d451
Compare
|
Fixed it (I hope it’s acceptable) by overriding the provided |
Summary of the PR
Update the vm-memory dependency to 0.18.0. This PR supersedes #378.
0.18.0 is a breaking change, first and foremost because it renames the
GuestMemorytrait toGuestMemoryBackend, replacing it with a newGuestMemorytrait that can abstract not only physical but also virtual memory, but in turn has a limited interface and requires specifying the required permissions for any memory access.(Luckily, most memory accesses use the
Bytestrait, which already implicitly specifies the access mode by way of which method is used, e.g.load()vs.store().)This PR first changes some calls to use the methods that will still be available:
check_range()instead ofcheck_address()virtio_queue::descriptor_utils::{Reader, Writer}::new(): Do not resolve memory accesses through guest memory regions, just collect slices throughget_slices()virtio_vsock::packet: Replaceget_slice()by a helper function that callsget_slices()and returns an error if the given guest memory region maps to more than a single slice. This is not ideal:get_slice()has been removed to make users aware that guest memory regions may not always map to a single slice in their memory, especially for virtual memory, and this is just ignoring that. However, it shouldn’t be a regression, so support for this can be implemented later, I think. (Maybe via bounce buffers if the interface must stay compatible?)get_host_address()is removed; we only need it for testing, so we can just useget_single_slice().as_ptr()there, basically.Then it bumps the vm-memory version, at which point we need to:
get_slices()returning aResult<Iterator, E>instead of a plainIterator,GuestMemory::Bitmapinstead of<GuestMemory::R as GuestMemoryRegion>::B, andSingleRegionGuestMemoryimplementGuestMemoryBackendinstead ofGuestMemory.Compatibility Note
Note that users should still be able to depend on vm-memory 0.17.2+, even with vm-virtio updating to 0.18.0. This is because 0.17.2 internally depends on 0.18.0 and just re-exports all symbols, just some under different names (i.e.
GuestMemoryBackendasGuestMemory).Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafecode is properly documented.