@@ -85,13 +85,10 @@ pub(crate) fn init(is_bsp: bool) {
8585 if is_bsp {
8686 if let Ok ( ( start, size) ) = get_vtl1_memory_info ( ) {
8787 debug_serial_println ! ( "VSM: Protect GPAs from {:#x} to {:#x}" , start, start + size) ;
88- if protect_physical_memory_range (
89- PhysFrame :: range (
90- PhysFrame :: containing_address ( PhysAddr :: new ( start) ) ,
91- PhysFrame :: containing_address ( PhysAddr :: new ( start + size) ) ,
92- ) ,
93- MemAttr :: empty ( ) ,
94- )
88+ if protect_vtl1_physical_memory_range ( PhysFrame :: range (
89+ PhysFrame :: containing_address ( PhysAddr :: new ( start) ) ,
90+ PhysFrame :: containing_address ( PhysAddr :: new ( start + size) ) ,
91+ ) )
9592 . is_err ( )
9693 {
9794 panic ! ( "Failed to protect VTL1 memory" ) ;
@@ -1306,14 +1303,20 @@ fn copy_heki_pages_from_vtl0(pa: u64, nranges: u64) -> Option<Vec<HekiPage>> {
13061303 Some ( heki_pages)
13071304}
13081305
1309- /// This function protects a physical memory range. It is a safe wrapper for `hv_modify_vtl_protection_mask`.
1310- /// `phys_frame_range` specifies the physical frame range to protect
1311- /// `mem_attr` specifies the memory attributes to be applied to the range
1306+ /// This function protects a VTL0 physical memory range from potentially compromised VTL0 by
1307+ /// restricting its access permissions using VTL protection mask (e.g., kernel code integrity).
1308+ /// It is a safe wrapper for `hv_modify_vtl_protection_mask`. `phys_frame_range` specifies the
1309+ /// physical frame range to protect (must belong to VTL0) `mem_attr` specifies the memory
1310+ /// attributes (VTL0's allowed access) to be applied to the range
13121311#[ inline]
13131312pub ( crate ) fn protect_physical_memory_range (
13141313 phys_frame_range : PhysFrameRange < Size4KiB > ,
13151314 mem_attr : MemAttr ,
13161315) -> Result < ( ) , VsmError > {
1316+ let vtl1_range = crate :: platform_low ( ) . vtl1_phys_frame_range ( ) ;
1317+ if phys_frame_range. start < vtl1_range. end && vtl1_range. start < phys_frame_range. end {
1318+ return Err ( VsmError :: Vtl1MemoryOverlap ) ;
1319+ }
13171320 let pa = phys_frame_range. start . start_address ( ) . as_u64 ( ) ;
13181321 let num_pages = phys_frame_range. count ( ) as u64 ;
13191322 if num_pages > 0 {
@@ -1323,6 +1326,30 @@ pub(crate) fn protect_physical_memory_range(
13231326 Ok ( ( ) )
13241327}
13251328
1329+ /// This function is a variant of [`protect_physical_memory_range`] to protect a VTL1 physical memory range.
1330+ /// Unlike [`protect_physical_memory_range`], this is intended exclusively for securing VTL1's own pages.
1331+ /// VTL0 should never access VTL1 memory, so the memory attribute is always empty (no read, write, or execute).
1332+ ///
1333+ /// Note. This function doesn't check whether `phys_frame_range` belongs to VTL1 because it is called by BSP
1334+ /// before the kernel platform data structure is initialized. To this end, one might call this function with
1335+ /// a VTL0 physical memory range which only restricts access to the range.
1336+ #[ inline]
1337+ pub ( crate ) fn protect_vtl1_physical_memory_range (
1338+ phys_frame_range : PhysFrameRange < Size4KiB > ,
1339+ ) -> Result < ( ) , VsmError > {
1340+ let pa = phys_frame_range. start . start_address ( ) . as_u64 ( ) ;
1341+ let num_pages = phys_frame_range. count ( ) as u64 ;
1342+ if num_pages > 0 {
1343+ hv_modify_vtl_protection_mask (
1344+ pa,
1345+ num_pages,
1346+ mem_attr_to_hv_page_prot_flags ( MemAttr :: empty ( ) ) ,
1347+ )
1348+ . map_err ( VsmError :: HypercallFailed ) ?;
1349+ }
1350+ Ok ( ( ) )
1351+ }
1352+
13261353/// Data structure for maintaining the memory content of a kernel module by its sections. Currently, it only maintains
13271354/// certain sections like `.text` and `.init.text` which are needed for module validation.
13281355pub struct ModuleMemory {
0 commit comments