Skip to content

Commit f0d2c3f

Browse files
authored
Use configuration flags to switch between backends (#504)
This PR removes `linux_disable_fallback`, `rdrand`, `js`, `test-in-browser`, and `custom` crate features. As their replacement two new configuration flags are introduced: `getrandom_browser_test` and `getrandom_backend`. The latter can have the following values: `custom`, `rdrand`, `linux_getrandom`, `wasm_js`, `esp_idf`. `getrandom_backend` allows to change default backends which resolves issues like #346 and provides more flexibility to users. For example, it allows to use RDRAND or RDRND (see #494) directly instead of syscall-based interfaces. We previously did not allow such overwrites because of security concerns, but they do not apply in this case since configuration flags used by a project can not be controlled by its upstream dependencies. The `register_custom_getrandom!` macro is removed in favor of explicitly defining the `__getrandom_custom` function. It does not look like the macro was widely used in practice and it's probably easier to explain the `extern fn` approach (especially to embedded developers) than the "magical" registration macro. The new configuration flags also allow a great simplification of our testing code. Finally, ESP-IDF support is no longer enabled by default because of the concerns raised in #397. Users can enable it by enabling the `esp_idf` opt-in backend. Closes #230 Closes #346 Closes #397 Closes #498
1 parent 26b88ca commit f0d2c3f

File tree

10 files changed

+461
-469
lines changed

10 files changed

+461
-469
lines changed

.github/workflows/tests.yml

+62-21
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ jobs:
3838
toolchain: ${{ matrix.toolchain }}
3939
- uses: Swatinem/rust-cache@v2
4040
- run: cargo test
41-
# Make sure enabling the std and custom features don't break anything
42-
- run: cargo test --features=std,custom
43-
- run: cargo test --features=linux_disable_fallback
41+
# Make sure enabling the std feature doesn't break anything
42+
- run: cargo test --features=std
4443
- if: ${{ matrix.toolchain == 'nightly' }}
4544
run: cargo test --benches
4645

@@ -69,6 +68,12 @@ jobs:
6968
sudo apt-get install --no-install-recommends ${{ matrix.packages }}
7069
- uses: Swatinem/rust-cache@v2
7170
- run: cargo test ${{ matrix.cargo_test_opts }} --target=${{ matrix.target }} --features=std
71+
- env:
72+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
73+
run: cargo test ${{ matrix.cargo_test_opts }} --target=${{ matrix.target }} --features=std
74+
- env:
75+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
76+
run: cargo test --features=std
7277

7378
ios-tests:
7479
name: iOS Simulator Test
@@ -242,21 +247,27 @@ jobs:
242247
wasm-pack --version
243248
- uses: Swatinem/rust-cache@v2
244249
- name: Test (Node)
245-
run: wasm-pack test --node --features=js
250+
env:
251+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
252+
run: wasm-pack test --node
246253
- name: Test (Firefox)
247-
run: wasm-pack test --headless --firefox --features=js,test-in-browser
254+
env:
255+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
256+
run: wasm-pack test --headless --firefox
248257
- name: Test (Chrome)
249-
run: wasm-pack test --headless --chrome --features=js,test-in-browser
258+
env:
259+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
260+
run: wasm-pack test --headless --chrome
250261
- name: Test (Edge)
251262
if: runner.os == 'Windows'
252-
run: wasm-pack test --headless --chrome --chromedriver $Env:EDGEWEBDRIVER\msedgedriver.exe --features=js,test-in-browser
263+
env:
264+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
265+
run: wasm-pack test --headless --chrome --chromedriver $Env:EDGEWEBDRIVER\msedgedriver.exe
253266
- name: Test (Safari)
254267
if: runner.os == 'macOS'
255-
run: wasm-pack test --headless --safari --features=js,test-in-browser
256-
- name: Test (custom getrandom)
257-
run: wasm-pack test --node --features=custom
258-
- name: Test (JS overrides custom)
259-
run: wasm-pack test --node --features=custom,js
268+
env:
269+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
270+
run: wasm-pack test --headless --safari
260271

261272
wasm64-tests:
262273
name: wasm64 Build/Link
@@ -268,10 +279,12 @@ jobs:
268279
components: rust-src
269280
- uses: Swatinem/rust-cache@v2
270281
- name: Build and Link tests (build-std)
282+
env:
283+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
271284
# This target is Tier 3, so we have to build libstd ourselves.
272285
# We currently cannot run these tests because wasm-bindgen-test-runner
273286
# does not yet support memory64.
274-
run: cargo test --no-run -Z build-std=std,panic_abort --target=wasm64-unknown-unknown --features=js
287+
run: cargo test --no-run -Z build-std=std,panic_abort --target=wasm64-unknown-unknown
275288

276289
wasi-tests:
277290
name: WASI Tests
@@ -325,24 +338,18 @@ jobs:
325338
aarch64-kmc-solid_asp3,
326339
armv6k-nintendo-3ds,
327340
armv7-sony-vita-newlibeabihf,
328-
riscv32imc-esp-espidf,
329341
aarch64-unknown-nto-qnx710,
330342
]
343+
# Supported tier 3 targets with libstd support
331344
include:
332345
- target: aarch64-unknown-nto-qnx710
333346
features: ["std"]
334-
# Supported tier 3 targets with libstd support
335347
- target: x86_64-unknown-openbsd
336348
features: ["std"]
337349
- target: x86_64-unknown-dragonfly
338350
features: ["std"]
339351
- target: x86_64-unknown-haiku
340352
features: ["std"]
341-
# Unsupported tier 3 targets to test the rdrand feature
342-
- target: x86_64-unknown-uefi
343-
features: ["rdrand"]
344-
- target: x86_64-unknown-l4re-uclibc
345-
features: ["rdrand"]
346353
- target: i686-unknown-hurd-gnu
347354
features: ["std"]
348355
steps:
@@ -353,6 +360,38 @@ jobs:
353360
- uses: Swatinem/rust-cache@v2
354361
- run: cargo build -Z build-std=${{ contains(matrix.features, 'std') && 'std' || 'core'}} --target=${{ matrix.target }} --features="${{ join(matrix.features, ',') }}"
355362

363+
build-rdrand:
364+
name: RDRAND Build
365+
runs-on: ubuntu-22.04
366+
strategy:
367+
matrix:
368+
target: [
369+
x86_64-unknown-uefi,
370+
x86_64-unknown-l4re-uclibc,
371+
]
372+
steps:
373+
- uses: actions/checkout@v4
374+
- uses: dtolnay/rust-toolchain@nightly # Required to build libcore
375+
with:
376+
components: rust-src
377+
- uses: Swatinem/rust-cache@v2
378+
- env:
379+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
380+
run: cargo build -Z build-std=core --target=${{ matrix.target }}
381+
382+
build-esp-idf:
383+
name: ESP-IDF Build
384+
runs-on: ubuntu-22.04
385+
steps:
386+
- uses: actions/checkout@v4
387+
- uses: dtolnay/rust-toolchain@nightly # Required to build libcore
388+
with:
389+
components: rust-src
390+
- uses: Swatinem/rust-cache@v2
391+
- env:
392+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="esp_idf"
393+
run: cargo build -Z build-std=core --target=riscv32imc-esp-espidf
394+
356395
build-no-atomics:
357396
name: No Atomics Build
358397
runs-on: ubuntu-22.04
@@ -362,4 +401,6 @@ jobs:
362401
with:
363402
targets: riscv32i-unknown-none-elf
364403
- uses: Swatinem/rust-cache@v2
365-
- run: cargo build --features custom --target riscv32i-unknown-none-elf
404+
- env:
405+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
406+
run: cargo build --target riscv32i-unknown-none-elf

.github/workflows/workspace.yml

+13-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ jobs:
2727
components: clippy,rust-src
2828
- name: std feature
2929
run: cargo clippy --features std
30-
- name: custom feature
31-
run: cargo clippy -Zbuild-std=core --target riscv32i-unknown-none-elf --features custom
30+
- name: custom backend
31+
env:
32+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
33+
run: cargo clippy -Zbuild-std=core --target riscv32i-unknown-none-elf
3234
- name: iOS (apple-other.rs)
3335
run: cargo clippy -Zbuild-std=core --target x86_64-apple-ios
3436
- name: ESP-IDF (espidf.rs)
37+
env:
38+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="esp_idf"
3539
run: cargo clippy -Zbuild-std=core --target riscv32imc-esp-espidf
3640
- name: Fuchsia (fuchsia.rs)
3741
run: cargo clippy -Zbuild-std=core --target x86_64-unknown-fuchsia
@@ -42,9 +46,13 @@ jobs:
4246
- name: Hermit (hermit.rs)
4347
run: cargo clippy -Zbuild-std=core --target x86_64-unknown-hermit
4448
- name: Web WASM (js.rs)
45-
run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown --features js
49+
env:
50+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
51+
run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown
4652
- name: Linux (linux_android.rs)
47-
run: cargo clippy --target x86_64-unknown-linux-gnu --features linux_disable_fallback
53+
env:
54+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
55+
run: cargo clippy --target x86_64-unknown-linux-gnu
4856
- name: Linux (linux_android_with_fallback.rs)
4957
run: cargo clippy --target x86_64-unknown-linux-gnu
5058
- name: NetBSD (netbsd.rs)
@@ -93,4 +101,4 @@ jobs:
93101
- name: Generate Docs
94102
env:
95103
RUSTDOCFLAGS: "-Dwarnings --cfg docsrs"
96-
run: cargo doc --no-deps --features custom
104+
run: cargo doc --no-deps --features std

Cargo.toml

+11-19
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,27 @@ wasi = { version = "0.13", default-features = false }
2727
[target.'cfg(all(windows, not(target_vendor = "win7")))'.dependencies]
2828
windows-targets = "0.52"
2929

30-
[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies]
31-
wasm-bindgen = { version = "0.2.89", default-features = false, optional = true }
32-
js-sys = { version = "0.3", optional = true }
33-
[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dev-dependencies]
30+
[target.'cfg(all(getrandom_backend = "wasm_js", any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies]
31+
wasm-bindgen = { version = "0.2.89", default-features = false }
32+
js-sys = "0.3"
33+
[target.'cfg(all(getrandom_backend = "wasm_js", getrandom_browser_test, any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dev-dependencies]
3434
wasm-bindgen-test = "0.3.39"
3535

3636
[features]
3737
# Implement std-only traits for getrandom::Error
3838
std = []
39-
# Disable `/dev/urandom` fallback for Linux and Android targets.
40-
# Bumps minimum supported Linux kernel version to 3.17 and Android API level to 23 (Marshmallow).
41-
linux_disable_fallback = []
42-
# Feature to enable fallback RDRAND-based implementation on x86/x86_64
43-
rdrand = []
44-
# Feature to enable JavaScript bindings on wasm*-unknown-unknown
45-
js = ["wasm-bindgen", "js-sys"]
46-
# Feature to enable custom RNG implementations
47-
custom = []
4839
# Unstable feature to support being a libstd dependency
4940
rustc-dep-of-std = ["compiler_builtins", "core"]
50-
# Unstable/test-only feature to run wasm-bindgen tests in a browser
51-
test-in-browser = []
5241

53-
[[test]]
54-
name = "custom"
55-
required-features = ["custom"]
42+
[lints.rust.unexpected_cfgs]
43+
level = "warn"
44+
check-cfg = [
45+
'cfg(getrandom_backend, values("custom", "rdrand", "linux_getrandom", "wasm_js", "esp_idf"))',
46+
'cfg(getrandom_browser_test)',
47+
]
5648

5749
[package.metadata.docs.rs]
58-
features = ["std", "custom"]
50+
features = ["std"]
5951
rustdoc-args = ["--cfg", "docsrs"]
6052

6153
# workaround for https://github.com/cross-rs/cross/issues/1345

src/custom.rs

+2-93
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,12 @@
11
//! An implementation which calls out to an externally defined function.
2-
use crate::{util::uninit_slice_fill_zero, Error};
2+
use crate::Error;
33
use core::{mem::MaybeUninit, num::NonZeroU32};
44

5-
/// Register a function to be invoked by `getrandom` on unsupported targets.
6-
///
7-
/// ## Writing a custom `getrandom` implementation
8-
///
9-
/// The function to register must have the same signature as
10-
/// [`getrandom::getrandom`](crate::getrandom). The function can be defined
11-
/// wherever you want, either in root crate or a dependent crate.
12-
///
13-
/// For example, if we wanted a `failure-getrandom` crate containing an
14-
/// implementation that always fails, we would first depend on `getrandom`
15-
/// (for the [`Error`] type) in `failure-getrandom/Cargo.toml`:
16-
/// ```toml
17-
/// [dependencies]
18-
/// getrandom = "0.2"
19-
/// ```
20-
/// Note that the crate containing this function does **not** need to enable the
21-
/// `"custom"` Cargo feature.
22-
///
23-
/// Next, in `failure-getrandom/src/lib.rs`, we define our function:
24-
/// ```rust
25-
/// use core::num::NonZeroU32;
26-
/// use getrandom::Error;
27-
///
28-
/// // Some application-specific error code
29-
/// const MY_CUSTOM_ERROR_CODE: u32 = Error::CUSTOM_START + 42;
30-
/// pub fn always_fail(buf: &mut [u8]) -> Result<(), Error> {
31-
/// let code = NonZeroU32::new(MY_CUSTOM_ERROR_CODE).unwrap();
32-
/// Err(Error::from(code))
33-
/// }
34-
/// ```
35-
///
36-
/// ## Registering a custom `getrandom` implementation
37-
///
38-
/// Functions can only be registered in the root binary crate. Attempting to
39-
/// register a function in a non-root crate will result in a linker error.
40-
/// This is similar to
41-
/// [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) or
42-
/// [`#[global_allocator]`](https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/global-allocators.html),
43-
/// where helper crates define handlers/allocators but only the binary crate
44-
/// actually _uses_ the functionality.
45-
///
46-
/// To register the function, we first depend on `failure-getrandom` _and_
47-
/// `getrandom` in `Cargo.toml`:
48-
/// ```toml
49-
/// [dependencies]
50-
/// failure-getrandom = "0.1"
51-
/// getrandom = { version = "0.2", features = ["custom"] }
52-
/// ```
53-
///
54-
/// Then, we register the function in `src/main.rs`:
55-
/// ```rust
56-
/// # mod failure_getrandom { pub fn always_fail(_: &mut [u8]) -> Result<(), getrandom::Error> { unimplemented!() } }
57-
/// use failure_getrandom::always_fail;
58-
/// use getrandom::register_custom_getrandom;
59-
///
60-
/// register_custom_getrandom!(always_fail);
61-
/// ```
62-
///
63-
/// Now any user of `getrandom` (direct or indirect) on this target will use the
64-
/// registered function. As noted in the
65-
/// [top-level documentation](index.html#custom-implementations) this
66-
/// registration only has an effect on unsupported targets.
67-
#[macro_export]
68-
macro_rules! register_custom_getrandom {
69-
($path:path) => {
70-
// TODO(MSRV 1.37): change to unnamed block
71-
const __GETRANDOM_INTERNAL: () = {
72-
// We use Rust ABI to be safe against potential panics in the passed function.
73-
#[no_mangle]
74-
unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 {
75-
// Make sure the passed function has the type of getrandom::getrandom
76-
type F = fn(&mut [u8]) -> ::core::result::Result<(), $crate::Error>;
77-
let _: F = $crate::getrandom;
78-
let f: F = $path;
79-
let slice = ::core::slice::from_raw_parts_mut(dest, len);
80-
match f(slice) {
81-
Ok(()) => 0,
82-
Err(e) => e.code().get(),
83-
}
84-
}
85-
};
86-
};
87-
}
88-
89-
#[allow(dead_code)]
905
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
916
extern "Rust" {
927
fn __getrandom_custom(dest: *mut u8, len: usize) -> u32;
938
}
94-
// Previously we always passed a valid, initialized slice to
95-
// `__getrandom_custom`. Ensure `dest` has been initialized for backward
96-
// compatibility with implementations that rely on that (e.g. Rust
97-
// implementations that construct a `&mut [u8]` slice from `dest` and
98-
// `len`).
99-
let dest = uninit_slice_fill_zero(dest);
100-
let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) };
9+
let ret = unsafe { __getrandom_custom(dest.as_mut_ptr().cast(), dest.len()) };
10110
match NonZeroU32::new(ret) {
10211
None => Ok(()),
10312
Some(code) => Err(Error::from(code)),

0 commit comments

Comments
 (0)