about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-11-13 18:30:39 +0100
committerRalf Jung <post@ralfj.de>2023-11-13 19:28:48 +0100
commitedb4c0aece550d652503f440388a45ea99fe0f94 (patch)
treed8f3716bdf05e708b4cd2640e7eba5517ccbbfd0 /src
parent6e907fa6ec15bd51ff4de34e4e36edd655abfc26 (diff)
downloadrust-edb4c0aece550d652503f440388a45ea99fe0f94.tar.gz
rust-edb4c0aece550d652503f440388a45ea99fe0f94.zip
share getentropy shim across various unixes
Diffstat (limited to 'src')
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs33
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs17
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs16
-rw-r--r--src/tools/miri/tests/pass-dep/getrandom.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs15
5 files changed, 48 insertions, 36 deletions
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index c013d275029..f993afa67ad 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -27,6 +27,8 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool {
         // `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as
         // well allow it in `dlsym`.
         "signal" => true,
+        // needed at least on macOS to avoid file-based fallback in getrandom
+        "getentropy" => true,
         // Give specific OSes a chance to allow their symbols.
         _ =>
             match target_os {
@@ -525,6 +527,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.getpid()?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
+            "getentropy" => {
+                // This function is non-standard but exists with the same signature and behavior on
+                // Linux, macOS, and FreeBSD.
+                if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd") {
+                    throw_unsup_format!(
+                        "`getentropy` is not supported on {}",
+                        this.tcx.sess.target.os
+                    );
+                }
+
+                let [buf, bufsize] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let buf = this.read_pointer(buf)?;
+                let bufsize = this.read_target_usize(bufsize)?;
+
+                // getentropy sets errno to EIO when the buffer size exceeds 256 bytes.
+                // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
+                // Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html
+                // macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html
+                if bufsize > 256 {
+                    let err = this.eval_libc("EIO");
+                    this.set_last_error(err)?;
+                    this.write_scalar(Scalar::from_i32(-1), dest)?
+                } else {
+                    this.gen_random(buf, bufsize)?;
+                    this.write_scalar(Scalar::from_i32(0), 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.
@@ -594,7 +624,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_int(super::UID, dest)?;
             }
 
-            "getpwuid_r" if this.frame_in_std() => {
+            "getpwuid_r"
+            if this.frame_in_std() => {
                 let [uid, pwd, buf, buflen, result] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.check_no_isolation("`getpwuid_r`")?;
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 f81710a41a6..96e322c4cf5 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -47,23 +47,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.read_scalar(len)?,
                 )?;
             }
-            "getentropy" => {
-                let [buf, bufsize] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let buf = this.read_pointer(buf)?;
-                let bufsize = this.read_target_usize(bufsize)?;
-
-                // getentropy sets errno to EIO when the buffer size exceeds 256 bytes.
-                // https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
-                if bufsize > 256 {
-                    let err = this.eval_libc("EIO");
-                    this.set_last_error(err)?;
-                    this.write_scalar(Scalar::from_i32(-1), dest)?
-                } else {
-                    this.gen_random(buf, bufsize)?;
-                    this.write_scalar(Scalar::from_i32(0), dest)?;
-                }
-            }
 
             // errno
             "__error" => {
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 5881a3f46f2..e8f35e7ba57 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -6,8 +6,8 @@ use shims::foreign_items::EmulateForeignItemResult;
 use shims::unix::fs::EvalContextExt as _;
 use shims::unix::thread::EvalContextExt as _;
 
-pub fn is_dyn_sym(name: &str) -> bool {
-    matches!(name, "getentropy")
+pub fn is_dyn_sym(_name: &str) -> bool {
+    false
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -113,18 +113,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(result, dest)?;
             }
 
-            // Random generation related shims
-            "getentropy" => {
-                let [buf, bufsize] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let buf = this.read_pointer(buf)?;
-                let bufsize = this.read_target_usize(bufsize)?;
-
-                this.gen_random(buf, bufsize)?;
-
-                this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS
-            }
-
             // Access to command-line arguments
             "_NSGetArgc" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
diff --git a/src/tools/miri/tests/pass-dep/getrandom.rs b/src/tools/miri/tests/pass-dep/getrandom.rs
index 60d6dd31e79..c0d9296a9a6 100644
--- a/src/tools/miri/tests/pass-dep/getrandom.rs
+++ b/src/tools/miri/tests/pass-dep/getrandom.rs
@@ -1,7 +1,8 @@
 // mac-os `getrandom_01` does some pointer shenanigans
 //@compile-flags: -Zmiri-permissive-provenance
 
-/// Test direct calls of getrandom 0.1 and 0.2
+/// Test direct calls of getrandom 0.1 and 0.2.
+/// Make sure they work even with isolation enabled (i.e., we do not hit a file-based fallback path).
 fn main() {
     let mut data = vec![0; 16];
     getrandom_01::getrandom(&mut data).unwrap();
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs
index 468727f70e0..4b863f68516 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs
@@ -1,11 +1,20 @@
-//@only-target-freebsd
+//@ignore-target-windows: no libc
+
+// on macOS this is not in the `libc` crate.
+#[cfg(target_os = "macos")]
+extern "C" {
+    fn getentropy(bytes: *mut libc::c_void, count: libc::size_t) -> libc::c_int;
+}
+
+#[cfg(not(target_os = "macos"))]
+use libc::getentropy;
 
 fn main() {
     let mut buf1 = [0u8; 256];
     let mut buf2 = [0u8; 257];
     unsafe {
-        assert_eq!(libc::getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0);
-        assert_eq!(libc::getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1);
+        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);
     }
 }