mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: vsock: Use checked descriptor iterator
Drop the local next_checked_desc helper and the inline translate_gva calls in from_tx_virtq_head and from_rx_virtq_head. Buffer ranges are now validated by the shared next_checked helper in vm-virtio, and the validated guest address is read directly from CheckedDescriptor::addr. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
a5962db441
commit
2bf5464f92
@@ -20,7 +20,8 @@ use std::ops::Deref;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use virtio_queue::DescriptorChain;
|
||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vm_virtio::checked_descriptor::DescriptorChainExt;
|
||||
|
||||
use super::{Result, VsockError, defs};
|
||||
use crate::get_host_address_range;
|
||||
@@ -127,7 +128,10 @@ impl VsockPacket {
|
||||
M: Clone + Deref,
|
||||
M::Target: GuestMemory,
|
||||
{
|
||||
let head = desc_chain.next().ok_or(VsockError::HdrDescMissing)?;
|
||||
let head = desc_chain
|
||||
.next_checked(access_platform)
|
||||
.map_err(|_| VsockError::GuestMemory)?
|
||||
.ok_or(VsockError::HdrDescMissing)?;
|
||||
|
||||
// All buffers in the TX queue must be readable.
|
||||
//
|
||||
@@ -140,10 +144,7 @@ impl VsockPacket {
|
||||
return Err(VsockError::HdrDescTooSmall(head.len()));
|
||||
}
|
||||
|
||||
let guest_hdr_addr = head
|
||||
.addr()
|
||||
.translate_gva(access_platform, VSOCK_PKT_HDR_SIZE)
|
||||
.map_err(|_| VsockError::GuestMemory)?;
|
||||
let guest_hdr_addr = head.addr();
|
||||
|
||||
// To avoid TOCTOU issues when reading/writing the VSock packet header in guest memory,
|
||||
// we need to copy the content of the header in the VMM's memory.
|
||||
@@ -182,9 +183,7 @@ impl VsockPacket {
|
||||
desc_chain.memory(),
|
||||
head.addr()
|
||||
.checked_add(VSOCK_PKT_HDR_SIZE as u64)
|
||||
.ok_or(VsockError::GuestMemory)?
|
||||
.translate_gva(access_platform, buf_size)
|
||||
.map_err(|_| VsockError::GuestMemory)?,
|
||||
.ok_or(VsockError::GuestMemory)?,
|
||||
buf_size,
|
||||
)
|
||||
.ok_or(VsockError::GuestMemory)?;
|
||||
@@ -197,7 +196,10 @@ impl VsockPacket {
|
||||
}
|
||||
|
||||
// We have separate header and data descriptors.
|
||||
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
||||
let buf_desc = desc_chain
|
||||
.next_checked(access_platform)
|
||||
.map_err(|_| VsockError::GuestMemory)?
|
||||
.ok_or(VsockError::BufDescMissing)?;
|
||||
|
||||
// TX data should be read-only.
|
||||
if buf_desc.is_write_only() {
|
||||
@@ -219,19 +221,20 @@ impl VsockPacket {
|
||||
let desc_len = desc.len() as usize;
|
||||
if desc_len > 0 && offset < total_len {
|
||||
let to_copy = std::cmp::min(desc_len, total_len - offset);
|
||||
let desc_addr = desc
|
||||
.addr()
|
||||
.translate_gva(access_platform, desc_len)
|
||||
.map_err(|_| VsockError::GuestMemory)?;
|
||||
desc_chain
|
||||
.memory()
|
||||
.read_slice(&mut owned[offset..offset + to_copy], desc_addr)
|
||||
.read_slice(&mut owned[offset..offset + to_copy], desc.addr())
|
||||
.map_err(|_| VsockError::GuestMemory)?;
|
||||
offset += to_copy;
|
||||
}
|
||||
|
||||
cur_desc = if desc.has_next() {
|
||||
Some(desc_chain.next().ok_or(VsockError::BufDescMissing)?)
|
||||
Some(
|
||||
desc_chain
|
||||
.next_checked(access_platform)
|
||||
.map_err(|_| VsockError::GuestMemory)?
|
||||
.ok_or(VsockError::BufDescMissing)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -248,15 +251,8 @@ impl VsockPacket {
|
||||
return Err(VsockError::BufDescTooSmall);
|
||||
}
|
||||
let buf_size = buf_desc.len() as usize;
|
||||
let buf_ptr = get_host_address_range(
|
||||
desc_chain.memory(),
|
||||
buf_desc
|
||||
.addr()
|
||||
.translate_gva(access_platform, buf_size)
|
||||
.map_err(|_| VsockError::GuestMemory)?,
|
||||
buf_size,
|
||||
)
|
||||
.ok_or(VsockError::GuestMemory)?;
|
||||
let buf_ptr = get_host_address_range(desc_chain.memory(), buf_desc.addr(), buf_size)
|
||||
.ok_or(VsockError::GuestMemory)?;
|
||||
pkt.buf = Some(PacketBuffer::Borrowed {
|
||||
ptr: buf_ptr,
|
||||
len: buf_size,
|
||||
@@ -279,7 +275,10 @@ impl VsockPacket {
|
||||
M: Clone + Deref,
|
||||
M::Target: GuestMemory,
|
||||
{
|
||||
let head = desc_chain.next().ok_or(VsockError::HdrDescMissing)?;
|
||||
let head = desc_chain
|
||||
.next_checked(access_platform)
|
||||
.map_err(|_| VsockError::GuestMemory)?
|
||||
.ok_or(VsockError::HdrDescMissing)?;
|
||||
|
||||
// All RX buffers must be writable.
|
||||
//
|
||||
@@ -292,10 +291,7 @@ impl VsockPacket {
|
||||
return Err(VsockError::HdrDescTooSmall(head.len()));
|
||||
}
|
||||
|
||||
let guest_hdr_addr = head
|
||||
.addr()
|
||||
.translate_gva(access_platform, VSOCK_PKT_HDR_SIZE)
|
||||
.map_err(|_| VsockError::GuestMemory)?;
|
||||
let guest_hdr_addr = head.addr();
|
||||
|
||||
// To avoid TOCTOU issues when reading/writing the VSock packet header in guest memory,
|
||||
// we need to copy the content of the header in the VMM's memory.
|
||||
@@ -309,7 +305,10 @@ impl VsockPacket {
|
||||
|
||||
// Prior to Linux v6.3 there are two descriptors
|
||||
if head.has_next() {
|
||||
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
||||
let buf_desc = desc_chain
|
||||
.next_checked(access_platform)
|
||||
.map_err(|_| VsockError::GuestMemory)?
|
||||
.ok_or(VsockError::BufDescMissing)?;
|
||||
let buf_size = buf_desc.len() as usize;
|
||||
|
||||
// TODO: We still assume that there are at most two descriptors. We should probably
|
||||
@@ -323,15 +322,8 @@ impl VsockPacket {
|
||||
guest_hdr_addr,
|
||||
hdr,
|
||||
buf: Some(PacketBuffer::Borrowed {
|
||||
ptr: get_host_address_range(
|
||||
desc_chain.memory(),
|
||||
buf_desc
|
||||
.addr()
|
||||
.translate_gva(access_platform, buf_size)
|
||||
.map_err(|_| VsockError::GuestMemory)?,
|
||||
buf_size,
|
||||
)
|
||||
.ok_or(VsockError::GuestMemory)?,
|
||||
ptr: get_host_address_range(desc_chain.memory(), buf_desc.addr(), buf_size)
|
||||
.ok_or(VsockError::GuestMemory)?,
|
||||
len: buf_size,
|
||||
}),
|
||||
})
|
||||
@@ -345,9 +337,7 @@ impl VsockPacket {
|
||||
desc_chain.memory(),
|
||||
head.addr()
|
||||
.checked_add(VSOCK_PKT_HDR_SIZE as u64)
|
||||
.ok_or(VsockError::GuestMemory)?
|
||||
.translate_gva(access_platform, buf_size)
|
||||
.map_err(|_| VsockError::GuestMemory)?,
|
||||
.ok_or(VsockError::GuestMemory)?,
|
||||
buf_size,
|
||||
)
|
||||
.ok_or(VsockError::GuestMemory)?,
|
||||
|
||||
Reference in New Issue
Block a user