virtio-devices: mem: Reject resize if device not activated by guest

If the guest has not activated the virtio-mem device then reject an
attempt to resize using it.

Fixes: #4001

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-04-21 10:12:56 +01:00
parent 047432a81b
commit c274ce4d49

View File

@ -137,6 +137,8 @@ pub enum Error {
DmaUnmap(std::io::Error),
// Invalid DMA mapping handler
InvalidDmaMappingHandler,
// Not activated by the guest
NotActivatedByGuest,
}
#[repr(C)]
@ -327,6 +329,7 @@ impl Request {
pub struct ResizeSender {
hotplugged_size: Arc<AtomicU64>,
activated: Arc<AtomicBool>,
tx: mpsc::Sender<Result<(), Error>>,
evt: EventFd,
}
@ -345,6 +348,7 @@ impl Clone for ResizeSender {
fn clone(&self) -> Self {
ResizeSender {
hotplugged_size: self.hotplugged_size.clone(),
activated: self.activated.clone(),
tx: self.tx.clone(),
evt: self
.evt
@ -356,6 +360,7 @@ impl Clone for ResizeSender {
pub struct Resize {
hotplugged_size: Arc<AtomicU64>,
activated: Arc<AtomicBool>,
tx: mpsc::Sender<Result<(), Error>>,
rx: mpsc::Receiver<Result<(), Error>>,
evt: EventFd,
@ -367,6 +372,7 @@ impl Resize {
Ok(Resize {
hotplugged_size: Arc::new(AtomicU64::new(hotplugged_size)),
activated: Arc::new(AtomicBool::default()),
tx,
rx,
evt: EventFd::new(EFD_NONBLOCK)?,
@ -376,12 +382,17 @@ impl Resize {
pub fn new_resize_sender(&self) -> Result<ResizeSender, Error> {
Ok(ResizeSender {
hotplugged_size: self.hotplugged_size.clone(),
activated: self.activated.clone(),
tx: self.tx.clone(),
evt: self.evt.try_clone().map_err(Error::EventFdTryCloneFail)?,
})
}
pub fn work(&self, desired_size: u64) -> Result<(), Error> {
if !self.activated.load(Ordering::Acquire) {
return Err(Error::NotActivatedByGuest);
}
self.hotplugged_size.store(desired_size, Ordering::Release);
self.evt.write(1).map_err(Error::EventFdWriteFail)?;
self.rx.recv().map_err(Error::MpscRecvFail)?
@ -1046,11 +1057,14 @@ impl VirtioDevice for Mem {
)?;
self.common.epoll_threads = Some(epoll_threads);
self.resize.activated.store(true, Ordering::Release);
event!("virtio-device", "activated", "id", &self.id);
Ok(())
}
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
self.resize.activated.store(false, Ordering::Release);
let result = self.common.reset();
event!("virtio-device", "reset", "id", &self.id);
result