Enable MPX

This commit is contained in:
Tate, Hongliang Tian 2018-12-29 17:11:37 +08:00
parent 9389b702ba
commit e5d3ab3cf9
6 changed files with 317 additions and 13 deletions

@ -21,7 +21,6 @@ extern crate lazy_static;
use std::ffi::CStr; // a borrowed C string use std::ffi::CStr; // a borrowed C string
use std::backtrace::{self, PrintFormat}; use std::backtrace::{self, PrintFormat};
use std::panic; use std::panic;
use sgx_types::*; use sgx_types::*;
use sgx_trts::libc; use sgx_trts::libc;
@ -32,27 +31,28 @@ mod fs;
mod process; mod process;
mod syscall; mod syscall;
mod vm; mod vm;
mod util;
use prelude::*;
/// Export system calls /// Export system calls
pub use syscall::*; pub use syscall::*;
// TODO: return meaningful exit code
#[no_mangle] #[no_mangle]
pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 {
let path_str = unsafe { let path_str = unsafe {
CStr::from_ptr(path_buf).to_string_lossy().into_owned() CStr::from_ptr(path_buf).to_string_lossy().into_owned()
}; };
println!("LibOS boots: {}", path_str);
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(||{
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
let argv = std::vec::Vec::new(); match do_boot(&path_str) {
let envp = std::vec::Vec::new(); Ok(()) => 0,
process::do_spawn(&path_str, &argv, &envp); Err(err) => err.errno.as_retval() /* Normal error */,
}
}) })
}).ok(); }).unwrap_or(-1 /* Fatal error */)
0
} }
#[no_mangle] #[no_mangle]
@ -60,10 +60,28 @@ pub extern "C" fn libos_run() -> i32 {
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(||{
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
let _ = process::run_task(); match do_run() {
Ok(()) => 0,
Err(err) => err.errno.as_retval() /* Normal error */,
}
}) })
}).ok(); }).unwrap_or(-1 /* Fatal error */)
0
} }
// 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(())
}

@ -0,0 +1,5 @@
use prelude::*;
pub use self::mpx_util::{*};
mod mpx_util;

@ -0,0 +1,100 @@
#include "mpx_util.h"
#include <string.h>
#include <stdint.h>
/*
* 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;
}

@ -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<i>*/
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<i>*/
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<i> */
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__ */

@ -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);
}

@ -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