Add getrandom syscall
This commit is contained in:
parent
85d6977118
commit
d24f89fd9c
@ -1,12 +1,12 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::random;
|
use crate::misc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DevRandom;
|
pub struct DevRandom;
|
||||||
|
|
||||||
impl INode for DevRandom {
|
impl INode for DevRandom {
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result<usize> {
|
fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result<usize> {
|
||||||
random::get_random(buf).map_err(|_| FsError::Again)?;
|
misc::get_random(buf).map_err(|_| FsError::Again)?;
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::random;
|
use crate::misc;
|
||||||
use rcore_fs_sefs::dev::{SefsUuid, UuidProvider};
|
use rcore_fs_sefs::dev::{SefsUuid, UuidProvider};
|
||||||
|
|
||||||
pub struct SgxUuidProvider;
|
pub struct SgxUuidProvider;
|
||||||
@ -7,7 +7,7 @@ pub struct SgxUuidProvider;
|
|||||||
impl UuidProvider for SgxUuidProvider {
|
impl UuidProvider for SgxUuidProvider {
|
||||||
fn generate_uuid(&self) -> SefsUuid {
|
fn generate_uuid(&self) -> SefsUuid {
|
||||||
let mut uuid: [u8; 16] = [0u8; 16];
|
let mut uuid: [u8; 16] = [0u8; 16];
|
||||||
random::get_random(&mut uuid).expect("failed to get random number");
|
misc::get_random(&mut uuid).expect("failed to get random number");
|
||||||
SefsUuid(uuid)
|
SefsUuid(uuid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ use super::*;
|
|||||||
|
|
||||||
#[cfg(feature = "cov")]
|
#[cfg(feature = "cov")]
|
||||||
mod coverage;
|
mod coverage;
|
||||||
|
mod random;
|
||||||
mod rlimit;
|
mod rlimit;
|
||||||
mod sysinfo;
|
mod sysinfo;
|
||||||
mod uname;
|
mod uname;
|
||||||
|
|
||||||
|
pub use self::random::{do_getrandom, get_random, RandFlags};
|
||||||
pub use self::rlimit::{do_prlimit, resource_t, rlimit_t, ResourceLimits};
|
pub use self::rlimit::{do_prlimit, resource_t, rlimit_t, ResourceLimits};
|
||||||
pub use self::sysinfo::{do_sysinfo, sysinfo_t};
|
pub use self::sysinfo::{do_sysinfo, sysinfo_t};
|
||||||
pub use self::uname::{do_uname, utsname_t};
|
pub use self::uname::{do_uname, utsname_t};
|
||||||
|
@ -1,20 +1,45 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use sgx_types::sgx_status_t;
|
pub fn do_getrandom(rand_buf: &mut [u8], flags: RandFlags) -> Result<()> {
|
||||||
|
debug!("getrandom: flags: {:?}", flags);
|
||||||
|
if flags.contains(RandFlags::GRND_NONBLOCK) {
|
||||||
|
get_random(rand_buf)
|
||||||
|
} else {
|
||||||
|
get_random_blocking(rand_buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MAX_RETRIES: u32 = 50;
|
bitflags! {
|
||||||
|
pub struct RandFlags: u32 {
|
||||||
|
/// Don't block and return EAGAIN instead
|
||||||
|
const GRND_NONBLOCK = 0x0001;
|
||||||
|
/// No effect
|
||||||
|
const GRND_RANDOM = 0x0002;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_random_blocking(rand: &mut [u8]) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
if get_random(rand).is_ok() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_random(rand: &mut [u8]) -> Result<()> {
|
pub fn get_random(rand: &mut [u8]) -> Result<()> {
|
||||||
|
use sgx_types::sgx_status_t;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t;
|
fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t;
|
||||||
}
|
}
|
||||||
|
const MAX_TIMES: u32 = 50;
|
||||||
|
|
||||||
if rand.is_empty() {
|
if rand.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// sgx_read_rand() may fail because of HW failure of RDRAND instruction,
|
// sgx_read_rand() may fail because of HW failure of RDRAND instruction,
|
||||||
// add retries to get the random number.
|
// add retries to get the random number.
|
||||||
for _ in 0..MAX_RETRIES {
|
for _ in 0..MAX_TIMES {
|
||||||
let status = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) };
|
let status = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) };
|
||||||
match status {
|
match status {
|
||||||
sgx_status_t::SGX_SUCCESS => {
|
sgx_status_t::SGX_SUCCESS => {
|
@ -3,8 +3,8 @@ use std::os::raw::c_char;
|
|||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
use super::aux_vec::{AuxKey, AuxVec};
|
use super::aux_vec::{AuxKey, AuxVec};
|
||||||
|
use crate::misc;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::random;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The initial stack of a process looks like below:
|
* The initial stack of a process looks like below:
|
||||||
@ -152,7 +152,7 @@ impl StackBuf {
|
|||||||
fn generate_random_on_stack(stack: &StackBuf) -> Result<*const u8> {
|
fn generate_random_on_stack(stack: &StackBuf) -> Result<*const u8> {
|
||||||
let rand_val = {
|
let rand_val = {
|
||||||
let mut rand: [u8; 16] = [0; 16];
|
let mut rand: [u8; 16] = [0; 16];
|
||||||
random::get_random(&mut rand)?;
|
misc::get_random(&mut rand)?;
|
||||||
rand
|
rand
|
||||||
};
|
};
|
||||||
stack.put_slice(&rand_val)
|
stack.put_slice(&rand_val)
|
||||||
|
@ -34,7 +34,7 @@ use crate::fs::{
|
|||||||
Stat, Statfs,
|
Stat, Statfs,
|
||||||
};
|
};
|
||||||
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
||||||
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
|
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t, RandFlags};
|
||||||
use crate::net::{
|
use crate::net::{
|
||||||
do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl,
|
do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl,
|
||||||
do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen,
|
do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen,
|
||||||
@ -406,7 +406,7 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(SchedGetattr = 315) => handle_unsupported(),
|
(SchedGetattr = 315) => handle_unsupported(),
|
||||||
(Renameat2 = 316) => handle_unsupported(),
|
(Renameat2 = 316) => handle_unsupported(),
|
||||||
(Seccomp = 317) => handle_unsupported(),
|
(Seccomp = 317) => handle_unsupported(),
|
||||||
(Getrandom = 318) => handle_unsupported(),
|
(Getrandom = 318) => do_getrandom(buf: *mut u8, len: size_t, flags: u32),
|
||||||
(MemfdCreate = 319) => handle_unsupported(),
|
(MemfdCreate = 319) => handle_unsupported(),
|
||||||
(KexecFileLoad = 320) => handle_unsupported(),
|
(KexecFileLoad = 320) => handle_unsupported(),
|
||||||
(Bpf = 321) => handle_unsupported(),
|
(Bpf = 321) => handle_unsupported(),
|
||||||
@ -827,6 +827,20 @@ fn do_sysinfo(info: *mut sysinfo_t) -> Result<isize> {
|
|||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_getrandom(buf: *mut u8, len: size_t, flags: u32) -> Result<isize> {
|
||||||
|
check_mut_array(buf, len)?;
|
||||||
|
let checked_len = if len > u32::MAX as usize {
|
||||||
|
u32::MAX as usize
|
||||||
|
} else {
|
||||||
|
len
|
||||||
|
};
|
||||||
|
let rand_buf = unsafe { std::slice::from_raw_parts_mut(buf, checked_len) };
|
||||||
|
let flags = RandFlags::from_bits(flags).ok_or_else(|| errno!(EINVAL, "invalid flags"))?;
|
||||||
|
|
||||||
|
misc::do_getrandom(rand_buf, flags)?;
|
||||||
|
Ok(checked_len as isize)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: handle tz: timezone_t
|
// TODO: handle tz: timezone_t
|
||||||
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize> {
|
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize> {
|
||||||
check_mut_ptr(tv_u)?;
|
check_mut_ptr(tv_u)?;
|
||||||
|
@ -4,7 +4,6 @@ pub mod dirty;
|
|||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod mem_util;
|
pub mod mem_util;
|
||||||
pub mod mpx_util;
|
pub mod mpx_util;
|
||||||
pub mod random;
|
|
||||||
pub mod resolv_conf_util;
|
pub mod resolv_conf_util;
|
||||||
pub mod sgx;
|
pub mod sgx;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
|
@ -52,10 +52,10 @@ impl<'a, 'b> ProcessVMBuilder<'a, 'b> {
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::util::random;
|
use crate::misc;
|
||||||
trace!("entrophy size = {}", range);
|
trace!("entrophy size = {}", range);
|
||||||
let mut random_buf: [u8; 8] = [0u8; 8]; // same length as usize
|
let mut random_buf: [u8; 8] = [0u8; 8]; // same length as usize
|
||||||
random::get_random(&mut random_buf).expect("failed to get random number");
|
misc::get_random(&mut random_buf).expect("failed to get random number");
|
||||||
let random_num: usize = u64::from_le_bytes(random_buf) as usize;
|
let random_num: usize = u64::from_le_bytes(random_buf) as usize;
|
||||||
random_num % range
|
random_num % range
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe
|
|||||||
truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info resolv_conf rlimit \
|
truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info resolv_conf rlimit \
|
||||||
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
||||||
ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
|
ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
|
||||||
spawn_attribute exec statfs umask pgrp vfork
|
spawn_attribute exec statfs random umask pgrp vfork
|
||||||
# Benchmarks: need to be compiled and run by bench-% target
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||||
|
|
||||||
|
5
test/random/Makefile
Normal file
5
test/random/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
43
test/random/main.c
Normal file
43
test/random/main.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <sys/random.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for getrandom
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
int test_getrandom() {
|
||||||
|
unsigned long rand;
|
||||||
|
|
||||||
|
ssize_t len = getrandom(&rand, sizeof(unsigned long), GRND_NONBLOCK);
|
||||||
|
if (len < 0 || len != sizeof(unsigned long)) {
|
||||||
|
THROW_ERROR("failed to call getrandom");
|
||||||
|
}
|
||||||
|
printf("generate random value: %lu\n", rand);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_getrandom_blocking() {
|
||||||
|
int rand;
|
||||||
|
|
||||||
|
ssize_t len = getrandom(&rand, sizeof(int), 0);
|
||||||
|
if (len < 0 || len != sizeof(int)) {
|
||||||
|
THROW_ERROR("failed to call getrandom");
|
||||||
|
}
|
||||||
|
printf("generate random value: %d\n", rand);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_getrandom),
|
||||||
|
TEST_CASE(test_getrandom_blocking),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user