summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend.rs53
-rw-r--r--src/vhost_kern/mod.rs50
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