From 2fa1bbac80df8389c9cbc01f76fd1805aef9d0d4 Mon Sep 17 00:00:00 2001 From: nia <29542929+niacat@users.noreply.github.com> Date: Wed, 23 Oct 2019 09:03:44 +0000 Subject: [PATCH 1/3] Switch to using the arandom sysctl on NetBSD (same as FreeBSD). (#115) Rename it from freebsd.rs to sysctl_arandom.rs. NetBSD has been patching rustc for some time to use the FreeBSD implementation because every single invocation of the compiler may drain from the entropy pool and cause the next to block. This can massively inflate build times for rust software, or cause it to fail entirely, especially in VMs (for example, our Xen package building cluster). --- src/{freebsd.rs => bsd_arandom.rs} | 28 ++++++++++++++++------------ src/lib.rs | 8 ++++---- src/use_file.rs | 2 +- 3 files changed, 21 insertions(+), 17 deletions(-) rename src/{freebsd.rs => bsd_arandom.rs} (57%) diff --git a/src/freebsd.rs b/src/bsd_arandom.rs similarity index 57% rename from src/freebsd.rs rename to src/bsd_arandom.rs index 61feaf733..eb564ffff 100644 --- a/src/freebsd.rs +++ b/src/bsd_arandom.rs @@ -6,12 +6,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementation for FreeBSD -use crate::util_libc::{sys_fill_exact, Weak}; +//! Implementation for FreeBSD and NetBSD +use crate::util_libc::sys_fill_exact; use crate::Error; -use core::{mem, ptr}; - -type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; +use core::ptr; fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t { static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND]; @@ -27,7 +25,7 @@ fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t { ) }; if ret == -1 { - error!("freebsd: kern.arandom syscall failed"); + error!("sysctl kern.arandom: syscall failed"); -1 } else { len as libc::ssize_t @@ -35,11 +33,17 @@ fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t { } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") }; - if let Some(fptr) = GETRANDOM.ptr() { - let func: GetRandomFn = unsafe { mem::transmute(fptr) }; - sys_fill_exact(dest, |buf| unsafe { func(buf.as_mut_ptr(), buf.len(), 0) }) - } else { - sys_fill_exact(dest, kern_arnd) + #[cfg(target_os = "freebsd")] + { + use crate::util_libc::Weak; + static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") }; + type GetRandomFn = + unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; + + if let Some(fptr) = GETRANDOM.ptr() { + let func: GetRandomFn = unsafe { core::mem::transmute(fptr) }; + return sys_fill_exact(dest, |buf| unsafe { func(buf.as_mut_ptr(), buf.len(), 0) }); + } } + sys_fill_exact(dest, kern_arnd) } diff --git a/src/lib.rs b/src/lib.rs index 6cb589dad..9d1274ec5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ //! | iOS | [`SecRandomCopyBytes`][4] //! | FreeBSD | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5] //! | OpenBSD | [`getentropy`][6] -//! | NetBSD | [`/dev/urandom`][7] after successfully polling `/dev/random` +//! | NetBSD | [`kern.arandom`][7] //! | Dragonfly BSD | [`/dev/random`][8] //! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10] //! | Fuchsia OS | [`cprng_draw`][11] @@ -104,7 +104,7 @@ //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 //! [6]: https://man.openbsd.org/getentropy.2 -//! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current +//! [7]: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-8.0 //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4 //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html @@ -198,7 +198,7 @@ cfg_if! { } else if #[cfg(target_os = "emscripten")] { #[path = "use_file.rs"] mod imp; } else if #[cfg(target_os = "freebsd")] { - #[path = "freebsd.rs"] mod imp; + #[path = "bsd_arandom.rs"] mod imp; } else if #[cfg(target_os = "fuchsia")] { #[path = "fuchsia.rs"] mod imp; } else if #[cfg(target_os = "haiku")] { @@ -212,7 +212,7 @@ cfg_if! { } else if #[cfg(target_os = "macos")] { #[path = "macos.rs"] mod imp; } else if #[cfg(target_os = "netbsd")] { - #[path = "use_file.rs"] mod imp; + #[path = "bsd_arandom.rs"] mod imp; } else if #[cfg(target_os = "openbsd")] { #[path = "openbsd.rs"] mod imp; } else if #[cfg(target_os = "redox")] { diff --git a/src/use_file.rs b/src/use_file.rs index 21e35343a..d3adaf2af 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -39,7 +39,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { } cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux", target_os = "netbsd"))] { + if #[cfg(any(target_os = "android", target_os = "linux"))] { fn init_file() -> Option { // Poll /dev/random to make sure it is ok to read from /dev/urandom. let mut pfd = libc::pollfd { From 9a385f19238f450992f47c995d95fe3391e0a58c Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 23 Oct 2019 09:35:50 +0000 Subject: [PATCH 2/3] Add VxWorks support (#86) --- .travis.yml | 1 + Cargo.toml | 4 ++-- src/error.rs | 2 ++ src/lib.rs | 7 +++++++ src/util_libc.rs | 3 +++ src/vxworks.rs | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/vxworks.rs diff --git a/.travis.yml b/.travis.yml index caa5480db..bdd9e72f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -139,6 +139,7 @@ matrix: - cargo xbuild --target=x86_64-unknown-uefi - cargo xbuild --target=x86_64-unknown-hermit - cargo xbuild --target=x86_64-unknown-l4re-uclibc + - cargo xbuild --target=x86_64-wrs-vxworks # also test minimum dependency versions are usable - cargo generate-lockfile -Z minimal-versions - cargo build --target=x86_64-sun-solaris diff --git a/Cargo.toml b/Cargo.toml index 92c838600..95fc8d861 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ cfg-if = "0.1.2" compiler_builtins = { version = "0.1", optional = true } core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" } -[target.'cfg(any(unix, target_os = "redox"))'.dependencies] -libc = { version = "0.2.62", default-features = false } +[target.'cfg(unix)'.dependencies] +libc = { version = "0.2.64", default-features = false } [target.'cfg(target_os = "wasi")'.dependencies] wasi = "0.7" diff --git a/src/error.rs b/src/error.rs index a27a750ea..3902506bf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -145,6 +145,7 @@ pub(crate) const BINDGEN_CRYPTO_UNDEF: Error = internal_error!(7); pub(crate) const BINDGEN_GRV_UNDEF: Error = internal_error!(8); pub(crate) const STDWEB_NO_RNG: Error = internal_error!(9); pub(crate) const STDWEB_RNG_FAILED: Error = internal_error!(10); +pub(crate) const RAND_SECURE_FATAL: Error = internal_error!(11); fn internal_desc(error: Error) -> Option<&'static str> { match error { @@ -159,6 +160,7 @@ fn internal_desc(error: Error) -> Option<&'static str> { BINDGEN_GRV_UNDEF => Some("wasm-bindgen: crypto.getRandomValues is undefined"), STDWEB_NO_RNG => Some("stdweb: no randomness source available"), STDWEB_RNG_FAILED => Some("stdweb: failed to get randomness"), + RAND_SECURE_FATAL => Some("randSecure: random number generator module is not initialized"), _ => None, } } diff --git a/src/lib.rs b/src/lib.rs index 9d1274ec5..b99ce195a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ //! | Haiku | `/dev/random` (identical to `/dev/urandom`) //! | L4RE, SGX, UEFI | [RDRAND][18] //! | Hermit | [RDRAND][18] as [`sys_rand`][22] is currently broken. +//! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure` //! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14]) //! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16]) //! | WASI | [`__wasi_random_get`][17] @@ -160,6 +161,10 @@ pub use crate::error::Error; #[allow(dead_code)] mod util; +#[cfg(target_os = "vxworks")] +#[allow(dead_code)] +mod util_libc; + cfg_if! { // Unlike the other Unix, Fuchsia and iOS don't use the libc to make any calls. if #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "emscripten", @@ -221,6 +226,8 @@ cfg_if! { #[path = "solaris_illumos.rs"] mod imp; } else if #[cfg(target_os = "wasi")] { #[path = "wasi.rs"] mod imp; + } else if #[cfg(target_os = "vxworks")] { + #[path = "vxworks.rs"] mod imp; } else if #[cfg(all(windows, getrandom_uwp))] { #[path = "windows_uwp.rs"] mod imp; } else if #[cfg(windows)] { diff --git a/src/util_libc.rs b/src/util_libc.rs index d662fc620..5a0517011 100644 --- a/src/util_libc.rs +++ b/src/util_libc.rs @@ -26,7 +26,10 @@ cfg_if! { } pub fn last_os_error() -> Error { + #[cfg(not(target_os = "vxworks"))] let errno = unsafe { *errno_location() }; + #[cfg(target_os = "vxworks")] + let errno = unsafe { libc::errnoGet() }; if errno > 0 { Error::from(NonZeroU32::new(errno as u32).unwrap()) } else { diff --git a/src/vxworks.rs b/src/vxworks.rs new file mode 100644 index 000000000..a2fe52ada --- /dev/null +++ b/src/vxworks.rs @@ -0,0 +1,35 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Implementation for VxWorks +use crate::error::{Error, RAND_SECURE_FATAL}; +use crate::util_libc::last_os_error; +use core::sync::atomic::{AtomicBool, Ordering::Relaxed}; + +pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + static RNG_INIT: AtomicBool = AtomicBool::new(false); + while !RNG_INIT.load(Relaxed) { + let ret = unsafe { libc::randSecure() }; + if ret < 0 { + return Err(RAND_SECURE_FATAL); + } else if ret > 0 { + RNG_INIT.store(true, Relaxed); + break; + } + unsafe { libc::usleep(10) }; + } + + // Prevent overflow of i32 + for chunk in dest.chunks_mut(i32::max_value() as usize) { + let ret = unsafe { libc::randABytes(chunk.as_mut_ptr(), chunk.len() as i32) }; + if ret != 0 { + return Err(last_os_error()); + } + } + Ok(()) +} From 81bd43e5d66e2ee12e81c61f3a5e5d853e33ffe4 Mon Sep 17 00:00:00 2001 From: Joseph Richey Date: Thu, 24 Oct 2019 02:06:53 -0700 Subject: [PATCH 3/3] Fix typos and bad doc links. (#117) --- src/error.rs | 2 +- src/lib.rs | 10 +++++----- src/rdrand.rs | 2 +- src/solaris_illumos.rs | 2 +- src/util.rs | 6 +++--- src/windows_uwp.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/error.rs b/src/error.rs index 3902506bf..b2cb9a8d0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -40,7 +40,7 @@ impl Error { /// /// This method is identical to `std::io::Error::raw_os_error()`, except /// that it works in `no_std` contexts. If this method returns `None`, the - /// error value can still be formatted via the `Diplay` implementation. + /// error value can still be formatted via the `Display` implementation. #[inline] pub fn raw_os_error(self) -> Option { if self.0.get() < Self::INTERNAL_START { diff --git a/src/lib.rs b/src/lib.rs index b99ce195a..c30540623 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,8 @@ //! | L4RE, SGX, UEFI | [RDRAND][18] //! | Hermit | [RDRAND][18] as [`sys_rand`][22] is currently broken. //! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure` -//! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14]) -//! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16]) +//! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and asm.js][16]) +//! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and asm.js][16]) //! | WASI | [`__wasi_random_get`][17] //! //! Getrandom doesn't have a blanket implementation for all Unix-like operating @@ -83,7 +83,7 @@ //! A few, Linux, NetBSD and Solaris, offer a choice between blocking and //! getting an error; in these cases we always choose to block. //! -//! On Linux (when the `genrandom` system call is not available) and on NetBSD +//! On Linux (when the `getrandom` system call is not available) and on NetBSD //! reading from `/dev/urandom` never blocks, even when the OS hasn't collected //! enough entropy yet. To avoid returning low-entropy bytes, we first read from //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded. @@ -114,7 +114,7 @@ //! [13]: https://github.com/nuxinl/cloudabi#random_get //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback -//! [16]: #support-for-webassembly-and-amsjs +//! [16]: #support-for-webassembly-and-asmjs //! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get //! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide //! [19]: https://www.unix.com/man-page/mojave/2/getentropy/ @@ -173,7 +173,7 @@ cfg_if! { target_os = "openbsd", target_os = "redox", target_os = "solaris"))] { #[allow(dead_code)] mod util_libc; - // Keep std-only trait definitions for backwards compatiblity + // Keep std-only trait definitions for backwards compatibility mod error_impls; } else if #[cfg(feature = "std")] { mod error_impls; diff --git a/src/rdrand.rs b/src/rdrand.rs index 96229673f..e4416821b 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -26,7 +26,7 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { let mut el = mem::zeroed(); if _rdrand64_step(&mut el) == 1 { // AMD CPUs from families 14h to 16h (pre Ryzen) sometimes fail to - // set CF on bogus random data, so we check these values explictly. + // set CF on bogus random data, so we check these values explicitly. // See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505 // We perform this check regardless of target to guard against // any implementation that incorrectly fails to set CF. diff --git a/src/solaris_illumos.rs b/src/solaris_illumos.rs index 7550fce96..947312302 100644 --- a/src/solaris_illumos.rs +++ b/src/solaris_illumos.rs @@ -15,7 +15,7 @@ //! //! Since Solaris 11.3 and mid-2015 illumos, the `getrandom` syscall is available. //! To make sure we can compile on both Solaris and its derivatives, as well as -//! function, we check for the existance of getrandom(2) in libc by calling +//! function, we check for the existence of getrandom(2) in libc by calling //! libc::dlsym. use crate::util_libc::{sys_fill_exact, Weak}; use crate::{use_file, Error}; diff --git a/src/util.rs b/src/util.rs index 63a9eab38..e0e930752 100644 --- a/src/util.rs +++ b/src/util.rs @@ -8,8 +8,8 @@ use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; -// This structure represents a laziliy initialized static usize value. Useful -// when it is perferable to just rerun initialization instead of locking. +// This structure represents a lazily initialized static usize value. Useful +// when it is preferable to just rerun initialization instead of locking. // Both unsync_init and sync_init will invoke an init() function until it // succeeds, then return the cached value for future calls. // @@ -25,7 +25,7 @@ use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; // v // } // the effects of c() or writes to shared memory will not necessarily be -// observed and additional syncronization methods with be needed. +// observed and additional synchronization methods with be needed. pub struct LazyUsize(AtomicUsize); impl LazyUsize { diff --git a/src/windows_uwp.rs b/src/windows_uwp.rs index bf15d1a2f..586c6f61c 100644 --- a/src/windows_uwp.rs +++ b/src/windows_uwp.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Implementation for Windows UWP targets. After deprecation of Windows XP -//! and Vista, this can superseed the `RtlGenRandom`-based implementation. +//! and Vista, this can supersede the `RtlGenRandom`-based implementation. use crate::Error; use core::{ffi::c_void, num::NonZeroU32, ptr};