1use linux_api::errno::Errno;
2use log::*;
3use rand::RngCore;
4use shadow_shim_helper_rs::syscall_types::ForeignPtr;
56use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
7use crate::host::syscall::types::ForeignArrayPtr;
89impl SyscallHandler {
10log_syscall!(
11 getrandom,
12/* rv */ isize,
13/* buf */ *const std::ffi::c_void,
14/* count */ usize,
15/* flags */ std::ffi::c_uint,
16 );
17pub fn getrandom(
18 ctx: &mut SyscallContext,
19 buf_ptr: ForeignPtr<u8>,
20 count: usize,
21 _flags: std::ffi::c_uint,
22 ) -> Result<isize, Errno> {
23// We ignore the flags arg, because we use the same random source for both
24 // random and urandom, and it never blocks anyway.
2526trace!("Trying to read {count} random bytes.");
2728// Get a native-process mem buffer where we can copy the random bytes.
29let dst_ptr = ForeignArrayPtr::new(buf_ptr, count);
30let mut memory = ctx.objs.process.memory_borrow_mut();
31let mut mem_ref = match memory.memory_ref_mut_uninit(dst_ptr) {
32Ok(m) => m,
33Err(e) => {
34warn!("Failed to get memory ref: {e:?}");
35return Err(Errno::EFAULT);
36 }
37 };
3839// Get random bytes using host rng to maintain determinism.
40let mut rng = ctx.objs.host.random_mut();
41 rng.fill_bytes(&mut mem_ref);
4243// We must flush the memory reference to write it back.
44match mem_ref.flush() {
45Ok(()) => Ok(isize::try_from(count).unwrap()),
46Err(e) => {
47warn!("Failed to flush writes: {e:?}");
48Err(Errno::EFAULT)
49 }
50 }
51 }
52}