Skip to content

Commit ea16e07

Browse files
committed
[host] adds init-paging feature
This is an extra feature flag that allows disabling our paging setup. This is needed to further enable custom guests and should not impact any of our current workloads. init-paging is on by default. Signed-off-by: danbugs <[email protected]>
1 parent 7d54ffc commit ea16e07

File tree

11 files changed

+152
-75
lines changed

11 files changed

+152
-75
lines changed

Justfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ test-like-ci config=default-target hypervisor="kvm":
7575
@# with default features
7676
just test {{config}} {{ if hypervisor == "mshv3" {"mshv3"} else {""} }}
7777

78-
@# with only one driver enabled + seccomp
79-
just test {{config}} seccomp,build-metadata,{{ if hypervisor == "mshv" {"mshv2"} else if hypervisor == "mshv3" {"mshv3"} else {"kvm"} }}
78+
@# with only one driver enabled + seccomp + build-metadata + init-paging
79+
just test {{config}} seccomp,build-metadata,init-paging,{{ if hypervisor == "mshv" {"mshv2"} else if hypervisor == "mshv3" {"mshv3"} else {"kvm"} }}
8080

8181
@# make sure certain cargo features compile
8282
cargo check -p hyperlight-host --features crashdump
@@ -119,7 +119,7 @@ test-integration guest target=default-target features="":
119119
test-seccomp target=default-target features="":
120120
@# run seccomp test with feature "seccomp" on and off
121121
cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --lib {{ if features =="" {''} else { "--features " + features } }} -- --ignored
122-
cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --no-default-features {{ if features =~"mshv3" {"--features mshv3"} else {"--features mshv2,kvm" } }} --lib -- --ignored
122+
cargo test --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host test_violate_seccomp_filters --no-default-features {{ if features =~"mshv3" {"--features init-paging,mshv3"} else {"--features mshv2,init-paging,kvm" } }} --lib -- --ignored
123123

124124
# runs tests that ensure compilation fails when it should
125125
test-compilation-fail target=default-target:

src/hyperlight_host/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ cfg_aliases = "0.2.1"
119119
built = { version = "0.8.0", optional = true, features = ["chrono", "git2"] }
120120

121121
[features]
122-
default = ["kvm", "mshv2", "seccomp", "build-metadata"]
122+
default = ["kvm", "mshv2", "seccomp", "build-metadata", "init-paging"]
123123
seccomp = ["dep:seccompiler"]
124124
function_call_metrics = []
125125
executable_heap = []
@@ -134,6 +134,7 @@ mshv3 = ["dep:mshv-bindings3", "dep:mshv-ioctls3"]
134134
gdb = ["dep:gdbstub", "dep:gdbstub_arch"]
135135
fuzzing = ["hyperlight-common/fuzzing"]
136136
build-metadata = ["dep:built"]
137+
init-paging = []
137138

138139
[[bench]]
139140
name = "benchmarks"

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ use super::gdb::{
6161
#[cfg(gdb)]
6262
use super::handlers::DbgMemAccessHandlerWrapper;
6363
use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
64+
#[cfg(feature = "init-paging")]
6465
use super::{
6566
CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE,
66-
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE, Hypervisor, InterruptHandle, LinuxInterruptHandle,
67-
VirtualCPU,
67+
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE,
6868
};
69+
use super::{HyperlightExit, Hypervisor, InterruptHandle, LinuxInterruptHandle, VirtualCPU};
6970
#[cfg(gdb)]
7071
use crate::HyperlightError;
71-
use crate::hypervisor::HyperlightExit;
7272
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
7373
use crate::mem::ptr::{GuestPtr, RawPtr};
7474
use crate::sandbox::SandboxConfiguration;
@@ -436,11 +436,12 @@ impl HypervLinuxDriver {
436436
}
437437

438438
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
439-
fn setup_initial_sregs(vcpu: &mut VcpuFd, pml4_addr: u64) -> Result<()> {
439+
fn setup_initial_sregs(vcpu: &mut VcpuFd, _pml4_addr: u64) -> Result<()> {
440+
#[cfg(feature = "init-paging")]
440441
let sregs = SpecialRegisters {
441442
cr0: CR0_PE | CR0_MP | CR0_ET | CR0_NE | CR0_AM | CR0_PG | CR0_WP,
442443
cr4: CR4_PAE | CR4_OSFXSR | CR4_OSXMMEXCPT,
443-
cr3: pml4_addr,
444+
cr3: _pml4_addr,
444445
efer: EFER_LME | EFER_LMA | EFER_SCE | EFER_NX,
445446
cs: SegmentRegister {
446447
type_: 11,
@@ -457,6 +458,14 @@ impl HypervLinuxDriver {
457458
},
458459
..Default::default()
459460
};
461+
462+
#[cfg(not(feature = "init-paging"))]
463+
let sregs = SpecialRegisters {
464+
cs: SegmentRegister {
465+
base: 0,
466+
selector: 0,
467+
},
468+
};
460469
vcpu.set_sregs(&sregs)?;
461470
Ok(())
462471
}

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ use super::surrogate_process::SurrogateProcess;
4141
use super::surrogate_process_manager::*;
4242
use super::windows_hypervisor_platform::{VMPartition, VMProcessor};
4343
use super::wrappers::{HandleWrapper, WHvFPURegisters};
44+
#[cfg(feature = "init-paging")]
4445
use super::{
4546
CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE,
46-
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE, HyperlightExit, Hypervisor, InterruptHandle, VirtualCPU,
47+
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE,
4748
};
49+
use super::{HyperlightExit, Hypervisor, InterruptHandle, VirtualCPU};
4850
use crate::hypervisor::fpu::FP_CONTROL_WORD_DEFAULT;
4951
use crate::hypervisor::wrappers::WHvGeneralRegisters;
5052
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
@@ -125,9 +127,10 @@ impl HypervWindowsDriver {
125127
})
126128
}
127129

128-
fn setup_initial_sregs(proc: &mut VMProcessor, pml4_addr: u64) -> Result<()> {
130+
fn setup_initial_sregs(proc: &mut VMProcessor, _pml4_addr: u64) -> Result<()> {
131+
#[cfg(feature = "init-paging")]
129132
proc.set_registers(&[
130-
(WHvX64RegisterCr3, WHV_REGISTER_VALUE { Reg64: pml4_addr }),
133+
(WHvX64RegisterCr3, WHV_REGISTER_VALUE { Reg64: _pml4_addr }),
131134
(
132135
WHvX64RegisterCr4,
133136
WHV_REGISTER_VALUE {
@@ -151,13 +154,37 @@ impl HypervWindowsDriver {
151154
WHV_REGISTER_VALUE {
152155
Segment: WHV_X64_SEGMENT_REGISTER {
153156
Anonymous: WHV_X64_SEGMENT_REGISTER_0 {
154-
Attributes: 0b1011 | (1 << 4) | (1 << 7) | (1 << 13), // Type (11: Execute/Read, accessed) | L (64-bit mode) | P (present) | S (code segment)
157+
Attributes: 0b1011 | (1 << 4) | (1 << 7) | (1 << 13), // Type 11 + S + P + L
155158
},
156-
..Default::default() // zero out the rest
159+
..Default::default()
157160
},
158161
},
159162
),
160-
])?;
163+
(
164+
WHvX64RegisterTr,
165+
WHV_REGISTER_VALUE {
166+
Segment: WHV_X64_SEGMENT_REGISTER {
167+
Limit: 0xFFFF,
168+
Anonymous: WHV_X64_SEGMENT_REGISTER_0 {
169+
Attributes: 0b1011 | (1 << 7), // Type 11 + P
170+
},
171+
..Default::default()
172+
},
173+
},
174+
),
175+
]);
176+
177+
#[cfg(not(feature = "init-paging"))]
178+
proc.set_registers(&[(
179+
WHvX64RegisterCs,
180+
WHV_REGISTER_VALUE {
181+
Segment: WHV_X64_SEGMENT_REGISTER {
182+
Base: 0,
183+
Selector: 0,
184+
..Default::default()
185+
},
186+
},
187+
)]);
161188
Ok(())
162189
}
163190

src/hyperlight_host/src/hypervisor/kvm.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, KvmDebug
3535
#[cfg(gdb)]
3636
use super::handlers::DbgMemAccessHandlerWrapper;
3737
use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper};
38+
#[cfg(feature = "init-paging")]
3839
use super::{
3940
CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE,
40-
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE, HyperlightExit, Hypervisor, InterruptHandle,
41-
LinuxInterruptHandle, VirtualCPU,
41+
EFER_LMA, EFER_LME, EFER_NX, EFER_SCE,
4242
};
43+
use super::{HyperlightExit, Hypervisor, InterruptHandle, LinuxInterruptHandle, VirtualCPU};
4344
#[cfg(gdb)]
4445
use crate::HyperlightError;
4546
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags};
@@ -390,14 +391,21 @@ impl KVMDriver {
390391
}
391392

392393
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
393-
fn setup_initial_sregs(vcpu_fd: &mut VcpuFd, pml4_addr: u64) -> Result<()> {
394+
fn setup_initial_sregs(vcpu_fd: &mut VcpuFd, _pml4_addr: u64) -> Result<()> {
394395
// setup paging and IA-32e (64-bit) mode
395396
let mut sregs = vcpu_fd.get_sregs()?;
396-
sregs.cr3 = pml4_addr;
397-
sregs.cr4 = CR4_PAE | CR4_OSFXSR | CR4_OSXMMEXCPT;
398-
sregs.cr0 = CR0_PE | CR0_MP | CR0_ET | CR0_NE | CR0_AM | CR0_PG | CR0_WP;
399-
sregs.efer = EFER_LME | EFER_LMA | EFER_SCE | EFER_NX;
400-
sregs.cs.l = 1; // required for 64-bit mode
397+
cfg_if::cfg_if! {
398+
if #[cfg(feature = "init-paging")] {
399+
sregs.cr3 = _pml4_addr;
400+
sregs.cr4 = CR4_PAE | CR4_OSFXSR | CR4_OSXMMEXCPT;
401+
sregs.cr0 = CR0_PE | CR0_MP | CR0_ET | CR0_NE | CR0_AM | CR0_PG | CR0_WP;
402+
sregs.efer = EFER_LME | EFER_LMA | EFER_SCE | EFER_NX;
403+
sregs.cs.l = 1; // required for 64-bit mode
404+
} else {
405+
sregs.cs.base = 0;
406+
sregs.cs.selector = 0;
407+
}
408+
}
401409
vcpu_fd.set_sregs(&sregs)?;
402410
Ok(())
403411
}

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,24 @@ use self::handlers::{
7575
};
7676
use crate::mem::ptr::RawPtr;
7777

78-
pub(crate) const CR4_PAE: u64 = 1 << 5;
79-
pub(crate) const CR4_OSFXSR: u64 = 1 << 9;
80-
pub(crate) const CR4_OSXMMEXCPT: u64 = 1 << 10;
81-
pub(crate) const CR0_PE: u64 = 1;
82-
pub(crate) const CR0_MP: u64 = 1 << 1;
83-
pub(crate) const CR0_ET: u64 = 1 << 4;
84-
pub(crate) const CR0_NE: u64 = 1 << 5;
85-
pub(crate) const CR0_WP: u64 = 1 << 16;
86-
pub(crate) const CR0_AM: u64 = 1 << 18;
87-
pub(crate) const CR0_PG: u64 = 1 << 31;
88-
pub(crate) const EFER_LME: u64 = 1 << 8;
89-
pub(crate) const EFER_LMA: u64 = 1 << 10;
90-
pub(crate) const EFER_SCE: u64 = 1;
91-
pub(crate) const EFER_NX: u64 = 1 << 11;
78+
cfg_if::cfg_if! {
79+
if #[cfg(feature = "init-paging")] {
80+
pub(crate) const CR4_PAE: u64 = 1 << 5;
81+
pub(crate) const CR4_OSFXSR: u64 = 1 << 9;
82+
pub(crate) const CR4_OSXMMEXCPT: u64 = 1 << 10;
83+
pub(crate) const CR0_PE: u64 = 1;
84+
pub(crate) const CR0_MP: u64 = 1 << 1;
85+
pub(crate) const CR0_ET: u64 = 1 << 4;
86+
pub(crate) const CR0_NE: u64 = 1 << 5;
87+
pub(crate) const CR0_WP: u64 = 1 << 16;
88+
pub(crate) const CR0_AM: u64 = 1 << 18;
89+
pub(crate) const CR0_PG: u64 = 1 << 31;
90+
pub(crate) const EFER_LME: u64 = 1 << 8;
91+
pub(crate) const EFER_LMA: u64 = 1 << 10;
92+
pub(crate) const EFER_SCE: u64 = 1;
93+
pub(crate) const EFER_NX: u64 = 1 << 11;
94+
}
95+
}
9296

9397
/// These are the generic exit reasons that we can handle from a Hypervisor the Hypervisors run method is responsible for mapping from
9498
/// the hypervisor specific exit reasons to these generic ones

src/hyperlight_host/src/mem/elf.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ use goblin::elf::reloc::{R_AARCH64_NONE, R_AARCH64_RELATIVE};
1919
#[cfg(target_arch = "x86_64")]
2020
use goblin::elf::reloc::{R_X86_64_NONE, R_X86_64_RELATIVE};
2121
use goblin::elf::{Elf, ProgramHeaders, Reloc};
22+
#[cfg(not(feature = "init-paging"))]
23+
use goblin::elf32::program_header::PT_LOAD;
24+
#[cfg(feature = "init-paging")]
2225
use goblin::elf64::program_header::PT_LOAD;
2326

2427
use crate::{Result, log_then_return, new_error};

src/hyperlight_host/src/mem/layout.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ use hyperlight_common::mem::{GuestMemoryRegion, HyperlightPEB, PAGE_SIZE_USIZE};
2020
use rand::{RngCore, rng};
2121
use tracing::{Span, instrument};
2222

23+
#[cfg(feature = "init-paging")]
24+
use super::memory_region::MemoryRegionType::PageTables;
2325
use super::memory_region::MemoryRegionType::{
24-
Code, GuardPage, Heap, HostFunctionDefinitions, InitData, InputData, OutputData, PageTables,
25-
Peb, Stack,
26+
Code, GuardPage, Heap, HostFunctionDefinitions, InitData, InputData, OutputData, Peb, Stack,
2627
};
2728
use super::memory_region::{
2829
DEFAULT_GUEST_BLOB_MEM_FLAGS, MemoryRegion, MemoryRegionFlags, MemoryRegionVecBuilder,
2930
};
31+
#[cfg(feature = "init-paging")]
3032
use super::mgr::AMOUNT_OF_MEMORY_PER_PT;
3133
use super::shared_mem::{ExclusiveSharedMemory, GuestSharedMemory, SharedMemory};
3234
use crate::error::HyperlightError::{GuestOffsetIsInvalid, MemoryRequestTooBig};
@@ -257,11 +259,13 @@ impl SandboxMemoryLayout {
257259
init_data_size: usize,
258260
init_data_permissions: Option<MemoryRegionFlags>,
259261
) -> Result<Self> {
260-
let total_page_table_size =
261-
Self::get_total_page_table_size(cfg, code_size, stack_size, heap_size);
262-
let guest_code_offset = total_page_table_size;
262+
#[cfg(feature = "init-paging")]
263+
let base = Self::get_total_page_table_size(cfg, code_size, stack_size, heap_size);
264+
#[cfg(not(feature = "init-paging"))]
265+
let base = Self::BASE_ADDRESS;
266+
let guest_code_offset = base;
263267
// The following offsets are to the fields of the PEB struct itself!
264-
let peb_offset = total_page_table_size + round_up_to(code_size, PAGE_SIZE_USIZE);
268+
let peb_offset = base + round_up_to(code_size, PAGE_SIZE_USIZE);
265269
let peb_security_cookie_seed_offset =
266270
peb_offset + offset_of!(HyperlightPEB, security_cookie_seed);
267271
let peb_guest_dispatch_function_ptr_offset =
@@ -325,7 +329,7 @@ impl SandboxMemoryLayout {
325329
guest_user_stack_buffer_offset,
326330
peb_address,
327331
guard_page_offset,
328-
total_page_table_size,
332+
total_page_table_size: base,
329333
guest_code_offset,
330334
init_data_offset,
331335
init_data_size,
@@ -507,6 +511,7 @@ impl SandboxMemoryLayout {
507511
}
508512

509513
#[cfg(test)]
514+
#[cfg(feature = "init-paging")]
510515
/// Get the page table size
511516
fn get_page_table_size(&self) -> usize {
512517
self.total_page_table_size
@@ -523,6 +528,7 @@ impl SandboxMemoryLayout {
523528
// then divide that by 0x200_000 (as we can map 2MB in each PT).
524529
// This will give us the total size of the PTs required for the sandbox to which we can add the size of the PML4, PDPT and PD.
525530
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
531+
#[cfg(feature = "init-paging")]
526532
fn get_total_page_table_size(
527533
cfg: SandboxConfiguration,
528534
code_size: usize,
@@ -582,19 +588,23 @@ impl SandboxMemoryLayout {
582588
pub fn get_memory_regions(&self, shared_mem: &GuestSharedMemory) -> Result<Vec<MemoryRegion>> {
583589
let mut builder = MemoryRegionVecBuilder::new(Self::BASE_ADDRESS, shared_mem.base_addr());
584590

585-
// PML4, PDPT, PD
586-
let code_offset = builder.push_page_aligned(
587-
self.total_page_table_size,
588-
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
589-
PageTables,
590-
);
591-
592-
if code_offset != self.guest_code_offset {
593-
return Err(new_error!(
594-
"Code offset does not match expected code offset expected: {}, actual: {}",
595-
self.guest_code_offset,
596-
code_offset
597-
));
591+
cfg_if::cfg_if! {
592+
if #[cfg(feature = "init-paging")] {
593+
// PML4, PDPT, PD
594+
let code_offset = builder.push_page_aligned(
595+
self.total_page_table_size,
596+
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
597+
PageTables,
598+
);
599+
600+
if code_offset != self.guest_code_offset {
601+
return Err(new_error!(
602+
"Code offset does not match expected code offset expected: {}, actual: {}",
603+
self.guest_code_offset,
604+
code_offset
605+
));
606+
}
607+
}
598608
}
599609

600610
// code

src/hyperlight_host/src/mem/memory_region.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use mshv_bindings::{hv_x64_memory_intercept_message, mshv_user_mem_region};
4343
#[cfg(target_os = "windows")]
4444
use windows::Win32::System::Hypervisor::{self, WHV_MEMORY_ACCESS_TYPE};
4545

46+
#[cfg(feature = "init-paging")]
4647
use super::mgr::{PAGE_NX, PAGE_PRESENT, PAGE_RW, PAGE_USER};
4748

4849
pub(crate) const DEFAULT_GUEST_BLOB_MEM_FLAGS: MemoryRegionFlags = MemoryRegionFlags::READ;
@@ -65,6 +66,7 @@ bitflags! {
6566
}
6667

6768
impl MemoryRegionFlags {
69+
#[cfg(feature = "init-paging")]
6870
pub(crate) fn translate_flags(&self) -> u64 {
6971
let mut page_flags = 0;
7072

0 commit comments

Comments
 (0)