Skip to content

Commit 961ec70

Browse files
committed
fix: Prevent balloon to be used with huge pages via snapshot mod
Insert a check into the snapshot restore routine that checks that a snapshot file cannot indicate both huge pages being enabled, while also listing a balloon device. If this condition is detected, refuse to load the snapshot and print an error suggesting that the snapshot file is corrupt. Signed-off-by: Patrick Roy <[email protected]>
1 parent 2e573c1 commit 961ec70

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

src/vmm/src/device_manager/persist.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::devices::virtio::vsock::{
3939
};
4040
use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_NET, TYPE_RNG};
4141
use crate::mmds::data_store::MmdsVersion;
42-
use crate::resources::VmResources;
42+
use crate::resources::{ResourcesError, VmResources};
4343
use crate::snapshot::Persist;
4444
use crate::vmm_config::mmds::MmdsConfigError;
4545
use crate::vstate::memory::GuestMemoryMmap;
@@ -69,6 +69,8 @@ pub enum DevicePersistError {
6969
MmdsConfig(#[from] MmdsConfigError),
7070
/// Entropy: {0}
7171
Entropy(#[from] EntropyError),
72+
/// Resource misconfiguration: {0}. Is the snapshot file corrupted?
73+
ResourcesError(#[from] ResourcesError),
7274
}
7375

7476
/// Holds the state of a balloon device connected to the MMIO space.
@@ -461,7 +463,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
461463

462464
constructor_args
463465
.vm_resources
464-
.update_from_restored_device(SharedDeviceType::Balloon(device.clone()));
466+
.update_from_restored_device(SharedDeviceType::Balloon(device.clone()))?;
465467

466468
restore_helper(
467469
device.clone(),
@@ -482,7 +484,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
482484

483485
constructor_args
484486
.vm_resources
485-
.update_from_restored_device(SharedDeviceType::VirtioBlock(device.clone()));
487+
.update_from_restored_device(SharedDeviceType::VirtioBlock(device.clone()))?;
486488

487489
restore_helper(
488490
device.clone(),
@@ -527,7 +529,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
527529

528530
constructor_args
529531
.vm_resources
530-
.update_from_restored_device(SharedDeviceType::Network(device.clone()));
532+
.update_from_restored_device(SharedDeviceType::Network(device.clone()))?;
531533

532534
restore_helper(
533535
device.clone(),
@@ -555,7 +557,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
555557

556558
constructor_args
557559
.vm_resources
558-
.update_from_restored_device(SharedDeviceType::Vsock(device.clone()));
560+
.update_from_restored_device(SharedDeviceType::Vsock(device.clone()))?;
559561

560562
restore_helper(
561563
device.clone(),
@@ -578,7 +580,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
578580

579581
constructor_args
580582
.vm_resources
581-
.update_from_restored_device(SharedDeviceType::Entropy(device.clone()));
583+
.update_from_restored_device(SharedDeviceType::Entropy(device.clone()))?;
582584

583585
restore_helper(
584586
device.clone(),

src/vmm/src/resources.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ impl VmResources {
202202

203203
/// Updates the resources from a restored device (used for configuring resources when
204204
/// restoring from a snapshot).
205-
pub fn update_from_restored_device(&mut self, device: SharedDeviceType) {
205+
pub fn update_from_restored_device(
206+
&mut self,
207+
device: SharedDeviceType,
208+
) -> Result<(), ResourcesError> {
206209
match device {
207210
SharedDeviceType::VirtioBlock(block) => {
208211
self.block.add_virtio_device(block);
@@ -214,6 +217,10 @@ impl VmResources {
214217

215218
SharedDeviceType::Balloon(balloon) => {
216219
self.balloon.set_device(balloon);
220+
221+
if self.vm_config.huge_pages != HugePageConfig::None {
222+
return Err(ResourcesError::BalloonDevice(BalloonConfigError::HugePages));
223+
}
217224
}
218225

219226
SharedDeviceType::Vsock(vsock) => {
@@ -223,6 +230,8 @@ impl VmResources {
223230
self.entropy.set_device(entropy);
224231
}
225232
}
233+
234+
Ok(())
226235
}
227236

228237
/// Returns whether dirty page tracking is enabled or not.
@@ -498,6 +507,7 @@ mod tests {
498507

499508
use super::*;
500509
use crate::cpu_config::templates::{CpuTemplateType, StaticCpuTemplate};
510+
use crate::devices::virtio::balloon::Balloon;
501511
use crate::devices::virtio::block::virtio::VirtioBlockError;
502512
use crate::devices::virtio::block::{BlockError, CacheType};
503513
use crate::devices::virtio::vsock::VSOCK_DEV_ID;
@@ -1442,6 +1452,33 @@ mod tests {
14421452
.unwrap_err();
14431453
}
14441454

1455+
#[test]
1456+
fn test_negative_restore_balloon_device_with_huge_pages() {
1457+
if KernelVersion::get().unwrap() >= KernelVersion::new(4, 16, 0) {
1458+
let mut vm_resources = default_vm_resources();
1459+
vm_resources.balloon = BalloonBuilder::new();
1460+
vm_resources
1461+
.update_vm_config(&MachineConfigUpdate {
1462+
huge_pages: Some(HugePageConfig::Hugetlbfs2M),
1463+
..Default::default()
1464+
})
1465+
.unwrap();
1466+
let err = vm_resources
1467+
.update_from_restored_device(SharedDeviceType::Balloon(Arc::new(Mutex::new(
1468+
Balloon::new(128, false, 0, true).unwrap(),
1469+
))))
1470+
.unwrap_err();
1471+
assert!(
1472+
matches!(
1473+
err,
1474+
ResourcesError::BalloonDevice(BalloonConfigError::HugePages)
1475+
),
1476+
"{:?}",
1477+
err
1478+
);
1479+
}
1480+
}
1481+
14451482
#[test]
14461483
fn test_set_entropy_device() {
14471484
let mut vm_resources = default_vm_resources();

0 commit comments

Comments
 (0)