summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLiu Jiang <gerry@linux.alibaba.com>2020-12-08 23:20:44 +0800
committerSergio Lopez <slp@sinrega.org>2020-12-14 12:15:40 +0100
commitce094b25d270f4004a9dcb95426d4bf734a29d87 (patch)
tree62aadfabfb32a64e97c0d127081ca6d1a442f9fc /src
parentd257479a40b42895b9adab11befa5385bbee0698 (diff)
downloadvmm_vhost-ce094b25d270f4004a9dcb95426d4bf734a29d87.tar.gz
vhost-kern: treat addrs in VringConfigData as HVA
The ring addresses in VringConfigData are host virtual addresses, and the kernel vhost drivers also expect those addresses as HVA. So it's wrong to validate/translate those addresses as GPA. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
Diffstat (limited to 'src')
-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