diff --git a/src/backends/rdrand.rs b/src/backends/rdrand.rs index e1e8934c..ece9a434 100644 --- a/src/backends/rdrand.rs +++ b/src/backends/rdrand.rs @@ -28,10 +28,19 @@ static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new(); const RETRY_LIMIT: usize = 10; #[target_feature(enable = "rdrand")] -#[cfg_attr(target_os = "uefi", allow(unused_unsafe))] // HACK: Rust lint gives false positive on uefi -unsafe fn rdrand() -> Option { +fn rdrand() -> Option { for _ in 0..RETRY_LIMIT { let mut val = 0; + // SAFETY: this function is safe to call from a `[target_feature(enable + // = "rdrand")]` context (it itself is annotated with + // `target_feature(enable = "rdrand")`) but was marked unsafe until + // https://github.com/rust-lang/stdarch/commit/59864cd which was pulled + // in via https://github.com/rust-lang/rust/commit/f2eb88b which is + // expected to be included in 1.93.0. Since our MSRV is 1.85, we need to + // use unsafe here and suppress the lint. + // + // TODO(MSRV 1.93): remove allow(unused_unsafe) and the unsafe block. + #[allow(unused_unsafe)] if unsafe { rdrand_step(&mut val) } == 1 { return Some(val); } @@ -49,12 +58,12 @@ compile_error!( // Adapted from Linux's test in arch/x86/kernel/cpu/rdrand.c // Fails with probability < 2^(-90) on 32-bit systems #[target_feature(enable = "rdrand")] -unsafe fn self_test() -> bool { +fn self_test() -> bool { // On AMD, RDRAND returns 0xFF...FF on failure, count it as a collision. let mut prev = Word::MAX; let mut fails = 0; for _ in 0..8 { - match unsafe { rdrand() } { + match rdrand() { Some(val) if val == prev => fails += 1, Some(val) => prev = val, None => return false, @@ -102,21 +111,20 @@ fn is_rdrand_good() -> bool { unsafe { self_test() } } -// TODO: make this function safe when we have feature(target_feature_11) #[target_feature(enable = "rdrand")] -unsafe fn rdrand_exact(dest: &mut [MaybeUninit]) -> Option<()> { +fn rdrand_exact(dest: &mut [MaybeUninit]) -> Option<()> { // We use chunks_exact_mut instead of chunks_mut as it allows almost all // calls to memcpy to be elided by the compiler. let mut chunks = dest.chunks_exact_mut(size_of::()); for chunk in chunks.by_ref() { - let src = unsafe { rdrand() }?.to_ne_bytes(); + let src = rdrand()?.to_ne_bytes(); chunk.copy_from_slice(slice_as_uninit(&src)); } let tail = chunks.into_remainder(); let n = tail.len(); if n > 0 { - let src = unsafe { rdrand() }?.to_ne_bytes(); + let src = rdrand()?.to_ne_bytes(); tail.copy_from_slice(slice_as_uninit(&src[..n])); } Some(()) @@ -124,27 +132,27 @@ unsafe fn rdrand_exact(dest: &mut [MaybeUninit]) -> Option<()> { #[cfg(target_arch = "x86_64")] #[target_feature(enable = "rdrand")] -unsafe fn rdrand_u32() -> Option { - unsafe { rdrand() }.map(crate::util::truncate) +fn rdrand_u32() -> Option { + rdrand().map(crate::util::truncate) } #[cfg(target_arch = "x86_64")] #[target_feature(enable = "rdrand")] -unsafe fn rdrand_u64() -> Option { - unsafe { rdrand() } +fn rdrand_u64() -> Option { + rdrand() } #[cfg(target_arch = "x86")] #[target_feature(enable = "rdrand")] -unsafe fn rdrand_u32() -> Option { - unsafe { rdrand() } +fn rdrand_u32() -> Option { + rdrand() } #[cfg(target_arch = "x86")] #[target_feature(enable = "rdrand")] -unsafe fn rdrand_u64() -> Option { - let a = unsafe { rdrand() }?; - let b = unsafe { rdrand() }?; +fn rdrand_u64() -> Option { + let a = rdrand()?; + let b = rdrand()?; Some((u64::from(a) << 32) | u64::from(b)) }