Skip to content

Commit cfddae5

Browse files
committed
rdrand: mark rdrand safe
In edition 2024 functions annotated with `target_feature(enable = "..")` are unsafe to call from contexts not so annotated, and otherwise safe. This was used in rust-lang/stdarch#1908 to mark RDRAND safe, and this change is expected to be in 1.93.0 and is already in nightly. Since uefi targets are only tested on nightly, we only saw this lint on uefi, resulting in a misattribution of the behavior and an incorrect comment. Thus acknowledge that the intrinsics are safe and mark `rdrand` itself safe (when called from an annotated context) and remove all the newly unused unsafe blocks. Link: https://doc.rust-lang.org/reference/attributes/codegen.html#r-attributes.codegen.target_feature.safety-restrictions.
1 parent 658bb1a commit cfddae5

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

src/backends/rdrand.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,19 @@ static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new();
2828
const RETRY_LIMIT: usize = 10;
2929

3030
#[target_feature(enable = "rdrand")]
31-
#[cfg_attr(target_os = "uefi", allow(unused_unsafe))] // HACK: Rust lint gives false positive on uefi
32-
unsafe fn rdrand() -> Option<Word> {
31+
fn rdrand() -> Option<Word> {
3332
for _ in 0..RETRY_LIMIT {
3433
let mut val = 0;
34+
// SAFETY: this function is safe to call from a `[target_feature(enable
35+
// = "rdrand")]` context (it itself is annotated with
36+
// `target_feature(enable = "rdrand")`) but was marked unsafe until
37+
// https://github.com/rust-lang/stdarch/pull/1908 which was pulled in
38+
// via https://github.com/rust-lang/rust/pull/148402 which is expected
39+
// to be included in 1.93.0. Since our MSRV is 1.85, we need to use
40+
// unsafe here and suppress the lint.
41+
//
42+
// TODO(MSRV 1.93): remove allow(unused_unsafe) and the unsafe block.
43+
#[allow(unused_unsafe)]
3544
if unsafe { rdrand_step(&mut val) } == 1 {
3645
return Some(val);
3746
}
@@ -54,7 +63,7 @@ unsafe fn self_test() -> bool {
5463
let mut prev = Word::MAX;
5564
let mut fails = 0;
5665
for _ in 0..8 {
57-
match unsafe { rdrand() } {
66+
match rdrand() {
5867
Some(val) if val == prev => fails += 1,
5968
Some(val) => prev = val,
6069
None => return false,
@@ -109,14 +118,14 @@ unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
109118
// calls to memcpy to be elided by the compiler.
110119
let mut chunks = dest.chunks_exact_mut(size_of::<Word>());
111120
for chunk in chunks.by_ref() {
112-
let src = unsafe { rdrand() }?.to_ne_bytes();
121+
let src = rdrand()?.to_ne_bytes();
113122
chunk.copy_from_slice(slice_as_uninit(&src));
114123
}
115124

116125
let tail = chunks.into_remainder();
117126
let n = tail.len();
118127
if n > 0 {
119-
let src = unsafe { rdrand() }?.to_ne_bytes();
128+
let src = rdrand()?.to_ne_bytes();
120129
tail.copy_from_slice(slice_as_uninit(&src[..n]));
121130
}
122131
Some(())
@@ -125,26 +134,26 @@ unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
125134
#[cfg(target_arch = "x86_64")]
126135
#[target_feature(enable = "rdrand")]
127136
unsafe fn rdrand_u32() -> Option<u32> {
128-
unsafe { rdrand() }.map(crate::util::truncate)
137+
rdrand().map(crate::util::truncate)
129138
}
130139

131140
#[cfg(target_arch = "x86_64")]
132141
#[target_feature(enable = "rdrand")]
133142
unsafe fn rdrand_u64() -> Option<u64> {
134-
unsafe { rdrand() }
143+
rdrand()
135144
}
136145

137146
#[cfg(target_arch = "x86")]
138147
#[target_feature(enable = "rdrand")]
139148
unsafe fn rdrand_u32() -> Option<u32> {
140-
unsafe { rdrand() }
149+
rdrand()
141150
}
142151

143152
#[cfg(target_arch = "x86")]
144153
#[target_feature(enable = "rdrand")]
145154
unsafe fn rdrand_u64() -> Option<u64> {
146-
let a = unsafe { rdrand() }?;
147-
let b = unsafe { rdrand() }?;
155+
let a = rdrand()?;
156+
let b = rdrand()?;
148157
Some((u64::from(a) << 32) | u64::from(b))
149158
}
150159

0 commit comments

Comments
 (0)