diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 4fc8b1d54cfc..538109eceae7 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -293,15 +293,9 @@ fn emulate_foreign_item( // is called if a `HashMap` is created the regular way (e.g. HashMap). match this.read_scalar(args[0])?.to_usize(this)? { id if id == sys_getrandom => { - let ptr = this.read_scalar(args[1])?.not_undef()?; - let len = this.read_scalar(args[2])?.to_usize(this)?; - - // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, - // neither of which have any effect on our current PRNG - let _flags = this.read_scalar(args[3])?.to_i32()?; - - this.gen_random(ptr, len as usize)?; - this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?; + // The first argument is the syscall id, + // so skip over it. + linux_getrandom(this, &args[1..], dest)?; } id => { throw_unsup_format!("miri does not support syscall ID {}", id) @@ -309,6 +303,10 @@ fn emulate_foreign_item( } } + "getrandom" => { + linux_getrandom(this, args, dest)?; + } + "dlsym" => { let _handle = this.read_scalar(args[0])?; let symbol = this.read_scalar(args[1])?.not_undef()?; @@ -969,3 +967,21 @@ fn eval_path_scalar(&mut self, path: &[&str]) -> InterpResult<'tcx, Option( + this: &mut MiriEvalContext<'_, 'tcx>, + args: &[OpTy<'tcx, Tag>], + dest: PlaceTy<'tcx, Tag>, +) -> InterpResult<'tcx> { + let ptr = this.read_scalar(args[0])?.not_undef()?; + let len = this.read_scalar(args[1])?.to_usize(this)?; + + // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, + // neither of which have any effect on our current PRNG. + let _flags = this.read_scalar(args[2])?.to_i32()?; + + this.gen_random(ptr, len as usize)?; + this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?; + Ok(()) +} diff --git a/tests/run-pass/linux-getrandom.rs b/tests/run-pass/linux-getrandom.rs new file mode 100644 index 000000000000..f582a282c59b --- /dev/null +++ b/tests/run-pass/linux-getrandom.rs @@ -0,0 +1,17 @@ +// Unfortunately, compiletest_rs does not support 'only-linux', +// so we need to ignore Windows and macOS instead. +// ignore-macos: Uses Linux-only APIs +// ignore-windows: Uses Linux-only APIs +#![feature(rustc_private)] +extern crate libc; + +fn main() { + let mut buf = [0u8; 5]; + unsafe { + assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0); + assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5); + + assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0); + assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5); + } +}