diff --git a/Cargo.lock b/Cargo.lock index 4d991b3..9b9f33f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,6 +250,7 @@ dependencies = [ "num-traits", "object", "paste", + "rand", "ringbuf", "static_cell", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index fee4143..1438b85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ num-traits = { version = "0.2", default-features = false } ringbuf = { version = "0.4.8", default-features = false, features = ["alloc"] } bitflags = "2.9.1" futures = { version = "0.3.31", default-features = false, features = ["alloc"] } +rand = { version = "0.9.2", default-features = false, features = ["small_rng"] } [profile.release] strip = true diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index 611e6b2..f040dca 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -262,7 +262,7 @@ | 0x113 (275) | sched_getattr | (pid_t pid, struct sched_attr *uattr, unsigned int usize, unsigned int flags) | __arm64_sys_sched_getattr | false | | 0x114 (276) | renameat2 | (int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) | __arm64_sys_renameat2 | false | | 0x115 (277) | seccomp | (unsigned int op, unsigned int flags, void *uargs) | __arm64_sys_seccomp | false | -| 0x116 (278) | getrandom | (char *ubuf, size_t len, unsigned int flags) | __arm64_sys_getrandom | false | +| 0x116 (278) | getrandom | (char *ubuf, size_t len, unsigned int flags) | __arm64_sys_getrandom | true | | 0x117 (279) | memfd_create | (const char *uname, unsigned int flags) | __arm64_sys_memfd_create | false | | 0x118 (280) | bpf | (int cmd, union bpf_attr *uattr, unsigned int size) | __arm64_sys_bpf | false | | 0x119 (281) | execveat | (int fd, const char *filename, const char *const *argv, const char *const *envp, int flags) | __arm64_sys_execveat | false | diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index b211f76..b8f9171 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -1,4 +1,5 @@ use crate::kernel::power::sys_reboot; +use crate::kernel::rand::sys_getrandom; use crate::{ arch::{Arch, ArchImpl}, clock::{gettime::sys_clock_gettime, timeofday::sys_gettimeofday}, @@ -265,6 +266,7 @@ pub async fn handle_syscall() { ) .await } + 0x116 => sys_getrandom(TUA::from_value(arg1 as _), arg2 as _, arg3 as _).await, 0x125 => Err(KernelError::NotSupported), 0x1b7 => { sys_faccessat2( diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index 32677b6..a2a5316 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -1,3 +1,4 @@ pub mod kpipe; pub mod power; +pub mod rand; pub mod uname; diff --git a/src/kernel/rand.rs b/src/kernel/rand.rs new file mode 100644 index 0000000..0588ac4 --- /dev/null +++ b/src/kernel/rand.rs @@ -0,0 +1,39 @@ +// TODO: generate a pool of entropy. + +use crate::{ + drivers::timer::uptime, + memory::uaccess::copy_to_user_slice, + sync::{OnceLock, SpinLock}, +}; +use alloc::vec::Vec; +use libkernel::error::Result; +use libkernel::memory::address::TUA; +use rand::{RngCore, SeedableRng, rngs::SmallRng}; + +pub async fn sys_getrandom(ubuf: TUA, size: isize, _flags: u32) -> Result { + let buf = { + let mut rng = ENTROPY_POOL + .get_or_init(|| { + let now = uptime(); + + SpinLock::new(SmallRng::seed_from_u64( + (now.as_micros() & 0xffffffff_ffffffff) as u64, + )) + }) + .lock_save_irq(); + + let mut buf = Vec::with_capacity(size as usize); + + for _ in 0..size { + buf.push((rng.next_u32() & 0xff) as u8); + } + + buf + }; + + copy_to_user_slice(&buf, ubuf.to_untyped()).await?; + + Ok(size as _) +} + +static ENTROPY_POOL: OnceLock> = OnceLock::new();