Skip to content

Commit 3a40345

Browse files
committed
Simplify atomics using LazyUsize
1 parent 658bb1a commit 3a40345

File tree

14 files changed

+82
-106
lines changed

14 files changed

+82
-106
lines changed

src/backends/getentropy.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@
77
//! - vita newlib since Dec 2021
88
//!
99
//! For these targets, we use getentropy(2) because getrandom(2) doesn't exist.
10-
use crate::Error;
10+
use crate::{Error, util_libc};
1111
use core::{ffi::c_void, mem::MaybeUninit};
1212

1313
pub use crate::util::{inner_u32, inner_u64};
1414

15-
#[path = "../util_libc.rs"]
16-
mod util_libc;
17-
1815
#[inline]
1916
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
2017
for chunk in dest.chunks_mut(256) {

src/backends/getrandom.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515
//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does
1616
//! nothing. On illumos, the default pool is used to implement getentropy(2),
1717
//! so we assume it is acceptable here.
18-
use crate::Error;
18+
use crate::{Error, util_libc};
1919
use core::mem::MaybeUninit;
2020

2121
pub use crate::util::{inner_u32, inner_u64};
2222

23-
#[path = "../util_libc.rs"]
24-
mod util_libc;
25-
2623
#[inline]
2724
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
2825
util_libc::sys_fill_exact(dest, |buf| {

src/backends/linux_android_with_fallback.rs

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,60 @@
11
//! Implementation for Linux / Android with `/dev/urandom` fallback
22
use super::{sanitizer, use_file};
3-
use crate::Error;
3+
use crate::{Error, lazy, util_libc};
44
use core::{
55
ffi::c_void,
66
mem::{MaybeUninit, transmute},
7-
ptr::NonNull,
8-
sync::atomic::{AtomicPtr, Ordering},
7+
ptr,
98
};
10-
use use_file::util_libc;
119

1210
pub use crate::util::{inner_u32, inner_u64};
1311

1412
type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;
1513

1614
/// Sentinel value which indicates that `libc::getrandom` either not available,
1715
/// or not supported by kernel.
18-
const NOT_AVAILABLE: NonNull<c_void> = unsafe { NonNull::new_unchecked(usize::MAX as *mut c_void) };
19-
20-
static GETRANDOM_FN: AtomicPtr<c_void> = AtomicPtr::new(core::ptr::null_mut());
16+
const NOT_AVAILABLE: usize = usize::MAX;
2117

2218
#[cold]
2319
#[inline(never)]
24-
fn init() -> NonNull<c_void> {
20+
fn init() -> usize {
2521
// Use static linking to `libc::getrandom` on MUSL targets and `dlsym` everywhere else
2622
#[cfg(not(target_env = "musl"))]
27-
let raw_ptr = {
28-
static NAME: &[u8] = b"getrandom\0";
29-
let name_ptr = NAME.as_ptr().cast::<libc::c_char>();
30-
unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) }
31-
};
23+
let fptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"getrandom".as_ptr()) } as usize;
3224
#[cfg(target_env = "musl")]
33-
let raw_ptr = {
25+
let fptr = {
3426
let fptr: GetRandomFn = libc::getrandom;
35-
unsafe { transmute::<GetRandomFn, *mut c_void>(fptr) }
27+
unsafe { transmute::<GetRandomFn, usize>(fptr) }
3628
};
3729

38-
let res_ptr = match NonNull::new(raw_ptr) {
39-
Some(fptr) => {
40-
let getrandom_fn = unsafe { transmute::<NonNull<c_void>, GetRandomFn>(fptr) };
41-
let dangling_ptr = NonNull::dangling().as_ptr();
42-
// Check that `getrandom` syscall is supported by kernel
43-
let res = unsafe { getrandom_fn(dangling_ptr, 0, 0) };
44-
if cfg!(getrandom_test_linux_fallback) {
45-
NOT_AVAILABLE
46-
} else if res.is_negative() {
47-
match util_libc::last_os_error().raw_os_error() {
48-
Some(libc::ENOSYS) => NOT_AVAILABLE, // No kernel support
49-
// The fallback on EPERM is intentionally not done on Android since this workaround
50-
// seems to be needed only for specific Linux-based products that aren't based
51-
// on Android. See https://github.com/rust-random/getrandom/issues/229.
52-
#[cfg(target_os = "linux")]
53-
Some(libc::EPERM) => NOT_AVAILABLE, // Blocked by seccomp
54-
_ => fptr,
55-
}
56-
} else {
57-
fptr
30+
let res_ptr = if fptr != 0 {
31+
let getrandom_fn = unsafe { transmute::<usize, GetRandomFn>(fptr) };
32+
// Check that `getrandom` syscall is supported by kernel
33+
let res = unsafe { getrandom_fn(ptr::dangling_mut(), 0, 0) };
34+
if cfg!(getrandom_test_linux_fallback) {
35+
NOT_AVAILABLE
36+
} else if res.is_negative() {
37+
match util_libc::last_os_error().raw_os_error() {
38+
Some(libc::ENOSYS) => NOT_AVAILABLE, // No kernel support
39+
// The fallback on EPERM is intentionally not done on Android since this workaround
40+
// seems to be needed only for specific Linux-based products that aren't based
41+
// on Android. See https://github.com/rust-random/getrandom/issues/229.
42+
#[cfg(target_os = "linux")]
43+
Some(libc::EPERM) => NOT_AVAILABLE, // Blocked by seccomp
44+
_ => fptr,
5845
}
46+
} else {
47+
fptr
5948
}
60-
None => NOT_AVAILABLE,
49+
} else {
50+
NOT_AVAILABLE
6151
};
6252

6353
#[cfg(getrandom_test_linux_without_fallback)]
6454
if res_ptr == NOT_AVAILABLE {
6555
panic!("Fallback is triggered with enabled `getrandom_test_linux_without_fallback`")
6656
}
6757

68-
GETRANDOM_FN.store(res_ptr.as_ptr(), Ordering::Release);
6958
res_ptr
7059
}
7160

@@ -77,23 +66,14 @@ fn use_file_fallback(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
7766

7867
#[inline]
7968
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
80-
// Despite being only a single atomic variable, we still cannot always use
81-
// Ordering::Relaxed, as we need to make sure a successful call to `init`
82-
// is "ordered before" any data read through the returned pointer (which
83-
// occurs when the function is called). Our implementation mirrors that of
84-
// the one in libstd, meaning that the use of non-Relaxed operations is
85-
// probably unnecessary.
86-
let raw_ptr = GETRANDOM_FN.load(Ordering::Acquire);
87-
let fptr = match NonNull::new(raw_ptr) {
88-
Some(p) => p,
89-
None => init(),
90-
};
69+
static GETRANDOM_FN: lazy::LazyUsize = lazy::LazyUsize::new();
70+
let fptr = GETRANDOM_FN.unsync_init(init);
9171

9272
if fptr == NOT_AVAILABLE {
9373
use_file_fallback(dest)
9474
} else {
9575
// note: `transmute` is currently the only way to convert a pointer into a function reference
96-
let getrandom_fn = unsafe { transmute::<NonNull<c_void>, GetRandomFn>(fptr) };
76+
let getrandom_fn = unsafe { transmute::<usize, GetRandomFn>(fptr) };
9777
util_libc::sys_fill_exact(dest, |buf| unsafe {
9878
let ret = getrandom_fn(buf.as_mut_ptr().cast(), buf.len(), 0);
9979
sanitizer::unpoison_linux_getrandom_result(buf, ret);

src/backends/netbsd.rs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,16 @@
33
//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we
44
//! implement our own weak linkage to it, and provide a fallback based on the
55
//! KERN_ARND sysctl.
6-
use crate::Error;
6+
use crate::{Error, lazy, util_libc};
77
use core::{
88
cmp,
99
ffi::c_void,
1010
mem::{self, MaybeUninit},
1111
ptr,
12-
sync::atomic::{AtomicPtr, Ordering},
1312
};
1413

1514
pub use crate::util::{inner_u32, inner_u64};
1615

17-
#[path = "../util_libc.rs"]
18-
mod util_libc;
19-
2016
unsafe extern "C" fn polyfill_using_kern_arand(
2117
buf: *mut c_void,
2218
buflen: libc::size_t,
@@ -42,36 +38,24 @@ unsafe extern "C" fn polyfill_using_kern_arand(
4238

4339
type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;
4440

45-
static GETRANDOM: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
46-
4741
#[cold]
4842
#[inline(never)]
49-
fn init() -> *mut c_void {
50-
static NAME: &[u8] = b"getrandom\0";
51-
let name_ptr = NAME.as_ptr().cast::<libc::c_char>();
52-
let mut ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name_ptr) };
43+
fn init() -> usize {
44+
let mut ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"getrandom".as_ptr()) };
5345
if ptr.is_null() || cfg!(getrandom_test_netbsd_fallback) {
5446
// Verify `polyfill_using_kern_arand` has the right signature.
5547
const POLYFILL: GetRandomFn = polyfill_using_kern_arand;
5648
ptr = POLYFILL as *mut c_void;
5749
}
58-
GETRANDOM.store(ptr, Ordering::Release);
59-
ptr
50+
ptr as usize
6051
}
6152

6253
#[inline]
6354
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
64-
// Despite being only a single atomic variable, we still cannot always use
65-
// Ordering::Relaxed, as we need to make sure a successful call to `init`
66-
// is "ordered before" any data read through the returned pointer (which
67-
// occurs when the function is called). Our implementation mirrors that of
68-
// the one in libstd, meaning that the use of non-Relaxed operations is
69-
// probably unnecessary.
70-
let mut fptr = GETRANDOM.load(Ordering::Acquire);
71-
if fptr.is_null() {
72-
fptr = init();
73-
}
74-
let fptr = unsafe { mem::transmute::<*mut c_void, GetRandomFn>(fptr) };
55+
static GETRANDOM_FN: lazy::LazyUsize = lazy::LazyUsize::new();
56+
57+
let fptr = GETRANDOM_FN.unsync_init(init);
58+
let fptr = unsafe { mem::transmute::<usize, GetRandomFn>(fptr) };
7559
util_libc::sys_fill_exact(dest, |buf| unsafe {
7660
fptr(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
7761
})

src/backends/rdrand.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
//! RDRAND backend for x86(-64) targets
2-
use crate::{Error, util::slice_as_uninit};
2+
use crate::{Error, lazy, util::slice_as_uninit};
33
use core::mem::{MaybeUninit, size_of};
44

5-
#[path = "../lazy.rs"]
6-
mod lazy;
7-
85
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
96
compile_error!("`rdrand` backend can be enabled only for x86 and x86-64 targets!");
107

src/backends/rndr.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ fn is_rndr_available() -> bool {
6969

7070
#[cfg(not(target_feature = "rand"))]
7171
fn is_rndr_available() -> bool {
72-
#[path = "../lazy.rs"]
73-
mod lazy;
72+
use crate::lazy;
7473
static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();
7574

7675
cfg_if::cfg_if! {

src/backends/solaris.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,11 @@
1212
//! For more information, see the man page linked in lib.rs and this blog post:
1313
//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2
1414
//! which also explains why this crate should not use getentropy(2).
15-
use crate::Error;
15+
use crate::{Error, util_libc};
1616
use core::{ffi::c_void, mem::MaybeUninit};
1717

1818
pub use crate::util::{inner_u32, inner_u64};
1919

20-
#[path = "../util_libc.rs"]
21-
mod util_libc;
22-
2320
const MAX_BYTES: usize = 1024;
2421

2522
#[inline]

src/backends/use_file.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Implementations that just need to read from a file
2-
use crate::Error;
2+
use crate::{Error, util_libc};
33
use core::{
44
ffi::{CStr, c_void},
55
mem::MaybeUninit,
@@ -9,9 +9,6 @@ use core::{
99
#[cfg(not(any(target_os = "android", target_os = "linux")))]
1010
pub use crate::util::{inner_u32, inner_u64};
1111

12-
#[path = "../util_libc.rs"]
13-
pub(super) mod util_libc;
14-
1512
/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
1613
/// For more information see the linked man pages in lib.rs.
1714
/// - On Linux, "/dev/urandom is preferred and sufficient in all use cases".

src/backends/vxworks.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
//! Implementation for VxWorks
2-
use crate::Error;
2+
use crate::{Error, util_libc};
33
use core::{
44
cmp::Ordering::{Equal, Greater, Less},
55
mem::MaybeUninit,
66
sync::atomic::{AtomicBool, Ordering::Relaxed},
77
};
88

9-
#[path = "../util_libc.rs"]
10-
mod util_libc;
11-
129
pub use crate::util::{inner_u32, inner_u64};
1310

1411
static RNG_INIT: AtomicBool = AtomicBool::new(false);

src/error.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ impl Error {
5959

6060
/// Creates a new instance of an `Error` from a negative error code.
6161
#[cfg(not(target_os = "uefi"))]
62-
#[allow(dead_code)]
6362
pub(super) fn from_neg_error_code(code: RawOsError) -> Self {
6463
if code < 0 {
6564
let code = NonZeroRawOsError::new(code).expect("`code` is negative");
@@ -71,7 +70,6 @@ impl Error {
7170

7271
/// Creates a new instance of an `Error` from an UEFI error code.
7372
#[cfg(target_os = "uefi")]
74-
#[allow(dead_code)]
7573
pub(super) fn from_uefi_code(code: RawOsError) -> Self {
7674
if code & UEFI_ERROR_FLAG != 0 {
7775
let code = NonZeroRawOsError::new(code).expect("The highest bit of `code` is set to 1");

0 commit comments

Comments
 (0)