Skip to content

Commit

Permalink
Merge #566 from mzohreva/mz/sgx-image-base
Browse files Browse the repository at this point in the history
Adjust frame IP in SGX relative to image base
  • Loading branch information
workingjubilee authored Oct 6, 2023
2 parents 11e0a4b + 43d7859 commit 036d490
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 11 deletions.
13 changes: 12 additions & 1 deletion src/backtrace/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@ impl Frame {
Frame::Raw(ctx) => ctx,
Frame::Cloned { ip, .. } => return ip,
};
unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void }
#[allow(unused_mut)]
let mut ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void };

// To reduce TCB size in SGX enclaves, we do not want to implement
// symbol resolution functionality. Rather, we can print the offset of
// the address here, which could be later mapped to correct function.
#[cfg(all(target_env = "sgx", target_vendor = "fortanix"))]
{
let image_base = super::get_image_base();
ip = usize::wrapping_sub(ip as usize, image_base as _) as _;
}
ip
}

pub fn sp(&self) -> *mut c_void {
Expand Down
33 changes: 33 additions & 0 deletions src/backtrace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,39 @@ impl fmt::Debug for Frame {
}
}

#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
mod sgx_no_std_image_base {
use core::ffi::c_void;
use core::sync::atomic::{AtomicUsize, Ordering::SeqCst};

static IMAGE_BASE: AtomicUsize = AtomicUsize::new(0);

/// Set the image base address. This is only available for Fortanix SGX
/// target when the `std` feature is not enabled. This can be used in the
/// standard library to set the correct base address.
#[doc(hidden)]
pub fn set_image_base(base_addr: *mut c_void) {
IMAGE_BASE.store(base_addr as _, SeqCst);
}

pub(crate) fn get_image_base() -> *mut c_void {
IMAGE_BASE.load(SeqCst) as _
}
}

#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
pub use self::sgx_no_std_image_base::set_image_base;

#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
#[deny(unused)]
pub(crate) use self::sgx_no_std_image_base::get_image_base;

#[cfg(all(target_env = "sgx", target_vendor = "fortanix", feature = "std"))]
#[deny(unused)]
pub(crate) fn get_image_base() -> *mut c_void {
std::os::fortanix_sgx::mem::image_base() as _
}

cfg_if::cfg_if! {
// This needs to come first, to ensure that
// Miri takes priority over the host platform
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ cfg_if::cfg_if! {
}
}

cfg_if::cfg_if! {
if #[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))] {
pub use self::backtrace::set_image_base;
}
}

#[allow(dead_code)]
struct Bomb {
enabled: bool,
Expand Down
11 changes: 1 addition & 10 deletions src/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ impl BacktraceFrameFmt<'_, '_, '_> {
#[allow(unused_mut)]
fn print_raw_generic(
&mut self,
mut frame_ip: *mut c_void,
frame_ip: *mut c_void,
symbol_name: Option<SymbolName<'_>>,
filename: Option<BytesOrWideString<'_>>,
lineno: Option<u32>,
Expand All @@ -233,15 +233,6 @@ impl BacktraceFrameFmt<'_, '_, '_> {
}
}

// To reduce TCB size in Sgx enclave, we do not want to implement symbol
// resolution functionality. Rather, we can print the offset of the
// address here, which could be later mapped to correct function.
#[cfg(all(feature = "std", target_env = "sgx", target_vendor = "fortanix"))]
{
let image_base = std::os::fortanix_sgx::mem::image_base();
frame_ip = usize::wrapping_sub(frame_ip as usize, image_base as _) as _;
}

// Print the index of the frame as well as the optional instruction
// pointer of the frame. If we're beyond the first symbol of this frame
// though we just print appropriate whitespace.
Expand Down
56 changes: 56 additions & 0 deletions tests/sgx-image-base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#![cfg(all(target_env = "sgx", target_vendor = "fortanix"))]
#![feature(sgx_platform)]

#[cfg(feature = "std")]
#[test]
fn sgx_image_base_with_std() {
use backtrace::trace;

let image_base = std::os::fortanix_sgx::mem::image_base();

let mut frame_ips = Vec::new();
trace(|frame| {
frame_ips.push(frame.ip());
true
});

assert!(frame_ips.len() > 0);
for ip in frame_ips {
let ip: u64 = ip as _;
assert!(ip < image_base);
}
}

#[cfg(not(feature = "std"))]
#[test]
fn sgx_image_base_no_std() {
use backtrace::trace_unsynchronized;

fn guess_image_base() -> u64 {
let mut top_frame_ip = None;
unsafe {
trace_unsynchronized(|frame| {
top_frame_ip = Some(frame.ip());
false
});
}
top_frame_ip.unwrap() as u64 & 0xFFFFFF000000
}

let image_base = guess_image_base();
backtrace::set_image_base(image_base as _);

let mut frame_ips = Vec::new();
unsafe {
trace_unsynchronized(|frame| {
frame_ips.push(frame.ip());
true
});
}

assert!(frame_ips.len() > 0);
for ip in frame_ips {
let ip: u64 = ip as _;
assert!(ip < image_base);
}
}

0 comments on commit 036d490

Please sign in to comment.