diff --git a/.github/workflows/nopanic.yaml b/.github/workflows/nopanic.yaml index 50fd9492..7ad20ce0 100644 --- a/.github/workflows/nopanic.yaml +++ b/.github/workflows/nopanic.yaml @@ -42,11 +42,11 @@ jobs: - name: Check (linux_android_with_fallback.rs) run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so )) - - name: Build (linux_android.rs) + - name: Build (getrandom.rs) env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom" run: cargo build --release - - name: Check (linux_android.rs) + - name: Check (getrandom.rs) run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so )) - name: Build (linux_raw.rs) @@ -105,11 +105,6 @@ jobs: - name: Check (rndr.rs) run: (exit $( grep -c panic target/aarch64-unknown-linux-gnu/release/libgetrandom_wrapper.so )) - - name: Build (getrandom.rs) - run: cross build --release --target=x86_64-unknown-freebsd - - name: Check (getrandom.rs) - run: (exit $( grep -c panic target/x86_64-unknown-freebsd/release/libgetrandom_wrapper.so )) - - name: Build (netbsd.rs) run: cross build --release --target=x86_64-unknown-netbsd - name: Check (netbsd.rs) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9dc3540b..84b148b4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,6 +65,10 @@ jobs: RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback run: cargo test --features=std + - env: + RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback + RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback + run: cargo test --features=std - env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand" RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="rdrand" diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index ad91b40e..29c0d5ab 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -41,8 +41,6 @@ jobs: run: cargo clippy -Zbuild-std=core --target x86_64-unknown-fuchsia - name: OpenBSD (getentropy.rs) run: cargo clippy -Zbuild-std=core --target x86_64-unknown-openbsd - - name: FreeBSD (getrandom.rs) - run: cargo clippy -Zbuild-std=core --target x86_64-unknown-freebsd - name: Hermit (hermit.rs) run: cargo clippy -Zbuild-std=core --target x86_64-unknown-hermit - name: Web WASM (wasm_js.rs) @@ -53,7 +51,7 @@ jobs: env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown --features wasm_js - - name: Linux (linux_android.rs) + - name: Linux (getrandom.rs) env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom" run: cargo clippy --target x86_64-unknown-linux-gnu diff --git a/Cargo.toml b/Cargo.toml index f2e1b663..69794a08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ cfg-if = "1" compiler_builtins = { version = "0.1", optional = true } core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" } -# linux_android / linux_android_with_fallback +# getrandom / linux_android_with_fallback [target.'cfg(all(any(target_os = "linux", target_os = "android"), not(any(getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))'.dependencies] libc = { version = "0.2.154", default-features = false } @@ -84,6 +84,7 @@ check-cfg = [ 'cfg(getrandom_backend, values("custom", "rdrand", "rndr", "linux_getrandom", "linux_raw", "wasm_js"))', 'cfg(getrandom_msan)', 'cfg(getrandom_test_linux_fallback)', + 'cfg(getrandom_test_linux_without_fallback)', 'cfg(getrandom_test_netbsd_fallback)', ] diff --git a/src/backends.rs b/src/backends.rs index 8bc97744..af66e54e 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -11,8 +11,8 @@ cfg_if! { mod custom; pub use custom::*; } else if #[cfg(getrandom_backend = "linux_getrandom")] { - mod linux_android; - pub use linux_android::*; + mod getrandom; + pub use getrandom::*; } else if #[cfg(getrandom_backend = "linux_raw")] { mod linux_raw; pub use linux_raw::*; @@ -54,17 +54,6 @@ cfg_if! { ))] { mod getentropy; pub use getentropy::*; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "hurd", - target_os = "illumos", - // Check for target_arch = "arm" to only include the 3DS. Does not - // include the Nintendo Switch (which is target_arch = "aarch64"). - all(target_os = "horizon", target_arch = "arm"), - ))] { - mod getrandom; - pub use getrandom::*; } else if #[cfg(any( // Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets // level 21 (Lollipop) [1], while `getrandom(2)` was added only in @@ -105,9 +94,19 @@ cfg_if! { mod use_file; mod linux_android_with_fallback; pub use linux_android_with_fallback::*; - } else if #[cfg(any(target_os = "android", target_os = "linux"))] { - mod linux_android; - pub use linux_android::*; + } else if #[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "hurd", + target_os = "illumos", + // Check for target_arch = "arm" to only include the 3DS. Does not + // include the Nintendo Switch (which is target_arch = "aarch64"). + all(target_os = "horizon", target_arch = "arm"), + ))] { + mod getrandom; + pub use getrandom::*; } else if #[cfg(target_os = "solaris")] { mod solaris; pub use solaris::*; diff --git a/src/backends/getrandom.rs b/src/backends/getrandom.rs index 4a7b96b0..27d5a1f5 100644 --- a/src/backends/getrandom.rs +++ b/src/backends/getrandom.rs @@ -16,7 +16,7 @@ //! nothing. On illumos, the default pool is used to implement getentropy(2), //! so we assume it is acceptable here. use crate::Error; -use core::{ffi::c_void, mem::MaybeUninit}; +use core::mem::MaybeUninit; pub use crate::util::{inner_u32, inner_u64}; @@ -26,6 +26,6 @@ mod util_libc; #[inline] pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { util_libc::sys_fill_exact(dest, |buf| unsafe { - libc::getrandom(buf.as_mut_ptr().cast::(), buf.len(), 0) + libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }) } diff --git a/src/backends/linux_android.rs b/src/backends/linux_android.rs deleted file mode 100644 index 58b4fe80..00000000 --- a/src/backends/linux_android.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Implementation for Linux / Android without `/dev/urandom` fallback -use crate::Error; -use core::mem::MaybeUninit; - -pub use crate::util::{inner_u32, inner_u64}; - -#[path = "../util_libc.rs"] -mod util_libc; - -#[cfg(not(any(target_os = "android", target_os = "linux")))] -compile_error!("`linux_getrandom` backend can be enabled only for Linux/Android targets!"); - -#[inline] -pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - util_libc::sys_fill_exact(dest, |buf| unsafe { - libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) - }) -} diff --git a/src/backends/linux_android_with_fallback.rs b/src/backends/linux_android_with_fallback.rs index 33dabd2e..2ad8f0a4 100644 --- a/src/backends/linux_android_with_fallback.rs +++ b/src/backends/linux_android_with_fallback.rs @@ -3,8 +3,8 @@ use super::use_file; use crate::Error; use core::{ ffi::c_void, - mem::{self, MaybeUninit}, - ptr::{self, NonNull}, + mem::{transmute, MaybeUninit}, + ptr::NonNull, sync::atomic::{AtomicPtr, Ordering}, }; use use_file::util_libc; @@ -17,18 +17,28 @@ type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) /// or not supported by kernel. const NOT_AVAILABLE: NonNull = unsafe { NonNull::new_unchecked(usize::MAX as *mut c_void) }; -static GETRANDOM_FN: AtomicPtr = AtomicPtr::new(ptr::null_mut()); +static GETRANDOM_FN: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); #[cold] #[inline(never)] fn init() -> NonNull { - static NAME: &[u8] = b"getrandom\0"; - let name_ptr = NAME.as_ptr().cast::(); - let raw_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) }; + // Use static linking to `libc::getrandom` on MUSL targets and `dlsym` everywhere else + #[cfg(not(target_env = "musl"))] + let raw_ptr = { + static NAME: &[u8] = b"getrandom\0"; + let name_ptr = NAME.as_ptr().cast::(); + unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) } + }; + #[cfg(target_env = "musl")] + let raw_ptr = { + let fptr: GetRandomFn = libc::getrandom; + unsafe { transmute::(fptr) } + }; + let res_ptr = match NonNull::new(raw_ptr) { Some(fptr) => { - let getrandom_fn = unsafe { mem::transmute::, GetRandomFn>(fptr) }; - let dangling_ptr = ptr::NonNull::dangling().as_ptr(); + let getrandom_fn = unsafe { transmute::, GetRandomFn>(fptr) }; + let dangling_ptr = NonNull::dangling().as_ptr(); // Check that `getrandom` syscall is supported by kernel let res = unsafe { getrandom_fn(dangling_ptr, 0, 0) }; if cfg!(getrandom_test_linux_fallback) { @@ -50,11 +60,16 @@ fn init() -> NonNull { None => NOT_AVAILABLE, }; + #[cfg(getrandom_test_linux_without_fallback)] + if res_ptr == NOT_AVAILABLE { + panic!("Fallback is triggered with enabled `getrandom_test_linux_without_fallback`") + } + GETRANDOM_FN.store(res_ptr.as_ptr(), Ordering::Release); res_ptr } -// prevent inlining of the fallback implementation +// Prevent inlining of the fallback implementation #[inline(never)] fn use_file_fallback(dest: &mut [MaybeUninit]) -> Result<(), Error> { use_file::fill_inner(dest) @@ -78,7 +93,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { use_file_fallback(dest) } else { // note: `transmute` is currently the only way to convert a pointer into a function reference - let getrandom_fn = unsafe { mem::transmute::, GetRandomFn>(fptr) }; + let getrandom_fn = unsafe { transmute::, GetRandomFn>(fptr) }; util_libc::sys_fill_exact(dest, |buf| unsafe { getrandom_fn(buf.as_mut_ptr().cast(), buf.len(), 0) })