From aaf5c5e742e72da91721e29276a27e5f5c32a377 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 May 2024 14:19:14 +0200 Subject: [PATCH] move randomness tests into a single file and share the getrandom implementation across unices --- src/tools/miri/ci/ci.sh | 8 ++-- .../miri/src/shims/unix/foreign_items.rs | 20 ++++++++- .../src/shims/unix/freebsd/foreign_items.rs | 28 ++++--------- .../src/shims/unix/linux/foreign_items.rs | 7 +--- .../tests/pass-dep/shims/libc-getentropy.rs | 13 ------ .../shims/libc-getrandom-without-isolation.rs | 41 ------------------- .../{libc-getrandom.rs => libc-random.rs} | 26 ++++++++++-- 7 files changed, 55 insertions(+), 88 deletions(-) delete mode 100644 src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs delete mode 100644 src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs rename src/tools/miri/tests/pass-dep/shims/{libc-getrandom.rs => libc-random.rs} (61%) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 6881f3695d7..713c97830a5 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -143,12 +143,12 @@ case $HOST_TARGET in # Partially supported targets (tier 2) VERY_BASIC="integer vec string btreemap" # common things we test on all of them (if they have std), requires no target-specific shims BASIC="$VERY_BASIC hello hashmap alloc align" # ensures we have the shims for stdout and basic data structures - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-getentropy libc-getrandom libc-misc fs env num_cpus - MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-getentropy libc-getrandom libc-misc fs env num_cpus - MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal $VERY_BASIC hello panic/panic - MIRI_TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $VERY_BASIC hello panic/panic concurrency/simple pthread-sync libc-misc + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-misc libc-random libc-time fs env num_cpus + MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-misc libc-random libc-time fs env num_cpus + MIRI_TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $VERY_BASIC hello panic/panic concurrency/simple pthread-sync libc-misc libc-random # TODO fix solaris stack guard # MIRI_TEST_TARGET=x86_64-pc-solaris run_tests_minimal $VERY_BASIC hello panic/panic pthread-sync + MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal $VERY_BASIC hello panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm MIRI_TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 45793602b21..595cf64a4e4 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -23,7 +23,7 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { // well allow it in `dlsym`. "signal" => true, // needed at least on macOS to avoid file-based fallback in getrandom - "getentropy" => true, + "getentropy" | "getrandom" => true, // Give specific OSes a chance to allow their symbols. _ => match target_os { @@ -632,6 +632,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_i32(0), dest)?; } } + "getrandom" => { + // This function is non-standard but exists with the same signature and behavior on + // Linux, FreeBSD and Solaris/Illumos. + if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris") { + throw_unsup_format!( + "`getentropy` is not supported on {}", + this.tcx.sess.target.os + ); + } + let [ptr, len, flags] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let len = this.read_target_usize(len)?; + let _flags = this.read_scalar(flags)?.to_i32()?; + // We ignore the flags, just always use the same PRNG / host RNG. + this.gen_random(ptr, len)?; + this.write_scalar(Scalar::from_target_usize(len, this), dest)?; + } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 0d5d5cb3d9a..e70cd35dda6 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -20,11 +20,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading - "pthread_attr_get_np" if this.frame_in_std() => { - let [_thread, _attr] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_null(dest)?; - } "pthread_set_name_np" => { let [thread, name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -75,27 +70,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Miscellaneous - "getrandom" => { - let [ptr, len, flags] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let ptr = this.read_pointer(ptr)?; - let len = this.read_target_usize(len)?; - let _flags = this.read_scalar(flags)?.to_i32()?; - // flags on freebsd does not really matter - // in practice, GRND_RANDOM does not particularly draw from /dev/random - // since it is the same as to /dev/urandom. - // GRND_INSECURE is only an alias of GRND_NONBLOCK, which - // does not affect the RNG. - // https://man.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2&n=1 - this.gen_random(ptr, len)?; - this.write_scalar(Scalar::from_target_usize(len, this), dest)?; - } "__error" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } + // Incomplete shims that we "stub out" just to get pre-main initialization code to work. + // These shims are enabled only when the caller is in the standard library. + "pthread_attr_get_np" if this.frame_in_std() => { + let [_thread, _attr] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + this.write_null(dest)?; + } + _ => return Ok(EmulateItemResult::NotSupported), } Ok(EmulateItemResult::NeedsJumping) diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 43b5db9e32d..ecf82f26a55 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -11,7 +11,7 @@ use shims::unix::linux::mem::EvalContextExt as _; use shims::unix::linux::sync::futex; pub fn is_dyn_sym(name: &str) -> bool { - matches!(name, "getrandom" | "statx") + matches!(name, "statx") } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -140,11 +140,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Miscellaneous - "getrandom" => { - let [ptr, len, flags] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - getrandom(this, ptr, len, flags, dest)?; - } "mmap64" => { let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs deleted file mode 100644 index 06109397c2b..00000000000 --- a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ignore-target-windows: no libc - -use libc::getentropy; - -fn main() { - let mut buf1 = [0u8; 256]; - let mut buf2 = [0u8; 257]; - unsafe { - assert_eq!(getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0); - assert_eq!(getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1); - assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO); - } -} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs deleted file mode 100644 index 349b447569a..00000000000 --- a/src/tools/miri/tests/pass-dep/shims/libc-getrandom-without-isolation.rs +++ /dev/null @@ -1,41 +0,0 @@ -//@only-target-linux -//@compile-flags: -Zmiri-disable-isolation - -use std::ptr; - -fn main() { - let mut buf = [0u8; 5]; - unsafe { - assert_eq!( - libc::syscall( - libc::SYS_getrandom, - ptr::null_mut::(), - 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(ptr::null_mut::(), 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, - ); - } -} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs b/src/tools/miri/tests/pass-dep/shims/libc-random.rs similarity index 61% rename from src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs rename to src/tools/miri/tests/pass-dep/shims/libc-random.rs index 9c670cbd507..71e33522634 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-random.rs @@ -1,9 +1,29 @@ //@ignore-target-windows: no libc -//@ignore-target-apple: no getrandom - -use std::ptr; +//@revisions: isolation no_isolation +//@[no_isolation]compile-flags: -Zmiri-disable-isolation fn main() { + test_getentropy(); + #[cfg(not(target_os = "macos"))] + test_getrandom(); +} + +fn test_getentropy() { + use libc::getentropy; + + let mut buf1 = [0u8; 256]; + let mut buf2 = [0u8; 257]; + unsafe { + assert_eq!(getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0); + assert_eq!(getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1); + assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO); + } +} + +#[cfg(not(target_os = "macos"))] +fn test_getrandom() { + use std::ptr; + let mut buf = [0u8; 5]; unsafe { #[cfg(target_os = "linux")]