-
Notifications
You must be signed in to change notification settings - Fork 190
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rndr_with_fallback: Add a RNDR backend with a Linux fallback
Currently, detecting whether FEAT_RNG is available without std relies on the Linux Kernel's MRS emulation. This commit adds a safe rndr_with_fallback backend for Linux systems. With this backend, getrandom will use the RNDR register on Linux systems where it is available and automatically fallback onto using Linux's getrandom syscall on systems where it is not. This implementation allows the crate to be build for Linux with this feature in advance and then run without having to know whether FEAT_RNG is implemented or not. For the time being, this backend is not used by default on any platform configuration. The intention is for it to be usable as an opt-in when an opt-in mechanism is available in the crate.
- Loading branch information
1 parent
6783b87
commit f3c5244
Showing
3 changed files
with
82 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
//! Linux-only safe RNDR register backend for aarch64 targets with fallback | ||
#[cfg(any( | ||
not(any(target_os = "linux", target_os = "android")), | ||
not(target_feature = "rand"), | ||
not(target_arch = "aarch64") | ||
))] | ||
compile_error!( | ||
"The rndr_with_fallback backend requires the `rand` target feature to be enabled | ||
at compile time and can only be built for Linux or Android." | ||
); | ||
|
||
use crate::{lazy::LazyBool, linux_android_with_fallback, rndr, Error}; | ||
use core::arch::asm; | ||
use core::mem::MaybeUninit; | ||
|
||
// Check whether FEAT_RNG is available on the system | ||
// | ||
// Requires the caller either be running in EL1 or be on a system supporting MRS emulation. | ||
// Due to the above, the implementation is currently restricted to Linux. | ||
fn is_rndr_available() -> bool { | ||
let mut id_aa64isar0: u64; | ||
|
||
// If FEAT_RNG is implemented, ID_AA64ISAR0_EL1.RNDR (bits 60-63) are 0b0001 | ||
// This is okay to do from EL0 in Linux because Linux will emulate MRS as per | ||
// https://docs.kernel.org/arch/arm64/cpu-feature-registers.html | ||
unsafe { | ||
asm!( | ||
"mrs {id}, ID_AA64ISAR0_EL1", | ||
id = out(reg) id_aa64isar0, | ||
); | ||
} | ||
|
||
(id_aa64isar0 >> 60) & 0xf >= 1 | ||
} | ||
|
||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { | ||
static RNDR_AVAILABLE: LazyBool = LazyBool::new(); | ||
if !RNDR_AVAILABLE.unsync_init(is_rndr_available) { | ||
return Err(Error::NO_RNDR); | ||
} | ||
|
||
// We've already checked that RNDR is available | ||
if rndr::getrandom_inner(dest).is_ok() { | ||
Ok(()) | ||
} else { | ||
linux_android_with_fallback::getrandom_inner(dest) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#![cfg(all( | ||
target_os = "linux", | ||
target_arch = "aarch64", | ||
feature = "rndr", | ||
target_feature = "rand" | ||
))] | ||
|
||
use getrandom::Error; | ||
#[macro_use] | ||
extern crate cfg_if; | ||
#[path = "../src/lazy.rs"] | ||
mod lazy; | ||
#[path = "../src/linux_android.rs"] | ||
mod linux_android; | ||
#[path = "../src/linux_android_with_fallback.rs"] | ||
mod linux_android_with_fallback; | ||
#[path = "../src/rndr.rs"] | ||
mod rndr; | ||
#[path = "../src/rndr_with_fallback.rs"] | ||
mod rndr_with_fallback; | ||
#[path = "../src/use_file.rs"] | ||
mod use_file; | ||
#[path = "../src/util.rs"] | ||
mod util; | ||
#[path = "../src/util_libc.rs"] | ||
mod util_libc; | ||
|
||
fn getrandom_impl(dest: &mut [u8]) -> Result<(), Error> { | ||
rndr_with_fallback::getrandom_inner(unsafe { util::slice_as_uninit_mut(dest) })?; | ||
Ok(()) | ||
} | ||
mod common; |