From 84b8d25bb631b5dc2a0c9788918625498f6e9f5e Mon Sep 17 00:00:00 2001 From: Julian Schindel Date: Thu, 12 Mar 2026 16:24:31 +0100 Subject: [PATCH] vm-migration: fix UB in `MemoryRangeTable::read_from` The pointer created by `Vec::as_ptr` may not be used for mutation of the underlying data [0]. This PR switches to `Vec::as_mut_ptr` and uses `cast` to avoid mutability changes when casting. Also improves safety reasoning, separates the unsafe call from the call to `read_exact` to improve clarity and simplifies the vector creation. [0]: https://doc.rust-lang.org/alloc/vec/struct.Vec.html#method.as_ptr On-behalf-of: SAP julian.schindel@sap.com Signed-off-by: Julian Schindel --- vm-migration/src/protocol.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/vm-migration/src/protocol.rs b/vm-migration/src/protocol.rs index 3ae226ece..4dfec4f62 100644 --- a/vm-migration/src/protocol.rs +++ b/vm-migration/src/protocol.rs @@ -332,19 +332,19 @@ impl MemoryRangeTable { pub fn read_from(fd: &mut dyn Read, length: u64) -> Result { assert!((length as usize).is_multiple_of(size_of::())); - let mut data: Vec = Vec::new(); - data.resize_with( - length as usize / (std::mem::size_of::()), - Default::default, - ); - // SAFETY: the slice is constructed with the correct arguments - fd.read_exact(unsafe { - std::slice::from_raw_parts_mut( - data.as_ptr() as *mut MemoryRange as *mut u8, - length as usize, - ) - }) - .map_err(MigratableError::MigrateSocket)?; + let mut data: Vec = + vec![MemoryRange::default(); length as usize / size_of::()]; + + // SAFETY: The pointer points to the just created vector data. + // `MemoryRange` can be read from and written to bytes since it's `[repr(C)]`. + // The vector data was initialized with `length as usize / size_of::()` valid + // `MemoryRange`s so the memory is valid for `length` bytes. + // During the lifetime of the slice, neither the backing vector nor the pointed to memory are accessed. + let data_slice_bytes = + unsafe { std::slice::from_raw_parts_mut(data.as_mut_ptr().cast(), length as usize) }; + + fd.read_exact(data_slice_bytes) + .map_err(MigratableError::MigrateSocket)?; Ok(Self { data }) }