From 40a52b56bee02487211d180e2dadbd41bf8fd032 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Thu, 10 Dec 2020 14:17:46 +0800 Subject: [PATCH] Initialize a randon number on stack for the stack protector --- src/libos/src/fs/dev_fs/dev_random.rs | 13 ++------- src/libos/src/fs/sefs/sgx_uuid_provider.rs | 11 ++----- src/libos/src/process/do_spawn/init_stack.rs | 14 ++++++++- src/libos/src/process/do_spawn/mod.rs | 4 +-- src/libos/src/util/mod.rs | 1 + src/libos/src/util/random.rs | 30 ++++++++++++++++++++ 6 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 src/libos/src/util/random.rs diff --git a/src/libos/src/fs/dev_fs/dev_random.rs b/src/libos/src/fs/dev_fs/dev_random.rs index 399a455b..4ccb1870 100644 --- a/src/libos/src/fs/dev_fs/dev_random.rs +++ b/src/libos/src/fs/dev_fs/dev_random.rs @@ -1,21 +1,14 @@ use super::*; use crate::net::PollEventFlags; +use crate::util::random; #[derive(Debug)] pub struct DevRandom; -extern "C" { - fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t; -} - impl File for DevRandom { fn read(&self, _buf: &mut [u8]) -> Result { - let (buf, size) = _buf.as_mut().as_mut_ptr_and_len(); - let status = unsafe { sgx_read_rand(buf, size) }; - if status != sgx_status_t::SGX_SUCCESS { - return_errno!(EAGAIN, "failed to get random number from sgx"); - } - Ok(size) + random::get_random(_buf)?; + Ok(_buf.len()) } fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { diff --git a/src/libos/src/fs/sefs/sgx_uuid_provider.rs b/src/libos/src/fs/sefs/sgx_uuid_provider.rs index f5e889b9..34fd0b39 100644 --- a/src/libos/src/fs/sefs/sgx_uuid_provider.rs +++ b/src/libos/src/fs/sefs/sgx_uuid_provider.rs @@ -1,20 +1,13 @@ use super::*; +use crate::util::random; use rcore_fs_sefs::dev::{SefsUuid, UuidProvider}; -use sgx_types::sgx_status_t; - -extern "C" { - fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t; -} pub struct SgxUuidProvider; impl UuidProvider for SgxUuidProvider { fn generate_uuid(&self) -> SefsUuid { let mut uuid: [u8; 16] = [0u8; 16]; - let buf = uuid.as_mut_ptr(); - let size = 16; - let status = unsafe { sgx_read_rand(buf, size) }; - assert!(status == sgx_status_t::SGX_SUCCESS); + random::get_random(&mut uuid).expect("failed to get random number"); SefsUuid(uuid) } } diff --git a/src/libos/src/process/do_spawn/init_stack.rs b/src/libos/src/process/do_spawn/init_stack.rs index ddb095f2..9df45f04 100644 --- a/src/libos/src/process/do_spawn/init_stack.rs +++ b/src/libos/src/process/do_spawn/init_stack.rs @@ -4,6 +4,7 @@ use std::{mem, ptr}; use super::aux_vec::{AuxKey, AuxVec}; use crate::prelude::*; +use crate::util::random; /* * The initial stack of a process looks like below: @@ -53,11 +54,13 @@ pub fn do_init( init_area_size: usize, argv: &[CString], envp: &[CString], - auxtbl: &AuxVec, + auxtbl: &mut AuxVec, ) -> Result { let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? }; let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?; let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?; + let rand_val_ptr = generate_random_on_stack(&stack_buf)?; + auxtbl.set(AuxKey::AT_RANDOM, rand_val_ptr as *const () as u64); adjust_alignment(&stack_buf, auxtbl, &envp_cloned, &argv_cloned)?; dump_auxtbl_on_stack(&stack_buf, auxtbl)?; dump_cstrptrs_on_stack(&stack_buf, &envp_cloned)?; @@ -146,6 +149,15 @@ impl StackBuf { } } +fn generate_random_on_stack(stack: &StackBuf) -> Result<*const u8> { + let rand_val = { + let mut rand: [u8; 16] = [0; 16]; + random::get_random(&mut rand)?; + rand + }; + stack.put_slice(&rand_val) +} + fn clone_cstrings_on_stack<'a, 'b>( stack: &'a StackBuf, cstrings: &'b [CString], diff --git a/src/libos/src/process/do_spawn/mod.rs b/src/libos/src/process/do_spawn/mod.rs index a39f9e2e..8f5744ba 100644 --- a/src/libos/src/process/do_spawn/mod.rs +++ b/src/libos/src/process/do_spawn/mod.rs @@ -130,7 +130,7 @@ fn new_process( let process_ref = current_ref.process().clone(); let vm = init_vm::do_init(&exec_elf_file, &ldso_elf_file)?; - let auxvec = init_auxvec(&vm, &exec_elf_file)?; + let mut auxvec = init_auxvec(&vm, &exec_elf_file)?; // Notify debugger to load the symbols from elf file let ldso_elf_base = vm.get_elf_ranges()[1].start() as u64; @@ -162,7 +162,7 @@ fn new_process( }; let user_stack_base = vm.get_stack_base(); let user_stack_limit = vm.get_stack_limit(); - let user_rsp = init_stack::do_init(user_stack_base, 4096, &argv, envp, &auxvec)?; + let user_rsp = init_stack::do_init(user_stack_base, 4096, &argv, envp, &mut auxvec)?; unsafe { Task::new( ldso_entry, diff --git a/src/libos/src/util/mod.rs b/src/libos/src/util/mod.rs index 92543d44..0ace301e 100644 --- a/src/libos/src/util/mod.rs +++ b/src/libos/src/util/mod.rs @@ -4,5 +4,6 @@ pub mod dirty; pub mod log; pub mod mem_util; pub mod mpx_util; +pub mod random; pub mod sgx; pub mod sync; diff --git a/src/libos/src/util/random.rs b/src/libos/src/util/random.rs new file mode 100644 index 00000000..d450b147 --- /dev/null +++ b/src/libos/src/util/random.rs @@ -0,0 +1,30 @@ +use super::*; + +use sgx_types::sgx_status_t; + +const MAX_RETRIES: u32 = 50; + +pub fn get_random(rand: &mut [u8]) -> Result<()> { + extern "C" { + fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t; + } + + if rand.is_empty() { + return Ok(()); + } + // sgx_read_rand() may fail because of HW failure of RDRAND instruction, + // add retries to get the random number. + for _ in 0..MAX_RETRIES { + let status = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) }; + match status { + sgx_status_t::SGX_SUCCESS => { + return Ok(()); + } + sgx_status_t::SGX_ERROR_INVALID_PARAMETER => { + panic!("invalid argument to get random number from SGX"); + } + _ => {} + } + } + Err(errno!(EAGAIN, "failed to get random number from SGX")) +}