diff options
-rw-r--r-- | src/backend.rs | 53 | ||||
-rw-r--r-- | src/vhost_kern/mod.rs | 50 |
2 files changed, 71 insertions, 32 deletions
diff --git a/src/backend.rs b/src/backend.rs index e5dc4b7..2d1a4a2 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -34,6 +34,26 @@ pub struct VringConfigData { pub log_addr: Option<u64>, } +impl VringConfigData { + /// Check whether the log (flag, address) pair is valid. + pub fn is_log_addr_valid(&self) -> bool { + if self.flags & 0x1 != 0 && self.log_addr.is_none() { + return false; + } + + true + } + + /// Get the log address, default to zero if not available. + pub fn get_log_addr(&self) -> u64 { + if self.flags & 0x1 != 0 && self.log_addr.is_some() { + self.log_addr.unwrap() + } else { + 0 + } + } +} + /// Memory region configuration data. #[derive(Default, Clone, Copy)] pub struct VhostUserMemoryRegionInfo { @@ -133,3 +153,36 @@ pub trait VhostBackend: std::marker::Sized { /// * `fd` - EventFd that will be signaled from guest. fn set_vring_err(&mut self, queue_index: usize, fd: &EventFd) -> Result<()>; } + +#[cfg(test)] +mod tests { + use VringConfigData; + + #[test] + fn test_vring_config_data() { + let mut config = VringConfigData { + queue_max_size: 0x1000, + queue_size: 0x2000, + flags: 0x0, + desc_table_addr: 0x4000, + used_ring_addr: 0x5000, + avail_ring_addr: 0x6000, + log_addr: None, + }; + + assert_eq!(config.is_log_addr_valid(), true); + assert_eq!(config.get_log_addr(), 0); + + config.flags = 0x1; + assert_eq!(config.is_log_addr_valid(), false); + assert_eq!(config.get_log_addr(), 0); + + config.log_addr = Some(0x7000); + assert_eq!(config.is_log_addr_valid(), true); + assert_eq!(config.get_log_addr(), 0x7000); + + config.flags = 0x0; + assert_eq!(config.is_log_addr_valid(), true); + assert_eq!(config.get_log_addr(), 0); + } +} diff --git a/src/vhost_kern/mod.rs b/src/vhost_kern/mod.rs index 5644118..6aad72c 100644 --- a/src/vhost_kern/mod.rs +++ b/src/vhost_kern/mod.rs @@ -12,7 +12,6 @@ //! control the in-kernel net, scsi, vsock vhost drivers. use std::os::unix::io::{AsRawFd, RawFd}; -use std::ptr::null; use vm_memory::{Address, GuestAddress, GuestMemory, GuestUsize}; use vmm_sys_util::eventfd::EventFd; @@ -49,15 +48,21 @@ pub trait VhostKernBackend<'a>: AsRawFd { /// Check whether the ring configuration is valid. fn is_valid(&self, config_data: &VringConfigData) -> bool { let queue_size = config_data.queue_size; - let desc_table_size = 16 * u64::from(queue_size) as GuestUsize; - let avail_ring_size = 6 + 2 * u64::from(queue_size) as GuestUsize; - let used_ring_size = 6 + 8 * u64::from(queue_size) as GuestUsize; if queue_size > config_data.queue_max_size || queue_size == 0 || (queue_size & (queue_size - 1)) != 0 { - false - } else if GuestAddress(config_data.desc_table_addr) + return false; + } + + // TODO: the GuestMemory trait lacks of method to look up GPA by HVA, + // so there's no way to validate HVAs. Please extend vm-memory crate + // first. + /* + let desc_table_size = 16 * u64::from(queue_size) as GuestUsize; + let avail_ring_size = 6 + 2 * u64::from(queue_size) as GuestUsize; + let used_ring_size = 6 + 8 * u64::from(queue_size) as GuestUsize; + if GuestAddress(config_data.desc_table_addr) .checked_add(desc_table_size) .map_or(true, |v| !self.mem().address_in_range(v)) { @@ -72,9 +77,10 @@ pub trait VhostKernBackend<'a>: AsRawFd { .map_or(true, |v| !self.mem().address_in_range(v)) { false - } else { - true } + */ + + config_data.is_log_addr_valid() } } @@ -186,33 +192,13 @@ impl<'a, T: VhostKernBackend<'a>> VhostBackend for T { return Err(Error::InvalidQueue); } - let desc_addr = self - .mem() - .get_host_address(GuestAddress(config_data.desc_table_addr)) - .map_err(|_| Error::InvalidGuestMemory)?; - let used_addr = self - .mem() - .get_host_address(GuestAddress(config_data.used_ring_addr)) - .map_err(|_| Error::InvalidGuestMemory)?; - let avail_addr = self - .mem() - .get_host_address(GuestAddress(config_data.avail_ring_addr)) - .map_err(|_| Error::InvalidGuestMemory)?; - let log_addr = match config_data.log_addr { - None => null(), - Some(a) => self - .mem() - .get_host_address(GuestAddress(a)) - .map_err(|_| Error::InvalidGuestMemory)?, - }; - let vring_addr = vhost_vring_addr { index: queue_index as u32, flags: config_data.flags, - desc_user_addr: desc_addr as u64, - used_user_addr: used_addr as u64, - avail_user_addr: avail_addr as u64, - log_guest_addr: log_addr as u64, + desc_user_addr: config_data.desc_table_addr, + used_user_addr: config_data.used_ring_addr, + avail_user_addr: config_data.avail_ring_addr, + log_guest_addr: config_data.get_log_addr(), }; // This ioctl is called on a valid vhost fd and has its |