diff --git a/src/entropy.rs b/src/entropy.rs index f286b40b4f..76480bf985 100644 --- a/src/entropy.rs +++ b/src/entropy.rs @@ -9,6 +9,7 @@ use rand_chacha::rand_core::{Rng, SeedableRng}; use crate::arch::kernel::processor::{get_timer_ticks, seed_entropy}; use crate::errno::Errno; +use crate::io; // Reseed every second for increased security while maintaining the performance of // the PRNG. @@ -29,14 +30,14 @@ static POOL: InterruptTicketMutex> = InterruptTicketMutex::new(None /// /// Returns the number of bytes written or `-ENOSYS` if the system does not support /// random data generation. -pub fn read(buf: &mut [u8], _flags: Flags) -> isize { +pub fn read(buf: &mut [u8], _flags: Flags) -> io::Result { let pool = &mut *POOL.lock(); let now = get_timer_ticks(); let pool = match pool { Some(pool) if now.saturating_sub(pool.last_reseed) <= RESEED_INTERVAL => pool, pool => { let Some(seed) = seed_entropy() else { - return -i32::from(Errno::Nosys) as isize; + return Err(Errno::Nosys); }; pool.insert(Pool { @@ -49,5 +50,5 @@ pub fn read(buf: &mut [u8], _flags: Flags) -> isize { pool.rng.fill_bytes(buf); // Slice lengths are always <= isize::MAX so this return value cannot conflict // with error numbers. - buf.len() as isize + Ok(buf.len()) } diff --git a/src/fd/delegate.rs b/src/fd/delegate.rs index dafaff99f1..0478d565f9 100644 --- a/src/fd/delegate.rs +++ b/src/fd/delegate.rs @@ -5,6 +5,7 @@ use core::mem::MaybeUninit; use delegate::delegate; use crate::fd::eventfd::EventFd; +use crate::fd::random_file::RandomFile; #[cfg(feature = "tcp")] use crate::fd::socket::tcp; #[cfg(feature = "udp")] @@ -54,6 +55,7 @@ pub(crate) enum Fd { DirectoryReader(DirectoryReader), #[cfg(feature = "uhyve")] UhyveFileHandle(UhyveFileHandle), + RandomFile(RandomFile), } macro_rules! fd_from { @@ -103,6 +105,7 @@ fd_from! { DirectoryReader(DirectoryReader), #[cfg(feature = "uhyve")] UhyveFileHandle(UhyveFileHandle), + RandomFile(RandomFile), } impl ObjectInterface for Fd { @@ -136,6 +139,7 @@ impl ObjectInterface for Fd { Self::DirectoryReader(fd) => fd, #[cfg(feature = "uhyve")] Self::UhyveFileHandle(fd) => fd, + Self::RandomFile(fd) => fd, } { async fn poll(&self, event: PollEvent) -> io::Result; async fn read(&self, buf: &mut [u8]) -> io::Result; diff --git a/src/fd/mod.rs b/src/fd/mod.rs index 548bcac736..7174bf547b 100644 --- a/src/fd/mod.rs +++ b/src/fd/mod.rs @@ -17,6 +17,7 @@ use crate::io; mod delegate; mod eventfd; +pub(crate) mod random_file; #[cfg(any(feature = "net", feature = "virtio-vsock"))] pub(crate) mod socket; pub(crate) mod stdio; diff --git a/src/fd/random_file.rs b/src/fd/random_file.rs new file mode 100644 index 0000000000..fd67e6dca1 --- /dev/null +++ b/src/fd/random_file.rs @@ -0,0 +1,10 @@ +use crate::fd::ObjectInterface; +use crate::{entropy, io}; + +pub struct RandomFile; + +impl ObjectInterface for RandomFile { + async fn read(&self, buf: &mut [u8]) -> io::Result { + entropy::read(buf, entropy::Flags::empty()) + } +} diff --git a/src/fs/dev_directory.rs b/src/fs/dev_directory.rs new file mode 100644 index 0000000000..2dfc2de940 --- /dev/null +++ b/src/fs/dev_directory.rs @@ -0,0 +1,39 @@ +use alloc::boxed::Box; +use alloc::sync::Arc; + +use crate::errno::Errno; +use crate::fd::random_file::RandomFile; +use crate::fd::{AccessPermission, Fd, OpenOption}; +use crate::fs::{NodeKind, VfsNode}; +use crate::io; + +pub(crate) fn init() { + crate::fs::FILESYSTEM + .get() + .unwrap() + .mount("/dev", Box::new(DevDirectory)) + .unwrap(); +} + +#[derive(Debug)] +pub(crate) struct DevDirectory; + +impl VfsNode for DevDirectory { + fn get_kind(&self) -> NodeKind { + NodeKind::Directory + } + + fn traverse_open( + &self, + path: &str, + _option: OpenOption, + _mode: AccessPermission, + ) -> io::Result>> { + match path { + "urandom" | "random" => Ok(Arc::new(async_lock::RwLock::new(Fd::RandomFile( + RandomFile, + )))), + _ => Err(Errno::Noent), + } + } +} diff --git a/src/fs/mem.rs b/src/fs/mem.rs index d09208ff3a..61002da066 100644 --- a/src/fs/mem.rs +++ b/src/fs/mem.rs @@ -648,7 +648,6 @@ impl VfsNode for MemDirectory { ) } - #[cfg(any(feature = "uhyve", feature = "virtio-fs"))] fn traverse_mount(&self, path: &str, obj: Box) -> io::Result<()> { block_on( async { diff --git a/src/fs/mod.rs b/src/fs/mod.rs index a7118b9256..7ba745996b 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -1,3 +1,4 @@ +pub(crate) mod dev_directory; pub(crate) mod mem; #[cfg(feature = "uhyve")] pub(crate) mod uhyve; @@ -5,7 +6,6 @@ pub(crate) mod uhyve; pub(crate) mod virtio_fs; use alloc::borrow::ToOwned; -#[cfg(any(feature = "uhyve", feature = "virtio-fs"))] use alloc::boxed::Box; use alloc::string::String; use alloc::sync::Arc; @@ -98,7 +98,6 @@ pub(crate) trait VfsNode: Send + Sync + fmt::Debug { } /// Mounts a file system - #[cfg(any(feature = "uhyve", feature = "virtio-fs"))] fn traverse_mount(&self, _path: &str, _obj: Box) -> io::Result<()> { Err(Errno::Nosys) } @@ -228,7 +227,6 @@ impl Filesystem { } /// Create new backing-fs at mountpoint mntpath - #[cfg(any(feature = "uhyve", feature = "virtio-fs"))] pub fn mount(&self, path: &str, obj: Box) -> io::Result<()> { debug!("Mounting {path}"); @@ -336,6 +334,8 @@ pub(crate) fn init() { if crate::env::is_uhyve() { uhyve::init(); } + + dev_directory::init(); } pub fn create_file(name: &str, data: &'static [u8], mode: AccessPermission) -> io::Result<()> { diff --git a/src/syscalls/entropy.rs b/src/syscalls/entropy.rs index ae7d33bbf6..4c2a06b2dc 100644 --- a/src/syscalls/entropy.rs +++ b/src/syscalls/entropy.rs @@ -29,18 +29,18 @@ unsafe fn read_entropy(buf: *mut u8, len: usize, flags: u32) -> isize { slice::from_raw_parts_mut(buf, len) }; - let ret = entropy::read(buf, flags); - if ret < 0 { - warn!("Unable to read entropy! Fallback to a naive implementation!"); - for byte in &mut *buf { - *byte = (generate_park_miller_lehmer_random_number() & 0xff) - .try_into() - .unwrap(); - } - buf.len().try_into().unwrap() - } else { - ret - } + entropy::read(buf, flags) + .unwrap_or_else(|_| { + warn!("Unable to read entropy! Fallback to a naive implementation!"); + for byte in &mut *buf { + *byte = (generate_park_miller_lehmer_random_number() & 0xff) + .try_into() + .unwrap(); + } + buf.len() + }) + .try_into() + .unwrap() } /// Fill `len` bytes in `buf` with cryptographically secure random data.