Add syscall getrandom

This commit is contained in:
Jianfeng Jiang
2023-06-12 17:12:15 +08:00
committed by Tate, Hongliang Tian
parent 3600a3a439
commit 5815f248fc
7 changed files with 136 additions and 3 deletions

View File

@ -1,9 +1,13 @@
mod null;
mod random;
pub mod tty;
mod urandom;
mod zero;
use crate::fs::device::{add_node, Device, DeviceId, DeviceType};
use crate::prelude::*;
pub use random::Random;
pub use urandom::Urandom;
/// Init the device node in fs, must be called after mounting rootfs.
pub fn init() -> Result<()> {
@ -14,5 +18,9 @@ pub fn init() -> Result<()> {
tty::init();
let tty = tty::get_n_tty().clone();
add_node(tty, "tty")?;
let random = Arc::new(random::Random);
add_node(random, "random")?;
let urandom = Arc::new(urandom::Urandom);
add_node(urandom, "urandom")?;
Ok(())
}

View File

@ -0,0 +1,36 @@
use crate::fs::device::{Device, DeviceId, DeviceType};
use crate::prelude::*;
pub struct Random;
impl Random {
pub fn getrandom(buf: &mut [u8]) -> Result<usize> {
getrandom::getrandom(buf)?;
Ok(buf.len())
}
}
impl Device for Random {
fn type_(&self) -> DeviceType {
DeviceType::CharDevice
}
fn id(&self) -> DeviceId {
// The same value as Linux
DeviceId::new(1, 8)
}
fn read(&self, buf: &mut [u8]) -> Result<usize> {
Self::getrandom(buf)
}
fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len())
}
}
impl From<getrandom::Error> for Error {
fn from(value: getrandom::Error) -> Self {
Error::with_message(Errno::ENOSYS, "cannot generate random bytes")
}
}

View File

@ -0,0 +1,30 @@
use crate::fs::device::{Device, DeviceId, DeviceType};
use crate::prelude::*;
pub struct Urandom;
impl Urandom {
pub fn getrandom(buf: &mut [u8]) -> Result<usize> {
getrandom::getrandom(buf)?;
Ok(buf.len())
}
}
impl Device for Urandom {
fn type_(&self) -> DeviceType {
DeviceType::CharDevice
}
fn id(&self) -> DeviceId {
// The same value as Linux
DeviceId::new(1, 9)
}
fn read(&self, buf: &mut [u8]) -> Result<usize> {
Self::getrandom(buf)
}
fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len())
}
}

View File

@ -0,0 +1,36 @@
use crate::device;
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::syscall::SYS_GETRANDOM;
use crate::util::write_bytes_to_user;
use super::SyscallReturn;
pub fn sys_getrandom(buf: Vaddr, count: usize, flags: u32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETRANDOM);
let flags = GetRandomFlags::from_bits_truncate(flags);
debug!(
"buf = 0x{:x}, count = 0x{:x}, flags = {:?}",
buf, count, flags
);
// TODO: support nonblock flag.
// Currently our getrandom implementation relies on x86-specific `rdrand` instruction, so it will never block.
let mut buffer = vec![0u8; count];
let read_len = if flags.contains(GetRandomFlags::GRND_RANDOM) {
device::Random::getrandom(&mut buffer)?
} else {
device::Urandom::getrandom(&mut buffer)?
};
write_bytes_to_user(buf, &buffer)?;
Ok(SyscallReturn::Return(read_len as isize))
}
bitflags::bitflags! {
#[derive(Pod)]
#[repr(C)]
pub struct GetRandomFlags: u32 {
const GRND_NONBLOCK = 0x0001;
const GRND_RANDOM = 0x0002;
const GRND_INSECURE = 0x0004;
}
}

View File

@ -75,6 +75,7 @@ use self::accept::sys_accept;
use self::bind::sys_bind;
use self::connect::sys_connect;
use self::getpeername::sys_getpeername;
use self::getrandom::sys_getrandom;
use self::getsockname::sys_getsockname;
use self::listen::sys_listen;
use self::pread64::sys_pread64;
@ -114,6 +115,7 @@ mod getpeername;
mod getpgrp;
mod getpid;
mod getppid;
mod getrandom;
mod getsockname;
mod gettid;
mod gettimeofday;
@ -295,7 +297,8 @@ define_syscall_nums!(
SYS_UTIMENSAT = 280,
SYS_EPOLL_CREATE1 = 291,
SYS_PIPE2 = 293,
SYS_PRLIMIT64 = 302
SYS_PRLIMIT64 = 302,
SYS_GETRANDOM = 318
);
pub struct SyscallArgument {
@ -453,6 +456,7 @@ pub fn syscall_dispatch(
SYS_EPOLL_CREATE1 => syscall_handler!(1, sys_epoll_create1, args),
SYS_PIPE2 => syscall_handler!(2, sys_pipe2, args),
SYS_PRLIMIT64 => syscall_handler!(4, sys_prlimit64, args),
SYS_GETRANDOM => syscall_handler!(3, sys_getrandom, args),
_ => {
error!("Unimplemented syscall number: {}", syscall_number);
return_errno_with_message!(Errno::ENOSYS, "Syscall was unimplemented");