Skip to content

Commit ffec78f

Browse files
cshungCopilot
andcommitted
feat: enable ASLR for PIE guest binaries
Add pick_aslr_address() that selects a random page-aligned virtual base for PIE code regions within 47-bit canonical user space. For PIE guests, Snapshot::new() calls this instead of identity-mapping code at the physical load address, then passes the result to set_code_gva(). Non-PIE binaries continue using their declared ELF base VA. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6f20a05d-6bee-4e2e-b320-12f8d9759bbc Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
1 parent 57cd8d3 commit ffec78f

5 files changed

Lines changed: 40 additions & 6 deletions

File tree

src/hyperlight_host/src/hypervisor/hyperlight_vm/aarch64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::{
1212
#[cfg(hvf)]
1313
use crate::hypervisor::HvfInterruptHandle;
1414
use crate::hypervisor::InterruptHandleImpl;
15-
#[cfg(any(kvm, mshv3))]
15+
#[cfg(target_os = "linux")]
1616
use crate::hypervisor::LinuxInterruptHandle;
1717
#[cfg(gdb)]
1818
use crate::hypervisor::gdb::{DebugCommChannel, DebugMsg, DebugResponse};

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ pub(crate) mod tests {
508508
)?;
509509

510510
// Set up required parameters for initialise
511-
let peb_addr = RawPtr::from(0x1000u64); // Dummy PEB address
512-
let seed = 12345u64; // Random seed
511+
let peb_addr = RawPtr::from(0x230000u64);
512+
let seed = 1234567890u64;
513513
let host_funcs = Arc::new(Mutex::new(FunctionRegistry::default()));
514514
let guest_max_log_level = Some(tracing_core::LevelFilter::ERROR);
515515

src/hyperlight_host/src/mem/layout.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,30 @@ impl SandboxMemoryLayout {
568568
Ok(())
569569
}
570570

571+
/// Pick a random page-aligned virtual address for ASLR.
572+
///
573+
/// The address is chosen within 47-bit canonical user space:
574+
/// lower bound 16 MiB (above identity-mapped layout regions),
575+
/// upper bound accounts for `loaded_size` so the mapping fits.
576+
pub(crate) fn pick_aslr_address(loaded_size: u64) -> Result<u64> {
577+
use rand::RngExt;
578+
let code_size_pages = loaded_size.div_ceil(PAGE_SIZE as u64);
579+
let min_page = 0x1000_u64; // 0x1000 * PAGE_SIZE = 0x1000000 (16 MiB)
580+
let max_page = 0x7_FFFF_FFFF_u64
581+
.checked_sub(code_size_pages)
582+
.ok_or_else(|| {
583+
new_error!(
584+
"PIE code region too large ({} pages) for ASLR randomization",
585+
code_size_pages
586+
)
587+
})?;
588+
let mut rng = rand::rng();
589+
let page_number = rng.random_range(min_page..max_page);
590+
page_number
591+
.checked_mul(PAGE_SIZE as u64)
592+
.ok_or_else(|| new_error!("ASLR page number overflow"))
593+
}
594+
571595
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
572596
pub(crate) fn write_init_data(&self, out: &mut [u8], bytes: &[u8]) -> Result<()> {
573597
out[self.init_data_offset()..self.init_data_offset() + self.init_data_size]

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,9 +2766,12 @@ mod tests {
27662766
/// `read_guest_memory_by_gva`, then assert both views are identical.
27672767
#[cfg(feature = "trace_guest")]
27682768
fn assert_gva_read_matches(sbox: &mut MultiUseSandbox, gva: u64, len: usize) {
2769-
// Guest reads via its own page tables
2769+
// Guest reads via its own page tables.
2770+
// do_map = false: the code region is already mapped (identity-mapped
2771+
// or ASLR-mapped), so we must not remap it with an identity mapping
2772+
// that would use the GVA as a physical address.
27702773
let expected: Vec<u8> = sbox
2771-
.call("ReadMappedBuffer", (gva, len as u64, true))
2774+
.call("ReadMappedBuffer", (gva, len as u64, false))
27722775
.unwrap();
27732776
assert_eq!(expected.len(), len);
27742777

src/hyperlight_host/src/sandbox/snapshot/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,14 @@ impl Snapshot {
326326
let entrypoint_va: u64 = exe_info.entrypoint().into();
327327
let is_pie = exe_info.is_pie();
328328

329-
let code_gva = if is_pie { load_addr } else { base_va };
329+
let code_gva = if is_pie {
330+
SandboxMemoryLayout::pick_aslr_address(exe_info.loaded_size() as u64)?
331+
} else if base_va == load_addr {
332+
// PIE binary at default load address (identity-mapped)
333+
load_addr
334+
} else {
335+
base_va
336+
};
330337
layout.set_code_gva(code_gva)?;
331338
let regions = layout.get_memory_regions()?;
332339

0 commit comments

Comments
 (0)