From e5d3ab3cf9acb26721266fef1e2d02d0fee57905 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Sat, 29 Dec 2018 17:11:37 +0800 Subject: [PATCH] Enable MPX --- src/libos/src/lib.rs | 44 ++++++++---- src/libos/src/util/mod.rs | 5 ++ src/libos/src/util/mpx_util.c | 100 +++++++++++++++++++++++++++ src/libos/src/util/mpx_util.h | 34 +++++++++ src/libos/src/util/mpx_util.rs | 66 ++++++++++++++++++ src/libos/src/util/mpx_util_x86-64.S | 81 ++++++++++++++++++++++ 6 files changed, 317 insertions(+), 13 deletions(-) create mode 100644 src/libos/src/util/mod.rs create mode 100644 src/libos/src/util/mpx_util.c create mode 100644 src/libos/src/util/mpx_util.h create mode 100644 src/libos/src/util/mpx_util.rs create mode 100644 src/libos/src/util/mpx_util_x86-64.S diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index a5e56253..e07540f1 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -21,7 +21,6 @@ extern crate lazy_static; use std::ffi::CStr; // a borrowed C string use std::backtrace::{self, PrintFormat}; use std::panic; - use sgx_types::*; use sgx_trts::libc; @@ -32,27 +31,28 @@ mod fs; mod process; mod syscall; mod vm; +mod util; + +use prelude::*; /// Export system calls pub use syscall::*; +// TODO: return meaningful exit code #[no_mangle] pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { let path_str = unsafe { CStr::from_ptr(path_buf).to_string_lossy().into_owned() }; - println!("LibOS boots: {}", path_str); - let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ - let argv = std::vec::Vec::new(); - let envp = std::vec::Vec::new(); - process::do_spawn(&path_str, &argv, &envp); + match do_boot(&path_str) { + Ok(()) => 0, + Err(err) => err.errno.as_retval() /* Normal error */, + } }) - }).ok(); - - 0 + }).unwrap_or(-1 /* Fatal error */) } #[no_mangle] @@ -60,10 +60,28 @@ pub extern "C" fn libos_run() -> i32 { let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ - let _ = process::run_task(); + match do_run() { + Ok(()) => 0, + Err(err) => err.errno.as_retval() /* Normal error */, + } }) - }).ok(); - - 0 + }).unwrap_or(-1 /* Fatal error */) } + +// TODO: make sure do_boot can only be called once +fn do_boot(path_str: &str) -> Result<(), Error> { + util::mpx_enable()?; + + let argv = std::vec::Vec::new(); + let envp = std::vec::Vec::new(); + process::do_spawn(&path_str, &argv, &envp)?; + + Ok(()) +} + +// TODO: make sure do_run() cannot be called before do_boot() +fn do_run() -> Result<(), Error> { + process::run_task()?; + Ok(()) +} diff --git a/src/libos/src/util/mod.rs b/src/libos/src/util/mod.rs new file mode 100644 index 00000000..35942ab0 --- /dev/null +++ b/src/libos/src/util/mod.rs @@ -0,0 +1,5 @@ +use prelude::*; + +pub use self::mpx_util::{*}; + +mod mpx_util; diff --git a/src/libos/src/util/mpx_util.c b/src/libos/src/util/mpx_util.c new file mode 100644 index 00000000..d31882d4 --- /dev/null +++ b/src/libos/src/util/mpx_util.c @@ -0,0 +1,100 @@ +#include "mpx_util.h" +#include +#include + +/* + * Define data structures for the part of XSAVE area that are relevant + * to enabling MPX + */ + +typedef struct { + uint64_t xstate_bv; + uint64_t __irrelevant[2]; + uint64_t __reserved[5]; +} __attribute__ ((packed)) xsave_header_t; + +typedef struct { + uint64_t __irrelevant[8]; +} __attribute__ ((packed)) bndreg_t ; + +typedef struct { + uint64_t enable: 1; + uint64_t bndpreserve: 1; + uint64_t __reserved: 10; + uint64_t __irrelevant: 52; +} __attribute__ ((packed)) bndcfgu_t; + +typedef struct { + bndcfgu_t bndcfgu; + uint64_t __irrelevant; +} __attribute__((packed)) bndcsr_t; + +typedef struct { + uint8_t __irrelevant0[512]; + xsave_header_t header; + uint8_t __irrelevant1[256]; + uint8_t __irrelevant2[128]; + bndreg_t bndreg; + bndcsr_t bndcsr; +} __attribute__ ((packed, __aligned__(64))) xsave_area_t ; + + +/* + * Restore the state components of CPU specified in rfbm from xsave_area. + * + * rfbm is the requested-feature bitmap, whose bits specifies which state + * components are to restored by this instruction. + */ +static void xrstor(xsave_area_t* xsave_area, uint64_t rfbm) { + uint32_t rfbm_l= rfbm; + uint32_t rfbm_h = rfbm >> 32; + +#define REX_PREFIX "0x48, " +#define XRSTOR64 REX_PREFIX "0x0f,0xae,0x2f " + + __asm__ __volatile__ ( + ".byte " XRSTOR64 "\n\t" + : + : "D" (xsave_area), "m" (*xsave_area), "a" (rfbm), "d" (rfbm) + : "memory"); +} + +/* The state component bitmaps for MPX + * + * The state component 3 (i.e., bit 3) is BNDREG state, which consists of the + * four MPX bound registers BND0-BND3. + * + * The state component 4 (i.e., bit 4) is BNDCSR state, which consists of the + * one MPX configuration register BNDCFGU and one MPX status register + * BNDSTATUS. + * */ +#define MPX_BNDREG_COMPONENT_MASK (0x08UL) +#define MPX_BNDCSR_COMPONENT_MASK (0x10UL) +#define MPX_ALL_COMPONENT_MASK (MPX_BNDCSR_COMPONENT_MASK | \ + MPX_BNDREG_COMPONENT_MASK) + +int __mpx_enable(void) { + xsave_area_t xsave_area; + memset(&xsave_area, 0, sizeof(xsave_area)); + + /* Initialize MPX states + * + * xrestor initializes state component i if rfbm[i] = 1 and + * xsave_area.header.xstate_bv[i] = 0 */ + uint64_t rfbm = MPX_ALL_COMPONENT_MASK; + xrstor(&xsave_area, rfbm); + + /* xrestor updates state component i if rfbm[i] = 1 and + * xsave_area.header.xstate_bv[i] = 1 */ + xsave_area.header.xstate_bv = MPX_BNDCSR_COMPONENT_MASK; + /* Set enable bit to 1 to enable MPX */ + xsave_area.bndcsr.bndcfgu.enable = 1; + /* Set bndpreserve bit to 1 so that BND0-BND3 remain unchanged upon + * control flow transfer instructions (e.g., call, jmp, etc.). */ + xsave_area.bndcsr.bndcfgu.bndpreserve = 1; + /* Set BNDCSR state component so that MPX is enabled. */ + rfbm = MPX_BNDCSR_COMPONENT_MASK; + xrstor(&xsave_area, rfbm); + + return 0; +} diff --git a/src/libos/src/util/mpx_util.h b/src/libos/src/util/mpx_util.h new file mode 100644 index 00000000..5af14ad4 --- /dev/null +++ b/src/libos/src/util/mpx_util.h @@ -0,0 +1,34 @@ +#ifndef __MPX_UTIL__ +#define __MPX_UTIL__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enable the use of MPX bound registers bnd0-bnd3 and bound instructions + * bndmk, bndcl and bndcu. */ +int __mpx_enable(void); + +/* Make a new bound in bnd*/ +void __mpx_bndmk0(unsigned long base, unsigned long size); +void __mpx_bndmk1(unsigned long base, unsigned long size); +void __mpx_bndmk2(unsigned long base, unsigned long size); +void __mpx_bndmk3(unsigned long base, unsigned long size); + +/* Check x against the lower bound of bnd*/ +void __mpx_bndcl0(unsigned long x); +void __mpx_bndcl1(unsigned long x); +void __mpx_bndcl2(unsigned long x); +void __mpx_bndcl3(unsigned long x); + +/* Check x against the upper bound of bnd */ +void __mpx_bndcu0(unsigned long x); +void __mpx_bndcu1(unsigned long x); +void __mpx_bndcu2(unsigned long x); +void __mpx_bndcu3(unsigned long x); + +#ifdef __cplusplus +} +#endif + +#endif /* __MPX_UTIL__ */ diff --git a/src/libos/src/util/mpx_util.rs b/src/libos/src/util/mpx_util.rs new file mode 100644 index 00000000..b0cd25a1 --- /dev/null +++ b/src/libos/src/util/mpx_util.rs @@ -0,0 +1,66 @@ +use super::*; + +pub fn mpx_enable() -> Result<(), Error> { + match unsafe { __mpx_enable () } { + 0 => { Ok(()) } + _ => { errno!(EPERM, "MPX cannot be enabled") } + } +} + +pub enum MpxReg { + BND0, + BND1, + BND2, + BND3, +} + +pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<(), Error> { + /* Check whether the upper bound overflows the max of 64-bit */ + if base.checked_add(size).is_none() { + return errno!(ERANGE, "Upper bound overflows"); + } + + match bndreg { + MpxReg::BND0 => unsafe { __mpx_bndmk0(base, size) }, + MpxReg::BND1 => unsafe { __mpx_bndmk1(base, size) }, + MpxReg::BND2 => unsafe { __mpx_bndmk2(base, size) }, + MpxReg::BND3 => unsafe { __mpx_bndmk3(base, size) }, + } + Ok(()) +} + +pub fn mpx_bndcl(bndreg: MpxReg, addr: usize) { + match bndreg { + MpxReg::BND0 => unsafe { __mpx_bndcl0(addr) }, + MpxReg::BND1 => unsafe { __mpx_bndcl1(addr) }, + MpxReg::BND2 => unsafe { __mpx_bndcl2(addr) }, + MpxReg::BND3 => unsafe { __mpx_bndcl3(addr) }, + } +} + +pub fn mpx_bndcu(bndreg: MpxReg, addr: usize) { + match bndreg { + MpxReg::BND0 => unsafe { __mpx_bndcu0(addr) }, + MpxReg::BND1 => unsafe { __mpx_bndcu1(addr) }, + MpxReg::BND2 => unsafe { __mpx_bndcu2(addr) }, + MpxReg::BND3 => unsafe { __mpx_bndcu3(addr) }, + } +} + + +extern { + // See mpx_util.h + fn __mpx_enable() -> i32; + fn __mpx_bndmk0(base: usize, size: usize); + fn __mpx_bndmk1(base: usize, size: usize); + fn __mpx_bndmk2(base: usize, size: usize); + fn __mpx_bndmk3(base: usize, size: usize); + fn __mpx_bndcl0(x: usize); + fn __mpx_bndcl1(x: usize); + fn __mpx_bndcl2(x: usize); + fn __mpx_bndcl3(x: usize); + fn __mpx_bndcu0(x: usize); + fn __mpx_bndcu1(x: usize); + fn __mpx_bndcu2(x: usize); + fn __mpx_bndcu3(x: usize); +} diff --git a/src/libos/src/util/mpx_util_x86-64.S b/src/libos/src/util/mpx_util_x86-64.S new file mode 100644 index 00000000..bca6bb5f --- /dev/null +++ b/src/libos/src/util/mpx_util_x86-64.S @@ -0,0 +1,81 @@ + .file "mpx_util_x86-64.S" + +/* For bnd0 */ + + .global __mpx_bndmk0 + .type __mpx_bndmk0, @function +__mpx_bndmk0: + bndmk (%rdi, %rsi, 1), %bnd0 + ret + + .global __mpx_bndcl0 + .type __mpx_bndcl0, @function +__mpx_bndcl0: + bndcl %rdi, %bnd0 + ret + + .global __mpx_bndcu0 + .type __mpx_bndcu0, @function +__mpx_bndcu0: + bndcu %rdi, %bnd0 + ret + +/* For bnd1 */ + + .global __mpx_bndmk1 + .type __mpx_bndmk1, @function +__mpx_bndmk1: + bndmk (%rdi, %rsi, 1), %bnd1 + ret + + .global __mpx_bndcl1 + .type __mpx_bndcl1, @function +__mpx_bndcl1: + bndcl %rdi, %bnd1 + ret + + .global __mpx_bndcu1 + .type __mpx_bndcu1, @function +__mpx_bndcu1: + bndcu %rdi, %bnd1 + ret + +/* For bnd2 */ + + .global __mpx_bndmk2 + .type __mpx_bndmk2, @function +__mpx_bndmk2: + bndmk (%rdi, %rsi, 1), %bnd2 + ret + + .global __mpx_bndcl2 + .type __mpx_bndcl2, @function +__mpx_bndcl2: + bndcl %rdi, %bnd2 + ret + + .global __mpx_bndcu2 + .type __mpx_bndcu2, @function +__mpx_bndcu2: + bndcu %rdi, %bnd2 + ret + +/* For bnd3 */ + + .global __mpx_bndmk3 + .type __mpx_bndmk3, @function +__mpx_bndmk3: + bndmk (%rdi, %rsi, 1), %bnd3 + ret + + .global __mpx_bndcl3 + .type __mpx_bndcl3, @function +__mpx_bndcl3: + bndcl %rdi, %bnd3 + ret + + .global __mpx_bndcu3 + .type __mpx_bndcu3, @function +__mpx_bndcu3: + bndcu %rdi, %bnd3 + ret