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] 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 61feaf73..eb564fff 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 6cb589da..9d1274ec 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 21e35343..d3adaf2a 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 {