Skip to content

Commit 7f1ca26

Browse files
committed
chore(vmm): Add pointer alignment check for Queue
Raw pointers of `struct Queue` are assumed to be aligned properly; otherwise some methods (e.g. `read_volatile()`) will panic. Such an alignment is possible when restored from a broken/fuzzed snapshot. Add pointer alignment check and exit with an error early instead of panic. Signed-off-by: Takahiro Itazuri <[email protected]>
1 parent 11d8a01 commit 7f1ca26

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

src/vmm/src/devices/virtio/queue.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum QueueError {
3434
DescIndexOutOfBounds(u16),
3535
/// Failed to write value into the virtio queue used ring: {0}
3636
MemoryError(#[from] vm_memory::GuestMemoryError),
37+
/// Pointer is not aligned properly: {0:p} misaligned for u{1}
38+
PointerNotAligned(*const u8, u8),
3739
}
3840

3941
/// A virtio descriptor constraints with C representative.
@@ -323,11 +325,33 @@ impl Queue {
323325
.get_slice_ptr(mem, self.used_ring_address, self.used_ring_size())?
324326
.cast();
325327

326-
// Disable it for kani tests, otherwise it will hit this assertion
327-
// and fail.
328-
#[cfg(not(kani))]
329-
if self.actual_size() < self.len() {
330-
return Err(QueueError::InvalidQueueSize(self.len(), self.actual_size()));
328+
// All the above pointers are expected to be aligned properly; otherwise some methods (e.g.
329+
// `read_volatile()`) will panic. Such an unalignment is possible when restored from a
330+
// broken/fuzzed snapshot.
331+
//
332+
// Specification of those pointers' alignments
333+
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-350007
334+
// > ================ ==========
335+
// > Virtqueue Part Alignment
336+
// > ================ ==========
337+
// > Descriptor Table 16
338+
// > Available Ring 2
339+
// > Used Ring 4
340+
// > ================ ==========
341+
if !self.desc_table_ptr.cast::<u128>().is_aligned() {
342+
return Err(QueueError::PointerNotAligned(
343+
self.desc_table_ptr.cast(),
344+
128,
345+
));
346+
}
347+
if !self.avail_ring_ptr.is_aligned() {
348+
return Err(QueueError::PointerNotAligned(
349+
self.avail_ring_ptr.cast(),
350+
16,
351+
));
352+
}
353+
if !self.used_ring_ptr.cast::<u32>().is_aligned() {
354+
return Err(QueueError::PointerNotAligned(self.used_ring_ptr.cast(), 32));
331355
}
332356

333357
Ok(())

0 commit comments

Comments
 (0)