From 4c082e7113904c8f15f2b23d134a333ee4f55edf Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 14 Jun 2019 01:43:42 -0700 Subject: [PATCH] Fix long buffer issues --- src/linux_android.rs | 26 ++++++++++++++++++-------- src/windows.rs | 13 +++++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/linux_android.rs b/src/linux_android.rs index 2aa549f77..bd967de7d 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -28,16 +28,20 @@ thread_local!( static RNG_SOURCE: RefCell> = RefCell::new(None); ); -fn syscall_getrandom(dest: &mut [u8], block: bool) -> Result<(), io::Error> { +fn syscall_getrandom(dest: &mut [u8], block: bool) -> Result { let flags = if block { 0 } else { libc::GRND_NONBLOCK }; let ret = unsafe { libc::syscall(libc::SYS_getrandom, dest.as_mut_ptr(), dest.len(), flags) }; - if ret < 0 || (ret as usize) != dest.len() { + if ret < 0 { + let err = io::Error::last_os_error(); + if err.raw_os_error() == Some(libc::EINTR) { + return Ok(0); // Call was interrupted, try again + } error!("Linux getrandom syscall failed with return value {}", ret); - return Err(io::Error::last_os_error()); + return Err(err); } - Ok(()) + Ok(ret as usize) } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { @@ -58,9 +62,15 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { Ok(s) }, |f| { match f { - RngSource::GetRandom => syscall_getrandom(dest, true), - RngSource::Device(f) => f.read_exact(dest), - }.map_err(From::from) + RngSource::GetRandom => { + let mut start = 0; + while start < dest.len() { + start += syscall_getrandom(&mut dest[start..], true)?; + } + Ok(()) + } + RngSource::Device(f) => f.read_exact(dest).map_err(From::from), + } }) }) } @@ -74,7 +84,7 @@ fn is_getrandom_available() -> bool { CHECKER.call_once(|| { let mut buf: [u8; 0] = []; let available = match syscall_getrandom(&mut buf, false) { - Ok(()) => true, + Ok(_) => true, Err(err) => err.raw_os_error() != Some(libc::ENOSYS), }; AVAILABLE.store(available, Ordering::Relaxed); diff --git a/src/windows.rs b/src/windows.rs index 92feea173..831a40f3c 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -17,12 +17,13 @@ use core::num::NonZeroU32; use crate::Error; pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - let ret = unsafe { - RtlGenRandom(dest.as_mut_ptr() as PVOID, dest.len() as ULONG) - }; - if ret == 0 { - error!("RtlGenRandom call failed"); - return Err(io::Error::last_os_error().into()); + // Prevent overflow of ULONG + for chunk in dest.chunks_mut(ULONG::max_value() as usize) { + let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr() as PVOID, chunk.len() as ULONG) }; + if ret == 0 { + error!("RtlGenRandom call failed"); + return Err(io::Error::last_os_error().into()); + } } Ok(()) }