Skip to content

Commit 841ac04

Browse files
committed
use bounce buffers for loading kernel if secret freedom is enabled
If secret freedom is enabled, the guest kernel and potential initrd needs to be loaded via bounce buffer, as we cannot directly do `read` syscalls that target guest memory. Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent 59cca16 commit 841ac04

File tree

4 files changed

+45
-51
lines changed

4 files changed

+45
-51
lines changed

src/vmm/src/arch/aarch64/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ pub mod vm;
1818

1919
use std::cmp::min;
2020
use std::fmt::Debug;
21-
use std::fs::File;
21+
use std::io::{Read, Seek};
2222

2323
use linux_loader::loader::pe::PE as Loader;
2424
use linux_loader::loader::{Cmdline, KernelLoader};
25-
use vm_memory::GuestMemoryError;
25+
use vm_memory::{GuestMemoryError, ReadVolatile};
2626

2727
use crate::arch::{BootProtocol, EntryPoint};
2828
use crate::cpu_config::aarch64::{CpuConfiguration, CpuConfigurationError};
@@ -187,16 +187,10 @@ fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 {
187187
}
188188

189189
/// Load linux kernel into guest memory.
190-
pub fn load_kernel(
191-
kernel: &File,
190+
pub fn load_kernel<R: ReadVolatile + Read + Seek>(
191+
mut kernel_file: R,
192192
guest_memory: &GuestMemoryMmap,
193193
) -> Result<EntryPoint, ConfigurationError> {
194-
// Need to clone the File because reading from it
195-
// mutates it.
196-
let mut kernel_file = kernel
197-
.try_clone()
198-
.map_err(|_| ConfigurationError::KernelFile)?;
199-
200194
let entry_addr = Loader::load(
201195
guest_memory,
202196
Some(GuestAddress(get_kernel_start())),

src/vmm/src/arch/x86_64/mod.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub mod xstate;
3131
#[allow(missing_docs)]
3232
pub mod generated;
3333

34-
use std::fs::File;
34+
use std::io::{Read, Seek};
3535

3636
use layout::CMDLINE_START;
3737
use linux_loader::configurator::linux::LinuxBootConfigurator;
@@ -44,6 +44,7 @@ use linux_loader::loader::elf::start_info::{
4444
};
4545
use linux_loader::loader::{Cmdline, KernelLoader, PvhBootCapability, load_cmdline};
4646
use log::debug;
47+
use vm_memory::ReadVolatile;
4748

4849
use super::EntryPoint;
4950
use crate::acpi::create_acpi_tables;
@@ -438,20 +439,14 @@ fn add_e820_entry(
438439
}
439440

440441
/// Load linux kernel into guest memory.
441-
pub fn load_kernel(
442-
kernel: &File,
442+
pub fn load_kernel<R: Read + ReadVolatile + Seek>(
443+
mut kernel: R,
443444
guest_memory: &GuestMemoryMmap,
444445
) -> Result<EntryPoint, ConfigurationError> {
445-
// Need to clone the File because reading from it
446-
// mutates it.
447-
let mut kernel_file = kernel
448-
.try_clone()
449-
.map_err(|_| ConfigurationError::KernelFile)?;
450-
451446
let entry_addr = Loader::load(
452447
guest_memory,
453448
None,
454-
&mut kernel_file,
449+
&mut kernel,
455450
Some(GuestAddress(get_kernel_start())),
456451
)
457452
.map_err(ConfigurationError::KernelLoader)?;

src/vmm/src/builder.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
66
use std::fmt::Debug;
77
use std::io;
8+
use std::os::fd::AsFd;
9+
use std::os::unix::fs::MetadataExt;
810
#[cfg(feature = "gdb")]
911
use std::sync::mpsc;
1012
use std::sync::{Arc, Mutex};
@@ -54,10 +56,11 @@ use crate::persist::{MicrovmState, MicrovmStateError};
5456
use crate::resources::VmResources;
5557
use crate::seccomp::BpfThreadMap;
5658
use crate::snapshot::Persist;
59+
use crate::utils::u64_to_usize;
5760
use crate::vmm_config::instance_info::InstanceInfo;
5861
use crate::vmm_config::machine_config::MachineConfigError;
5962
use crate::vstate::kvm::Kvm;
60-
use crate::vstate::memory::GuestRegionMmap;
63+
use crate::vstate::memory::{GuestRegionMmap, MaybeBounce};
6164
use crate::vstate::vcpu::{Vcpu, VcpuError};
6265
use crate::vstate::vm::Vm;
6366
use crate::{EventManager, Vmm, VmmError, device_manager};
@@ -237,8 +240,28 @@ pub fn build_microvm_for_boot(
237240
.register_memory_regions(guest_memory)
238241
.map_err(VmmError::Vm)?;
239242

240-
let entry_point = load_kernel(&boot_config.kernel_file, vmm.vm.guest_memory())?;
241-
let initrd = InitrdConfig::from_config(boot_config, vmm.vm.guest_memory())?;
243+
let entry_point = load_kernel(
244+
MaybeBounce::new(
245+
boot_config.kernel_file.try_clone().unwrap(),
246+
vm_resources.machine_config.secret_free,
247+
),
248+
vmm.vm.guest_memory(),
249+
)?;
250+
let initrd = match &boot_config.initrd_file {
251+
Some(initrd_file) => {
252+
let size = initrd_file
253+
.metadata()
254+
.map_err(InitrdError::Metadata)?
255+
.size();
256+
257+
Some(InitrdConfig::from_reader(
258+
vmm.vm.guest_memory(),
259+
MaybeBounce::new(initrd_file.as_fd(), vm_resources.machine_config.secret_free),
260+
u64_to_usize(size),
261+
)?)
262+
}
263+
None => None,
264+
};
242265

243266
#[cfg(feature = "gdb")]
244267
let (gdb_tx, gdb_rx) = mpsc::channel();

src/vmm/src/initrd.rs

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::fs::File;
5-
use std::os::unix::fs::MetadataExt;
6-
74
use vm_memory::{GuestAddress, GuestMemory, ReadVolatile, VolatileMemoryError};
85

96
use crate::arch::initrd_load_addr;
10-
use crate::utils::u64_to_usize;
11-
use crate::vmm_config::boot_source::BootConfig;
127
use crate::vstate::memory::GuestMemoryMmap;
138

149
/// Errors associated with initrd loading.
@@ -20,8 +15,6 @@ pub enum InitrdError {
2015
Load,
2116
/// Cannot image metadata: {0}
2217
Metadata(std::io::Error),
23-
/// Cannot copy initrd file fd: {0}
24-
CloneFd(std::io::Error),
2518
/// Cannot load initrd due to an invalid image: {0}
2619
Read(VolatileMemoryError),
2720
}
@@ -36,31 +29,20 @@ pub struct InitrdConfig {
3629
}
3730

3831
impl InitrdConfig {
39-
/// Load initrd into guest memory based on the boot config.
40-
pub fn from_config(
41-
boot_cfg: &BootConfig,
42-
vm_memory: &GuestMemoryMmap,
43-
) -> Result<Option<Self>, InitrdError> {
44-
Ok(match &boot_cfg.initrd_file {
45-
Some(f) => {
46-
let f = f.try_clone().map_err(InitrdError::CloneFd)?;
47-
Some(Self::from_file(vm_memory, f)?)
48-
}
49-
None => None,
50-
})
51-
}
52-
5332
/// Loads the initrd from a file into guest memory.
54-
pub fn from_file(vm_memory: &GuestMemoryMmap, mut file: File) -> Result<Self, InitrdError> {
55-
let size = file.metadata().map_err(InitrdError::Metadata)?.size();
56-
let size = u64_to_usize(size);
33+
pub fn from_reader<R: ReadVolatile>(
34+
vm_memory: &GuestMemoryMmap,
35+
mut reader: R,
36+
size: usize,
37+
) -> Result<Self, InitrdError> {
5738
let Some(address) = initrd_load_addr(vm_memory, size) else {
5839
return Err(InitrdError::Address);
5940
};
6041
let mut slice = vm_memory
6142
.get_slice(GuestAddress(address), size)
6243
.map_err(|_| InitrdError::Load)?;
63-
file.read_exact_volatile(&mut slice)
44+
reader
45+
.read_exact_volatile(&mut slice)
6446
.map_err(InitrdError::Read)?;
6547

6648
Ok(InitrdConfig {
@@ -105,7 +87,7 @@ mod tests {
10587

10688
// Need to reset the cursor to read initrd properly.
10789
tempfile.seek(SeekFrom::Start(0)).unwrap();
108-
let initrd = InitrdConfig::from_file(&gm, tempfile).unwrap();
90+
let initrd = InitrdConfig::from_reader(&gm, tempfile, image.len()).unwrap();
10991
assert!(gm.address_in_range(initrd.address));
11092
assert_eq!(initrd.size, image.len());
11193
}
@@ -120,7 +102,7 @@ mod tests {
120102

121103
// Need to reset the cursor to read initrd properly.
122104
tempfile.seek(SeekFrom::Start(0)).unwrap();
123-
let res = InitrdConfig::from_file(&gm, tempfile);
105+
let res = InitrdConfig::from_reader(&gm, tempfile, image.len());
124106
assert!(matches!(res, Err(InitrdError::Address)), "{:?}", res);
125107
}
126108

@@ -134,7 +116,7 @@ mod tests {
134116

135117
// Need to reset the cursor to read initrd properly.
136118
tempfile.seek(SeekFrom::Start(0)).unwrap();
137-
let res = InitrdConfig::from_file(&gm, tempfile);
119+
let res = InitrdConfig::from_reader(&gm, tempfile, image.len());
138120
assert!(matches!(res, Err(InitrdError::Address)), "{:?}", res);
139121
}
140122
}

0 commit comments

Comments
 (0)