Skip to content

Commit

Permalink
share getentropy shim across various unixes
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Nov 13, 2023
1 parent 6722d14 commit cb0d2c3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 32 deletions.
30 changes: 30 additions & 0 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
"getentropy" => true,
// Give specific OSes a chance to allow their symbols.
_ =>
match target_os {
Expand Down Expand Up @@ -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.
Expand Down
17 changes: 0 additions & 17 deletions src/shims/unix/freebsd/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" => {
Expand Down
16 changes: 2 additions & 14 deletions src/shims/unix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {}
Expand Down Expand Up @@ -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)?;
Expand Down
2 changes: 1 addition & 1 deletion tests/pass-dep/shims/libc-getentropy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@only-target-freebsd
//@ignore-target-windows: no libc

Check failure on line 1 in tests/pass-dep/shims/libc-getentropy.rs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x86_64-unknown-linux-gnu)

pass test got exit status: 1

no message

Check failure on line 1 in tests/pass-dep/shims/libc-getentropy.rs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x86_64-unknown-linux-gnu)

test generated output

you likely need to bless the tests with `./miri test --bless`

Check failure on line 1 in tests/pass-dep/shims/libc-getentropy.rs

View workflow job for this annotation

GitHub Actions / build (macos-latest, x86_64-apple-darwin)

pass test got exit status: 1

no message

Check failure on line 1 in tests/pass-dep/shims/libc-getentropy.rs

View workflow job for this annotation

GitHub Actions / build (macos-latest, x86_64-apple-darwin)

test generated output

you likely need to bless the tests with `./miri test --bless`

fn main() {
let mut buf1 = [0u8; 256];
Expand Down

0 comments on commit cb0d2c3

Please sign in to comment.