Skip to content

Commit 10a6057

Browse files
authored
Merge branch 'main' into save_restore_vmgs
2 parents 7d1b944 + f1701ab commit 10a6057

File tree

21 files changed

+839
-663
lines changed

21 files changed

+839
-663
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5428,6 +5428,7 @@ dependencies = [
54285428
"petri_artifacts_core",
54295429
"petri_artifacts_vmm_test",
54305430
"pipette_client",
5431+
"powershell_builder",
54315432
"prost",
54325433
"scsidisk_resources",
54335434
"serde",
@@ -5663,6 +5664,14 @@ version = "0.2.0"
56635664
source = "registry+https://github.com/rust-lang/crates.io-index"
56645665
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
56655666

5667+
[[package]]
5668+
name = "powershell_builder"
5669+
version = "0.0.0"
5670+
dependencies = [
5671+
"guid",
5672+
"jiff",
5673+
]
5674+
56665675
[[package]]
56675676
name = "prettyplease"
56685677
version = "0.1.25"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ pal_async = { path = "support/pal/pal_async" }
134134
pal_async_test = { path = "support/pal/pal_async_test" }
135135
pal_event = { path = "support/pal/pal_event" }
136136
pal_uring = { path = "support/pal/pal_uring" }
137+
powershell_builder = { path = "support/powershell_builder" }
137138
safeatomic = { path = "support/safeatomic" }
138139
serde_helpers = { path = "support/serde_helpers" }
139140
sev_guest_device = { path = "support/sev_guest_device" }

flowey/flowey_lib_hvlite/src/_jobs/cfg_versions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub const MDBOOK: &str = "0.4.40";
2323
pub const MDBOOK_ADMONISH: &str = "1.18.0";
2424
pub const MDBOOK_MERMAID: &str = "0.14.0";
2525
pub const RUSTUP_TOOLCHAIN: &str = "1.87.0";
26-
pub const MU_MSVM: &str = "25.1.3";
26+
pub const MU_MSVM: &str = "25.1.4";
2727
pub const NEXTEST: &str = "0.9.96";
2828
pub const NODEJS: &str = "18.x";
2929
// N.B. Kernel version numbers for dev and stable branches are not directly

openhcl/build_info/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ pub struct BuildInfo {
1515
revision: &'static str,
1616
#[inspect(safe, rename = "scm_branch")]
1717
branch: &'static str,
18+
#[inspect(safe)]
19+
internal_scm_revision: &'static str,
20+
#[inspect(safe)]
21+
internal_scm_branch: &'static str,
1822
}
1923

2024
impl BuildInfo {
@@ -35,6 +39,16 @@ impl BuildInfo {
3539
} else {
3640
""
3741
},
42+
internal_scm_revision: if let Some(r) = option_env!("INTERNAL_GIT_SHA") {
43+
r
44+
} else {
45+
""
46+
},
47+
internal_scm_branch: if let Some(r) = option_env!("INTERNAL_GIT_BRANCH") {
48+
r
49+
} else {
50+
""
51+
},
3852
}
3953
}
4054

openhcl/hcl/src/ioctl.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3039,8 +3039,6 @@ impl Hcl {
30393039
.expect("check_vtl_access hypercall should not fail")
30403040
};
30413041

3042-
// TODO GUEST_VSM: for isolated VMs, if the status is operation denied,
3043-
// return memory unaccepted?
30443042
status.result().map_err(Error::CheckVtlAccess)?;
30453043

30463044
let access_result = output[0];

openhcl/openhcl_dma_manager/src/lib.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ pub struct DmaClientParameters {
155155
struct DmaManagerInner {
156156
shared_spawner: Option<PagePoolAllocatorSpawner>,
157157
private_spawner: Option<PagePoolAllocatorSpawner>,
158-
lower_vtl: Arc<DmaManagerLowerVtl>,
158+
lower_vtl: Option<Arc<DmaManagerLowerVtl>>,
159159
}
160160

161161
/// Used by [`OpenhclDmaManager`] to modify VTL permissions via
@@ -164,6 +164,9 @@ struct DmaManagerInner {
164164
/// This is required due to some users (like the GET or partition struct itself)
165165
/// that are constructed before the partition struct which normally implements
166166
/// this trait.
167+
///
168+
/// This type should never be created on a hardware isolated VM, as the
169+
/// hypervisor is untrusted.
167170
struct DmaManagerLowerVtl {
168171
mshv_hvcall: hcl::ioctl::MshvHvcall,
169172
}
@@ -261,7 +264,12 @@ impl DmaManagerInner {
261264
private
262265
.allocator(device_name.into())
263266
.context("failed to create private allocator")?,
264-
self.lower_vtl.clone(),
267+
self.lower_vtl
268+
.as_ref()
269+
.ok_or(anyhow::anyhow!(
270+
"lower vtl not available on hardware isolated platforms"
271+
))?
272+
.clone(),
265273
))
266274
}
267275
},
@@ -290,7 +298,12 @@ impl DmaManagerInner {
290298
// lowering VTL permissions is required.
291299
DmaClientBacking::LockedMemoryLowerVtl(LowerVtlMemorySpawner::new(
292300
LockedMemorySpawner,
293-
self.lower_vtl.clone(),
301+
self.lower_vtl
302+
.as_ref()
303+
.ok_or(anyhow::anyhow!(
304+
"lower vtl not available on hardware isolated platforms"
305+
))?
306+
.clone(),
294307
))
295308
}
296309
},
@@ -308,6 +321,7 @@ impl OpenhclDmaManager {
308321
shared_ranges: &[MemoryRange],
309322
private_ranges: &[MemoryRange],
310323
vtom: u64,
324+
isolation_type: virt::IsolationType,
311325
) -> anyhow::Result<Self> {
312326
let shared_pool = if shared_ranges.is_empty() {
313327
None
@@ -337,7 +351,11 @@ impl OpenhclDmaManager {
337351
inner: Arc::new(DmaManagerInner {
338352
shared_spawner: shared_pool.as_ref().map(|pool| pool.allocator_spawner()),
339353
private_spawner: private_pool.as_ref().map(|pool| pool.allocator_spawner()),
340-
lower_vtl: DmaManagerLowerVtl::new().context("failed to create lower vtl")?,
354+
lower_vtl: if isolation_type.is_hardware_isolated() {
355+
None
356+
} else {
357+
Some(DmaManagerLowerVtl::new().context("failed to create lower vtl")?)
358+
},
341359
}),
342360
shared_pool,
343361
private_pool,

openhcl/underhill_core/src/worker.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,7 @@ async fn new_underhill_vm(
15231523
.vtom_offset_bit
15241524
.map(|bit| 1 << bit)
15251525
.unwrap_or(0),
1526+
isolation,
15261527
)
15271528
.context("failed to create global dma manager")?;
15281529

openhcl/underhill_mem/src/init.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
227227
tracing::debug!("Building valid encrypted memory view");
228228
let encrypted_memory_view = {
229229
let _span = tracing::info_span!("create encrypted memory view", CVM_ALLOWED).entered();
230-
GuestPartitionMemoryView::new(params.mem_layout, true)?
230+
GuestPartitionMemoryView::new(
231+
params.mem_layout,
232+
crate::mapping::GuestValidMemoryType::Encrypted,
233+
true,
234+
)?
231235
};
232236

233237
tracing::debug!("Building encrypted memory map");
@@ -241,8 +245,8 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
241245

242246
let use_vtl1 = params.maximum_vtl >= Vtl::Vtl1;
243247

244-
// Start by giving VTL 0 full access to all lower-vtl memory. TODO GUEST
245-
// VSM: with lazy acceptance, it should instead be initialized to no
248+
// Start by giving VTL 0 full access to all lower-vtl memory.
249+
// TODO GUEST VSM: with lazy acceptance, it should instead be initialized to no
246250
// access.
247251
tracing::debug!("Building VTL0 memory map");
248252
let vtl0_mapping = Arc::new({
@@ -321,7 +325,11 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
321325

322326
let shared_memory_view = {
323327
let _span = tracing::info_span!("create shared memory view", CVM_ALLOWED).entered();
324-
GuestPartitionMemoryView::new(params.complete_memory_layout, false)?
328+
GuestPartitionMemoryView::new(
329+
params.complete_memory_layout,
330+
crate::mapping::GuestValidMemoryType::Shared,
331+
false,
332+
)?
325333
};
326334

327335
let valid_shared_memory = shared_memory_view.partition_valid_memory();
@@ -442,9 +450,6 @@ pub async fn init(params: &Init<'_>) -> anyhow::Result<MemoryMappings> {
442450
acceptor.as_ref().unwrap().clone(),
443451
)) as Arc<dyn ProtectIsolatedMemory>;
444452

445-
// TODO GUEST VSM: create guest memory objects using execute permissions
446-
// for the instruction emulator to use when reading instructions.
447-
448453
tracing::debug!("Creating VTL0 guest memory for kernel execute access");
449454
let vtl0_kx_gm = GuestMemory::new_multi_region(
450455
"vtl0_kx",

openhcl/underhill_mem/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
766766
for gpn in
767767
ram_range.range.start() / PAGE_SIZE as u64..ram_range.range.end() / PAGE_SIZE as u64
768768
{
769-
// TODO GUEST_VSM: for now, use the encrypted mapping to
769+
// TODO GUEST VSM: for now, use the encrypted mapping to
770770
// find all accepted memory. When lazy acceptance exists,
771771
// this should track all pages that have been accepted and
772772
// should be used instead.
@@ -955,6 +955,12 @@ impl ProtectIsolatedMemory for HardwareIsolatedMemoryProtector {
955955
Ok(())
956956
}
957957

958+
fn is_overlay_page(&self, vtl: GuestVtl, gpn: u64) -> bool {
959+
self.inner.lock().overlay_pages[vtl]
960+
.iter()
961+
.any(|p| p.gpn == gpn)
962+
}
963+
958964
fn set_vtl1_protections_enabled(&self) {
959965
self.vtl1_protections_enabled
960966
.store(true, std::sync::atomic::Ordering::Relaxed);

openhcl/underhill_mem/src/mapping.rs

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ impl<'a> GuestPartitionMemoryView<'a> {
3535
/// page.
3636
pub fn new(
3737
memory_layout: &'a MemoryLayout,
38+
memory_type: GuestValidMemoryType,
3839
valid_bitmap_state: bool,
3940
) -> Result<Self, MappingError> {
4041
let valid_memory =
41-
GuestValidMemory::new(memory_layout, valid_bitmap_state).map(Arc::new)?;
42+
GuestValidMemory::new(memory_layout, memory_type, valid_bitmap_state).map(Arc::new)?;
4243
Ok(Self {
4344
memory_layout,
4445
valid_memory,
@@ -88,6 +89,18 @@ impl GuestMemoryView {
8889
}
8990
}
9091

92+
#[derive(Error, Debug)]
93+
#[error("the specified page is not mapped")]
94+
struct NotMapped;
95+
96+
#[derive(Error, Debug)]
97+
enum BitmapFailure {
98+
#[error("the specified page was accessed using the wrong visibility mapping")]
99+
IncorrectHostVisibilityAccess,
100+
#[error("the specified page access violates VTL 1 protections")]
101+
Vtl1ProtectionsViolation,
102+
}
103+
91104
/// SAFETY: Implementing the `GuestMemoryAccess` contract, including the
92105
/// size and lifetime of the mappings and bitmaps.
93106
unsafe impl GuestMemoryAccess for GuestMemoryView {
@@ -164,6 +177,91 @@ unsafe impl GuestMemoryAccess for GuestMemoryView {
164177
.map(|bitmap| bitmap.access_bitmap())
165178
}
166179
}
180+
181+
fn page_fault(
182+
&self,
183+
address: u64,
184+
len: usize,
185+
write: bool,
186+
bitmap_failure: bool,
187+
) -> guestmem::PageFaultAction {
188+
let gpn = address / PAGE_SIZE as u64;
189+
if !bitmap_failure {
190+
guestmem::PageFaultAction::Fail(guestmem::PageFaultError::other(NotMapped {}))
191+
} else {
192+
let valid_memory = self
193+
.memory_mapping
194+
.valid_memory
195+
.as_ref()
196+
.expect("all backings with bitmaps should have a GuestValidMemory");
197+
if !valid_memory.check_valid(gpn) {
198+
match valid_memory.memory_type() {
199+
GuestValidMemoryType::Shared => {
200+
tracing::warn!(
201+
?address,
202+
?len,
203+
?write,
204+
"tried to access private page using shared mapping"
205+
);
206+
guestmem::PageFaultAction::Fail(guestmem::PageFaultError::new(
207+
guestmem::GuestMemoryErrorKind::NotShared,
208+
BitmapFailure::IncorrectHostVisibilityAccess,
209+
))
210+
}
211+
GuestValidMemoryType::Encrypted => {
212+
tracing::warn!(
213+
?address,
214+
?len,
215+
?write,
216+
"tried to access shared page using private mapping"
217+
);
218+
guestmem::PageFaultAction::Fail(guestmem::PageFaultError::new(
219+
guestmem::GuestMemoryErrorKind::NotPrivate,
220+
BitmapFailure::IncorrectHostVisibilityAccess,
221+
))
222+
}
223+
}
224+
} else {
225+
// Currently, only VTL 1 permissions are tracked, so any
226+
// invalid accesses here violate VTL 1 protections.
227+
if let Some(permission_bitmaps) = &self.memory_mapping.permission_bitmaps {
228+
let check_bitmap = if write {
229+
&permission_bitmaps.write_bitmap
230+
} else {
231+
match self.view_type {
232+
GuestMemoryViewReadType::Read => &permission_bitmaps.read_bitmap,
233+
GuestMemoryViewReadType::KernelExecute => {
234+
&permission_bitmaps.kernel_execute_bitmap
235+
}
236+
GuestMemoryViewReadType::UserExecute => {
237+
&permission_bitmaps.user_execute_bitmap
238+
}
239+
}
240+
};
241+
242+
if !check_bitmap.page_state(gpn) {
243+
tracing::warn!(?address, ?len, ?write, ?self.view_type, "VTL 1 permissions violation");
244+
245+
return guestmem::PageFaultAction::Fail(guestmem::PageFaultError::new(
246+
guestmem::GuestMemoryErrorKind::VtlProtected,
247+
BitmapFailure::Vtl1ProtectionsViolation,
248+
));
249+
}
250+
}
251+
252+
// Possible race condition where the bitmaps are in transition
253+
// and while the original check failed, the bitmaps now show
254+
// valid access to the page. Retry in that situation.
255+
guestmem::PageFaultAction::Retry
256+
}
257+
}
258+
}
259+
}
260+
261+
#[derive(Debug, Copy, Clone)]
262+
pub enum GuestValidMemoryType {
263+
Shared,
264+
Encrypted,
167265
}
168266

169267
/// Partition-wide (cross-vtl) tracking of valid memory that can be used in
@@ -172,10 +270,15 @@ unsafe impl GuestMemoryAccess for GuestMemoryView {
172270
pub struct GuestValidMemory {
173271
valid_bitmap: GuestMemoryBitmap,
174272
valid_bitmap_lock: Mutex<()>,
273+
memory_type: GuestValidMemoryType,
175274
}
176275

177276
impl GuestValidMemory {
178-
fn new(memory_layout: &MemoryLayout, valid_bitmap_state: bool) -> Result<Self, MappingError> {
277+
fn new(
278+
memory_layout: &MemoryLayout,
279+
memory_type: GuestValidMemoryType,
280+
valid_bitmap_state: bool,
281+
) -> Result<Self, MappingError> {
179282
let valid_bitmap = {
180283
let mut bitmap = {
181284
// Calculate the total size of the address space by looking at the ending region.
@@ -201,6 +304,7 @@ impl GuestValidMemory {
201304
Ok(GuestValidMemory {
202305
valid_bitmap,
203306
valid_bitmap_lock: Default::default(),
307+
memory_type,
204308
})
205309
}
206310

@@ -215,6 +319,11 @@ impl GuestValidMemory {
215319
self.valid_bitmap.page_state(gpn)
216320
}
217321

322+
/// Returns the type of memory tracked by the bitmap
323+
pub(crate) fn memory_type(&self) -> GuestValidMemoryType {
324+
self.memory_type
325+
}
326+
218327
fn access_bitmap(&self) -> guestmem::BitmapInfo {
219328
let ptr = NonNull::new(self.valid_bitmap.as_ptr()).unwrap();
220329
guestmem::BitmapInfo {

0 commit comments

Comments
 (0)