diff --git a/Cargo.lock b/Cargo.lock index 9db00054d..4c8c0c495 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,6 +209,7 @@ dependencies = [ "bitvec", "bytemuck", "bytemuck_derive", + "cfg-if", "controlled", "core2", "cpio-decoder", diff --git a/kernel/aster-nix/Cargo.toml b/kernel/aster-nix/Cargo.toml index dfdd1bf8c..c8f52bd72 100644 --- a/kernel/aster-nix/Cargo.toml +++ b/kernel/aster-nix/Cargo.toml @@ -59,12 +59,9 @@ spin = "0.9.4" vte = "0.10" lru = "0.12.3" log = "0.4" -getrandom = { version = "0.2.10", default-features = false, features = [ - "rdrand", -] } bitvec = { version = "1.0", default-features = false, features = ["alloc"] } hashbrown = "0.14" -rand = {version = "0.8.5", default-features = false, features = ["small_rng"]} +rand = { version = "0.8.5", default-features = false, features = ["getrandom", "small_rng", "std_rng"] } static_assertions = "1.1.0" inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e" } getset = "0.1.2" @@ -72,6 +69,12 @@ atomic = "0.6" bytemuck = "1.14.3" bytemuck_derive = "1.5.0" takeable = "0.2.2" +cfg-if = "1.0" + +[target.x86_64-unknown-none.dependencies] +getrandom = { version = "0.2.10", default-features = false, features = [ + "rdrand", +] } [dependencies.lazy_static] version = "1.0" diff --git a/kernel/aster-nix/src/device/random.rs b/kernel/aster-nix/src/device/random.rs index e3c064dc9..1998514eb 100644 --- a/kernel/aster-nix/src/device/random.rs +++ b/kernel/aster-nix/src/device/random.rs @@ -8,13 +8,14 @@ use crate::{ }, prelude::*, process::signal::Poller, + util::random::getrandom, }; pub struct Random; impl Random { pub fn getrandom(buf: &mut [u8]) -> Result { - getrandom::getrandom(buf)?; + getrandom(buf)?; Ok(buf.len()) } } @@ -44,9 +45,3 @@ impl FileIo for Random { events & mask } } - -impl From for Error { - fn from(value: getrandom::Error) -> Self { - Error::with_message(Errno::ENOSYS, "cannot generate random bytes") - } -} diff --git a/kernel/aster-nix/src/device/urandom.rs b/kernel/aster-nix/src/device/urandom.rs index e9d316f5c..20ef9c087 100644 --- a/kernel/aster-nix/src/device/urandom.rs +++ b/kernel/aster-nix/src/device/urandom.rs @@ -8,13 +8,14 @@ use crate::{ }, prelude::*, process::signal::Poller, + util::random::getrandom, }; pub struct Urandom; impl Urandom { pub fn getrandom(buf: &mut [u8]) -> Result { - getrandom::getrandom(buf)?; + getrandom(buf)?; Ok(buf.len()) } } diff --git a/kernel/aster-nix/src/lib.rs b/kernel/aster-nix/src/lib.rs index 2fdfcf7da..29347069b 100644 --- a/kernel/aster-nix/src/lib.rs +++ b/kernel/aster-nix/src/lib.rs @@ -67,6 +67,7 @@ pub(crate) mod vdso; pub mod vm; pub fn init() { + util::random::init(); driver::init(); time::init(); net::init(); diff --git a/kernel/aster-nix/src/process/process/mod.rs b/kernel/aster-nix/src/process/process/mod.rs index b818e5cb4..a45fac948 100644 --- a/kernel/aster-nix/src/process/process/mod.rs +++ b/kernel/aster-nix/src/process/process/mod.rs @@ -600,6 +600,7 @@ mod test { use super::*; fn new_process(parent: Option>) -> Arc { + crate::util::random::init(); crate::fs::rootfs::init_root_mount(); let pid = allocate_tid(); let parent = if let Some(parent) = parent { diff --git a/kernel/aster-nix/src/process/process_vm/init_stack/mod.rs b/kernel/aster-nix/src/process/process_vm/init_stack/mod.rs index e6188a29b..e9b182b6c 100644 --- a/kernel/aster-nix/src/process/process_vm/init_stack/mod.rs +++ b/kernel/aster-nix/src/process/process_vm/init_stack/mod.rs @@ -23,7 +23,7 @@ use aster_rights::{Full, Rights}; use self::aux_vec::{AuxKey, AuxVec}; use crate::{ prelude::*, - util::read_cstring_from_vmar, + util::{random::getrandom, read_cstring_from_vmar}, vm::{perms::VmPerms, vmar::Vmar, vmo::VmoOptions}, }; @@ -107,7 +107,7 @@ impl InitStack { pub(super) fn new() -> Self { let nr_pages_padding = { let mut random_nr_pages_padding: u8 = 0; - getrandom::getrandom(random_nr_pages_padding.as_bytes_mut()).unwrap(); + getrandom(random_nr_pages_padding.as_bytes_mut()).unwrap(); random_nr_pages_padding as usize }; let initial_top = MAX_USERSPACE_VADDR - PAGE_SIZE * nr_pages_padding; @@ -340,7 +340,7 @@ impl<'a> InitStackWriter<'a> { fn generate_random_for_aux_vec() -> [u8; 16] { let mut rand_val = [0; 16]; - getrandom::getrandom(&mut rand_val).unwrap(); + getrandom(&mut rand_val).unwrap(); rand_val } diff --git a/kernel/aster-nix/src/util/mod.rs b/kernel/aster-nix/src/util/mod.rs index effb567ca..4b9d09adc 100644 --- a/kernel/aster-nix/src/util/mod.rs +++ b/kernel/aster-nix/src/util/mod.rs @@ -7,6 +7,7 @@ use aster_rights::Full; use crate::{prelude::*, vm::vmar::Vmar}; pub mod net; +pub mod random; /// Read bytes into the `dest` buffer /// from the user space of the current process. diff --git a/kernel/aster-nix/src/util/random.rs b/kernel/aster-nix/src/util/random.rs new file mode 100644 index 000000000..561ff399a --- /dev/null +++ b/kernel/aster-nix/src/util/random.rs @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MPL-2.0 + +use rand::{rngs::StdRng, Error as RandError, RngCore}; +use spin::Once; + +use crate::prelude::*; + +static RNG: Once> = Once::new(); + +/// Fill `dest` with random bytes. +/// +/// It's cryptographically secure, as documented in [`rand::rngs::StdRng`]. +pub fn getrandom(dst: &mut [u8]) -> Result<()> { + Ok(RNG.get().unwrap().lock().try_fill_bytes(dst)?) +} + +pub fn init() { + // The seed used to initialize the RNG is required to be secure and unpredictable. + + cfg_if::cfg_if! { + if #[cfg(target_arch = "x86_64")] { + use rand::SeedableRng; + + RNG.call_once(|| SpinLock::new(StdRng::from_entropy())); + } else { + compile_error!("unsupported target"); + } + } +} + +impl From for Error { + fn from(value: RandError) -> Self { + Error::with_message(Errno::ENOSYS, "cannot generate random bytes") + } +}