From ce0b2601277f0d5f9e11d217c32c8faf6461dee7 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 23 May 2025 13:21:32 +1000 Subject: [PATCH 1/2] Allow `custom` to act as a fallback --- Cargo.toml | 7 +++++++ src/backends.rs | 26 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4a982ee7..46379666 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,18 @@ categories = ["os", "no-std"] exclude = [".*"] [features] +# `first-party-backends-only` is enabled by default for conservative backwards compatibility in 0.3 +# NOTE: Future versions may wish to remove this default depending on the security ramifications. +default = ["first-party-backends-only"] # Implement std::error::Error for getrandom::Error and # use std to retrieve OS error descriptions std = [] # Unstable feature to support being a libstd dependency rustc-dep-of-std = ["dep:compiler_builtins", "dep:core"] +# Throw a compiler error when a first-party backend is not available +# WARNING: It is highly recommended to enable this feature only for binary crates and tests, +# i.e. avoid unconditionally enabling it in library crates. +first-party-backends-only = [] # Optional backend: wasm_js # This flag enables the backend but does not select it. To use the backend, use diff --git a/src/backends.rs b/src/backends.rs index dbe93456..ce7ba07e 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -8,6 +8,8 @@ cfg_if! { if #[cfg(getrandom_backend = "custom")] { + // We allow 3rd party backends when `getrandom_backend = "custom"` is enabled, as it can + // only be enabled by the final binary, even when `first-party-backends-only` is enabled. mod custom; pub use custom::*; } else if #[cfg(getrandom_backend = "linux_getrandom")] { @@ -31,6 +33,7 @@ cfg_if! { mod wasm_js; pub use wasm_js::*; } else { + // If `wasm_js` is enabled the user intended for it to be used, compiler error compile_error!(concat!( "The \"wasm_js\" backend requires the `wasm_js` feature \ for `getrandom`. For more information see: \ @@ -142,7 +145,7 @@ cfg_if! { } else if #[cfg(target_env = "p2")] { mod wasi_p2; pub use wasi_p2::*; - } else { + } else if #[cfg(feature = "first-party-backends-only")] { compile_error!( "Unknown version of WASI (only previews 1 and 2 are supported) \ or Rust version older than 1.80 was used" @@ -167,7 +170,7 @@ cfg_if! { } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] { mod rdrand; pub use rdrand::*; - } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] { + } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), feature = "first-party-backends-only"))] { compile_error!(concat!( "The wasm32-unknown-unknown targets are not supported by default; \ you may need to enable the \"wasm_js\" configuration flag. Note \ @@ -175,10 +178,25 @@ cfg_if! { For more information see: \ https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#webassembly-support" )); - } else { + } else if #[cfg(feature = "first-party-backends-only")] { compile_error!(concat!( - "target is not supported. You may need to define a custom backend see: \ + "target is not supported by a first party backend.\ + You may need to define a custom backend see: \ https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#custom-backend" )); + } else { + #[cfg(feature = "first-party-backends-only")] + compile_error!(concat!( + "an internal error has allowed a 3rd party backend when it\ + was explicitly prohibited.\ + Please file a bug report. See: \ + https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION") + )); + + // Since `first-party-backends-only` is not enabled, allow 3rd party backends via `custom`. + // This is a duplicate of the first branch in this cfg_if statement to allow `custom` to either + // be the highest or lowest priority based on `getrandom_backend = "custom"`. + mod custom; + pub use custom::*; } } From a93916f6f0cc5684b071977760e82d898d30f0d7 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 23 May 2025 17:37:57 +1000 Subject: [PATCH 2/2] Invert to `custom-fallback` feature Also add `getrandom_no_fallback` escape hatch for security-concerned final binaries. --- Cargo.toml | 15 ++++++++------- src/backends.rs | 41 +++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 46379666..160b76d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,18 +12,11 @@ categories = ["os", "no-std"] exclude = [".*"] [features] -# `first-party-backends-only` is enabled by default for conservative backwards compatibility in 0.3 -# NOTE: Future versions may wish to remove this default depending on the security ramifications. -default = ["first-party-backends-only"] # Implement std::error::Error for getrandom::Error and # use std to retrieve OS error descriptions std = [] # Unstable feature to support being a libstd dependency rustc-dep-of-std = ["dep:compiler_builtins", "dep:core"] -# Throw a compiler error when a first-party backend is not available -# WARNING: It is highly recommended to enable this feature only for binary crates and tests, -# i.e. avoid unconditionally enabling it in library crates. -first-party-backends-only = [] # Optional backend: wasm_js # This flag enables the backend but does not select it. To use the backend, use @@ -32,6 +25,13 @@ first-party-backends-only = [] # i.e. avoid unconditionally enabling it in library crates. wasm_js = ["dep:wasm-bindgen", "dep:js-sys"] +# Optional backend: custom-fallback +# This flag enables the use of a 3rd party backend when this crate does not have a suitable option. +# This flag can be overridden using the getrandom_no_fallback RUSTFLAG. +# WARNING: It is highly recommended to enable this feature only for binary crates and tests, +# i.e. avoid unconditionally enabling it in library crates. +custom-fallback = [] + [dependencies] cfg-if = "1" @@ -97,6 +97,7 @@ check-cfg = [ 'cfg(getrandom_test_linux_without_fallback)', 'cfg(getrandom_test_netbsd_fallback)', 'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this. + 'cfg(getrandom_no_fallback)', ] [package.metadata.docs.rs] diff --git a/src/backends.rs b/src/backends.rs index ce7ba07e..fcf04852 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -9,7 +9,7 @@ cfg_if! { if #[cfg(getrandom_backend = "custom")] { // We allow 3rd party backends when `getrandom_backend = "custom"` is enabled, as it can - // only be enabled by the final binary, even when `first-party-backends-only` is enabled. + // only be enabled by the final binary, even when `custom-fallback` isn't enabled. mod custom; pub use custom::*; } else if #[cfg(getrandom_backend = "linux_getrandom")] { @@ -145,11 +145,17 @@ cfg_if! { } else if #[cfg(target_env = "p2")] { mod wasi_p2; pub use wasi_p2::*; - } else if #[cfg(feature = "first-party-backends-only")] { + } else if #[cfg(not(feature = "custom-fallback"))] { + // If the user has not enabled `custom-fallback` then no backend is available compile_error!( "Unknown version of WASI (only previews 1 and 2 are supported) \ or Rust version older than 1.80 was used" ); + } else if #[cfg(getrandom_no_fallback)] { + compile_error!( + "The `getrandom_no_fallback` RUSTFLAG has been set,\ + but the \"custom-fallback\" feature has been enabled." + ); } } } else if #[cfg(target_os = "hermit")] { @@ -170,7 +176,20 @@ cfg_if! { } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] { mod rdrand; pub use rdrand::*; - } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), feature = "first-party-backends-only"))] { + } else if #[cfg(all(feature = "custom-fallback", not(getrandom_no_fallback)))] { + // Since `getrandom_no_fallback` is not enabled, allow 3rd party backends via `custom`. + // This is a duplicate of the first branch in this cfg_if statement to allow `custom` to either + // be the highest or lowest priority based on `getrandom_backend = "custom"`. + mod custom; + pub use custom::*; + } else if #[cfg(all(feature = "custom-fallback", getrandom_no_fallback))] { + compile_error!( + "The `getrandom_no_fallback` RUSTFLAG has been set,\ + but the \"custom-fallback\" feature has been enabled.\ + This typically happens when a dependency provides a custom fallback\ + but you have forbidden it using `getrandom_no_fallback`." + ); + } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] { compile_error!(concat!( "The wasm32-unknown-unknown targets are not supported by default; \ you may need to enable the \"wasm_js\" configuration flag. Note \ @@ -178,25 +197,11 @@ cfg_if! { For more information see: \ https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#webassembly-support" )); - } else if #[cfg(feature = "first-party-backends-only")] { + } else { compile_error!(concat!( "target is not supported by a first party backend.\ You may need to define a custom backend see: \ https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#custom-backend" )); - } else { - #[cfg(feature = "first-party-backends-only")] - compile_error!(concat!( - "an internal error has allowed a 3rd party backend when it\ - was explicitly prohibited.\ - Please file a bug report. See: \ - https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION") - )); - - // Since `first-party-backends-only` is not enabled, allow 3rd party backends via `custom`. - // This is a duplicate of the first branch in this cfg_if statement to allow `custom` to either - // be the highest or lowest priority based on `getrandom_backend = "custom"`. - mod custom; - pub use custom::*; } }