Fix some `getrandom` behavior
This commit is contained in:
parent
36a38c3f04
commit
d43fbd8f89
|
|
@ -18,7 +18,7 @@ impl Device for Full {
|
|||
}
|
||||
|
||||
fn id(&self) -> DeviceId {
|
||||
// Same value with Linux
|
||||
// The same value as Linux
|
||||
DeviceId::new(1, 7)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub use urandom::Urandom;
|
|||
|
||||
use crate::{
|
||||
fs::{
|
||||
device::{add_node, Device, DeviceId, DeviceType},
|
||||
device::{add_node, Device, DeviceId},
|
||||
fs_resolver::FsPath,
|
||||
ramfs::RamFs,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(unused_variables)]
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::inode_handle::FileIo,
|
||||
fs::{
|
||||
device::{Device, DeviceId, DeviceType},
|
||||
inode_handle::FileIo,
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::{PollHandle, Pollable},
|
||||
};
|
||||
|
|
@ -18,7 +18,7 @@ impl Device for Null {
|
|||
}
|
||||
|
||||
fn id(&self) -> DeviceId {
|
||||
// Same value with Linux
|
||||
// The same value as Linux
|
||||
DeviceId::new(1, 3)
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ impl Device for Null {
|
|||
}
|
||||
|
||||
impl Pollable for Null {
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
let events = IoEvents::IN | IoEvents::OUT;
|
||||
events & mask
|
||||
}
|
||||
|
|
@ -40,6 +40,8 @@ impl FileIo for Null {
|
|||
}
|
||||
|
||||
fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
Ok(reader.remain())
|
||||
let len = reader.remain();
|
||||
reader.skip(len);
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(unused_variables)]
|
||||
|
||||
use super::Urandom;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
|
|
@ -10,15 +9,14 @@ use crate::{
|
|||
},
|
||||
prelude::*,
|
||||
process::signal::{PollHandle, Pollable},
|
||||
util::random::getrandom,
|
||||
};
|
||||
|
||||
pub struct Random;
|
||||
|
||||
impl Random {
|
||||
pub fn getrandom(buf: &mut [u8]) -> Result<usize> {
|
||||
getrandom(buf);
|
||||
Ok(buf.len())
|
||||
pub fn getrandom(writer: &mut VmWriter) -> Result<usize> {
|
||||
// TODO: Support true randomness by collecting environment noise.
|
||||
Urandom::getrandom(writer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +36,7 @@ impl Device for Random {
|
|||
}
|
||||
|
||||
impl Pollable for Random {
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
let events = IoEvents::IN | IoEvents::OUT;
|
||||
events & mask
|
||||
}
|
||||
|
|
@ -46,13 +44,12 @@ impl Pollable for Random {
|
|||
|
||||
impl FileIo for Random {
|
||||
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
let mut buf = vec![0; writer.avail()];
|
||||
let size = Self::getrandom(buf.as_mut_slice());
|
||||
writer.write_fallible(&mut buf.as_slice().into())?;
|
||||
size
|
||||
Self::getrandom(writer)
|
||||
}
|
||||
|
||||
fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
Ok(reader.remain())
|
||||
let len = reader.remain();
|
||||
reader.skip(len);
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@
|
|||
use ostd::mm::{DmaCoherent, FrameAllocOptions, HasPaddr, VmIo};
|
||||
use tdx_guest::tdcall::{get_report, TdCallError};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
error::Error,
|
||||
events::IoEvents,
|
||||
fs::{inode_handle::FileIo, utils::IoctlCmd},
|
||||
fs::{
|
||||
device::{Device, DeviceId, DeviceType},
|
||||
inode_handle::FileIo,
|
||||
utils::IoctlCmd,
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::{PollHandle, Pollable},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(unused_variables)]
|
||||
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
|
|
@ -16,9 +14,26 @@ use crate::{
|
|||
pub struct Urandom;
|
||||
|
||||
impl Urandom {
|
||||
pub fn getrandom(buf: &mut [u8]) -> Result<usize> {
|
||||
getrandom(buf);
|
||||
Ok(buf.len())
|
||||
pub fn getrandom(writer: &mut VmWriter) -> Result<usize> {
|
||||
const IO_CAPABILITY: usize = 4096;
|
||||
|
||||
if !writer.has_avail() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let mut buffer = vec![0; writer.avail().min(IO_CAPABILITY)];
|
||||
let mut written_bytes = 0;
|
||||
|
||||
while writer.has_avail() {
|
||||
getrandom(&mut buffer[..writer.avail().min(IO_CAPABILITY)]);
|
||||
match writer.write_fallible(&mut VmReader::from(buffer.as_slice())) {
|
||||
Ok(len) => written_bytes += len,
|
||||
Err((err, 0)) if written_bytes == 0 => return Err(err.into()),
|
||||
Err((_, len)) => return Ok(written_bytes + len),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(written_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +53,7 @@ impl Device for Urandom {
|
|||
}
|
||||
|
||||
impl Pollable for Urandom {
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
let events = IoEvents::IN | IoEvents::OUT;
|
||||
events & mask
|
||||
}
|
||||
|
|
@ -46,13 +61,12 @@ impl Pollable for Urandom {
|
|||
|
||||
impl FileIo for Urandom {
|
||||
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
let mut buf = vec![0; writer.avail()];
|
||||
let size = Self::getrandom(buf.as_mut_slice());
|
||||
writer.write_fallible(&mut buf.as_slice().into())?;
|
||||
size
|
||||
Self::getrandom(writer)
|
||||
}
|
||||
|
||||
fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
Ok(reader.remain())
|
||||
let len = reader.remain();
|
||||
reader.skip(len);
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(unused_variables)]
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::inode_handle::FileIo,
|
||||
fs::{
|
||||
device::{Device, DeviceId, DeviceType},
|
||||
inode_handle::FileIo,
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::{PollHandle, Pollable},
|
||||
};
|
||||
|
|
@ -18,7 +18,7 @@ impl Device for Zero {
|
|||
}
|
||||
|
||||
fn id(&self) -> DeviceId {
|
||||
// Same value with Linux
|
||||
// The same value as Linux
|
||||
DeviceId::new(1, 5)
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ impl Device for Zero {
|
|||
}
|
||||
|
||||
impl Pollable for Zero {
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
fn poll(&self, mask: IoEvents, _poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
let events = IoEvents::IN | IoEvents::OUT;
|
||||
events & mask
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,28 +4,39 @@ use super::SyscallReturn;
|
|||
use crate::{device, prelude::*};
|
||||
|
||||
pub fn sys_getrandom(buf: Vaddr, count: usize, flags: u32, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let flags = GetRandomFlags::from_bits_truncate(flags);
|
||||
let flags = GetRandomFlags::from_bits(flags)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid 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];
|
||||
|
||||
if flags.contains(GetRandomFlags::GRND_INSECURE | GetRandomFlags::GRND_RANDOM) {
|
||||
return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
"requesting insecure and blocking randomness makes no sense"
|
||||
);
|
||||
}
|
||||
|
||||
// Currently we don't really generate true randomness by collecting environment noise, so we
|
||||
// will never block.
|
||||
// TODO: Support `GRND_NONBLOCK` and `GRND_INSECURE`.
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
let mut writer = user_space.writer(buf, count)?;
|
||||
let read_len = if flags.contains(GetRandomFlags::GRND_RANDOM) {
|
||||
device::Random::getrandom(&mut buffer)?
|
||||
device::Random::getrandom(&mut writer)?
|
||||
} else {
|
||||
device::Urandom::getrandom(&mut buffer)?
|
||||
device::Urandom::getrandom(&mut writer)?
|
||||
};
|
||||
ctx.user_space()
|
||||
.write_bytes(buf, &mut VmReader::from(buffer.as_slice()))?;
|
||||
Ok(SyscallReturn::Return(read_len as isize))
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Pod)]
|
||||
#[repr(C)]
|
||||
pub struct GetRandomFlags: u32 {
|
||||
/// Flags for `getrandom`.
|
||||
///
|
||||
/// Reference: <https://elixir.bootlin.com/linux/v6.16.9/source/include/uapi/linux/random.h#L56>.
|
||||
struct GetRandomFlags: u32 {
|
||||
const GRND_NONBLOCK = 0x0001;
|
||||
const GRND_RANDOM = 0x0002;
|
||||
const GRND_INSECURE = 0x0004;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
|
@ -64,4 +62,4 @@ FN_SETUP(close)
|
|||
{
|
||||
CHECK(close(fd));
|
||||
}
|
||||
END_SETUP()
|
||||
END_SETUP()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "../test.h"
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
FN_TEST(short_rw)
|
||||
{
|
||||
int fd;
|
||||
char *buf;
|
||||
|
||||
fd = TEST_SUCC(open("/dev/random", O_RDONLY));
|
||||
|
||||
buf = TEST_SUCC(mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
||||
TEST_SUCC(munmap(buf + PAGE_SIZE * 2, PAGE_SIZE));
|
||||
|
||||
// Invalid address
|
||||
TEST_ERRNO(read(fd, buf + PAGE_SIZE * 2, PAGE_SIZE), EFAULT);
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2, 0), _ret == 0);
|
||||
|
||||
// Valid address, insufficient space
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - 1, PAGE_SIZE), _ret == 1);
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - (PAGE_SIZE - 1), PAGE_SIZE + 2),
|
||||
_ret == (PAGE_SIZE - 1));
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - PAGE_SIZE, PAGE_SIZE + 2),
|
||||
_ret == PAGE_SIZE);
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - (PAGE_SIZE + 1), PAGE_SIZE + 2),
|
||||
_ret == (PAGE_SIZE + 1));
|
||||
|
||||
// Valid address, sufficient space
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - 1, 1), _ret == 1);
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - (PAGE_SIZE - 1), PAGE_SIZE - 2),
|
||||
_ret == (PAGE_SIZE - 2));
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - PAGE_SIZE, PAGE_SIZE - 1),
|
||||
_ret == (PAGE_SIZE - 1));
|
||||
TEST_RES(read(fd, buf + PAGE_SIZE * 2 - (PAGE_SIZE + 1), PAGE_SIZE),
|
||||
_ret == PAGE_SIZE);
|
||||
|
||||
TEST_SUCC(munmap(buf, PAGE_SIZE * 2));
|
||||
TEST_SUCC(close(fd));
|
||||
}
|
||||
END_TEST()
|
||||
|
|
@ -67,3 +67,4 @@ epoll/epoll_err
|
|||
epoll/poll_err
|
||||
file_io/iovec_err
|
||||
devfs/full
|
||||
devfs/random
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ getrandom01
|
|||
getrandom02
|
||||
getrandom03
|
||||
getrandom04
|
||||
# getrandom05
|
||||
getrandom05
|
||||
|
||||
getresgid01
|
||||
# getresgid01_16
|
||||
|
|
|
|||
Loading…
Reference in New Issue