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