randd: Update to redox-scheme 0.8

This commit is contained in:
bjorn3
2025-12-13 12:53:03 +01:00
parent 1ac570fe06
commit c574eda94a
3 changed files with 112 additions and 54 deletions
Generated
+1 -1
View File
@@ -1539,7 +1539,7 @@ dependencies = [
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"raw-cpuid",
"redox-scheme 0.2.4",
"redox-scheme 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall",
"sha2",
]
+1 -1
View File
@@ -10,7 +10,7 @@ daemon = { path = "../daemon" }
redox_syscall = "0.5"
libredox = "0.1.3"
sha2 = "0.8"
redox-scheme = "0.2.1"
redox-scheme = "0.8.2"
[target.'cfg(target_arch = "x86_64")'.dependencies]
raw-cpuid = "11.0.1"
+110 -52
View File
@@ -13,12 +13,14 @@ pub const MODE_READ: u16 = 0o4;
#[cfg(target_arch = "x86_64")]
use raw_cpuid::CpuId;
use redox_scheme::{RequestKind, SchemeMut, SignalBehavior, Socket, V2};
use redox_scheme::scheme::SchemeSync;
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
use syscall::data::Stat;
use syscall::flag::EventFlags;
use syscall::schemev2::NewFdFlags;
use syscall::{
Error, Result, EBADF, EBADFD, EEXIST, ENOENT, EPERM, MODE_CHR, O_CREAT, O_EXCL, O_RDONLY,
O_RDWR, O_WRONLY,
Error, Result, EBADF, EEXIST, ENOENT, EPERM, MODE_CHR, O_CREAT, O_EXCL, O_RDONLY, O_RDWR,
O_WRONLY,
};
// Create an RNG Seed to create initial seed from the rdrand intel instruction
@@ -166,65 +168,104 @@ impl RandScheme {
fn test_scheme_perms() {
use syscall::{O_CLOEXEC, O_STAT};
let mut ctx = CallerCtx {
pid: 0,
uid: 1,
gid: 1,
id: unsafe { std::mem::zeroed() }, // Id doesn't have a public constructor
};
let mut scheme = RandScheme::new();
scheme.prng_stat.st_mode = MODE_CHR | 0o200;
scheme.prng_stat.st_uid = 1;
scheme.prng_stat.st_gid = 1;
assert!(scheme.open("/", O_RDWR, 1, 1).is_err());
assert!(scheme.open("/", O_RDONLY, 1, 1).is_err());
assert!(scheme.open("/", O_RDWR, &ctx).is_err());
assert!(scheme.open("/", O_RDONLY, &ctx).is_err());
scheme.prng_stat.st_mode = MODE_CHR | 0o400;
let mut fd = scheme.open("", O_RDONLY, 1, 1).unwrap();
let mut fd = match scheme.open("", O_RDONLY, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
assert!(scheme.open("", O_WRONLY, 1, 1).is_err());
assert!(scheme.open("", O_RDWR, 1, 1).is_err());
assert!(scheme.open("", O_WRONLY, &ctx).is_err());
assert!(scheme.open("", O_RDWR, &ctx).is_err());
scheme.prng_stat.st_mode = MODE_CHR | 0o600;
fd = scheme.open("", O_RDWR, 1, 1).unwrap();
fd = match scheme.open("", O_RDWR, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
fd = scheme.open("", O_STAT, 2, 2).unwrap();
ctx.uid = 2;
ctx.gid = 2;
fd = match scheme.open("", O_STAT, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err());
assert!(scheme.close(fd).is_ok());
fd = scheme.open("", O_STAT | O_CLOEXEC, 2, 2).unwrap();
scheme.on_close(fd);
fd = match scheme.open("", O_STAT | O_CLOEXEC, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
// Try another user in group (no group perms)
fd = scheme.open("", O_STAT | O_CLOEXEC, 2, 1).unwrap();
ctx.uid = 2;
ctx.gid = 1;
fd = match scheme.open("", O_STAT | O_CLOEXEC, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
scheme.prng_stat.st_mode = MODE_CHR | 0o660;
fd = scheme.open("", O_STAT | O_CLOEXEC, 2, 1).unwrap();
fd = match scheme.open("", O_STAT | O_CLOEXEC, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
// Check root can do anything
scheme.prng_stat.st_mode = MODE_CHR | 0o000;
fd = scheme.open("", O_STAT | O_CLOEXEC, 0, 0).unwrap();
ctx.uid = 0;
ctx.gid = 0;
fd = match scheme.open("", O_STAT | O_CLOEXEC, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
// Check the rand:/urandom URL (Equivalent to rand:/)
scheme.prng_stat.st_mode = MODE_CHR | 0o660;
fd = scheme.open("/urandom", O_STAT | O_CLOEXEC, 2, 1).unwrap();
ctx.uid = 2;
ctx.gid = 1;
fd = match scheme.open("/urandom", O_STAT | O_CLOEXEC, &ctx).unwrap() {
OpenResult::ThisScheme { number, .. } => number,
_ => panic!(),
};
assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok());
assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok());
assert!(scheme.close(fd).is_ok());
scheme.on_close(fd);
}
impl SchemeMut for RandScheme {
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
impl SchemeSync for RandScheme {
fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
// We are only allowing
// reads/writes from rand:/ and rand:/urandom - the root directory on its own is passed as an empty slice
if path != "" && path != "/urandom" {
@@ -238,8 +279,8 @@ impl SchemeMut for RandScheme {
let open_file_info = OpenFileInfo {
o_flags: flags,
file_stat: self.prng_stat,
uid,
gid,
uid: ctx.uid,
gid: ctx.gid,
};
if (open_file_info.o_flag_set(O_RDONLY) || open_file_info.o_flag_set(O_RDWR))
@@ -263,11 +304,21 @@ impl SchemeMut for RandScheme {
self.next_fd += Wrapping(1);
}
}
Ok(fd.0)
Ok(OpenResult::ThisScheme {
number: fd.0,
flags: NewFdFlags::empty(),
})
}
/* Resource operations */
fn read(&mut self, file: usize, buf: &mut [u8], _offset: u64, _flags: u32) -> Result<usize> {
fn read(
&mut self,
file: usize,
buf: &mut [u8],
_offset: u64,
_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_READ)?;
@@ -279,7 +330,14 @@ impl SchemeMut for RandScheme {
Ok(buf.len())
}
fn write(&mut self, file: usize, buf: &[u8], _offset: u64, _flags: u32) -> Result<usize> {
fn write(
&mut self,
file: usize,
buf: &[u8],
_offset: u64,
_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_WRITE)?;
@@ -299,7 +357,7 @@ impl SchemeMut for RandScheme {
Ok(buf.len())
}
fn fchmod(&mut self, file: usize, mode: u16) -> Result<usize> {
fn fchmod(&mut self, file: usize, mode: u16, _ctx: &CallerCtx) -> Result<()> {
// Check fd and permissions
let file_info = self.get_fd(file)?;
// only root and owner can chmod
@@ -308,10 +366,10 @@ impl SchemeMut for RandScheme {
}
self.prng_stat.st_mode = MODE_CHR | mode;
Ok(0)
Ok(())
}
fn fchown(&mut self, file: usize, uid: u32, gid: u32) -> Result<usize> {
fn fchown(&mut self, file: usize, uid: u32, gid: u32, _ctx: &CallerCtx) -> Result<()> {
// Check fd and permissions
let file_info = self.get_fd(file)?;
// only root and owner can chmod
@@ -321,18 +379,18 @@ impl SchemeMut for RandScheme {
self.prng_stat.st_uid = uid;
self.prng_stat.st_gid = gid;
Ok(0)
Ok(())
}
fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize, _ctx: &CallerCtx) -> Result<usize> {
// Just ignore this.
Ok(0)
}
fn fevent(&mut self, _id: usize, _flags: EventFlags) -> Result<EventFlags> {
fn fevent(&mut self, _id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result<EventFlags> {
Ok(EventFlags::EVENT_READ)
}
fn fpath(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
fn fpath(&mut self, _file: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
let mut i = 0;
let scheme_path = b"rand";
while i < buf.len() && i < scheme_path.len() {
@@ -342,26 +400,23 @@ impl SchemeMut for RandScheme {
Ok(i)
}
fn fstat(&mut self, file: usize, stat: &mut Stat) -> Result<usize> {
fn fstat(&mut self, file: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_READ)?;
*stat = self.prng_stat.clone();
Ok(0)
Ok(())
}
fn close(&mut self, file: usize) -> Result<usize> {
fn on_close(&mut self, file: usize) {
// just remove the file descriptor from the open descriptors
match self.open_descriptors.remove(&file) {
Some(_) => Ok(0),
None => Err(Error::new(EBADFD)),
}
self.open_descriptors.remove(&file);
}
}
fn daemon(daemon: daemon::Daemon) -> ! {
let socket = Socket::<V2>::create("rand").expect("randd: failed to create rand scheme");
let socket = Socket::create("rand").expect("randd: failed to create rand scheme");
let mut scheme = RandScheme::new();
@@ -373,13 +428,16 @@ fn daemon(daemon: daemon::Daemon) -> ! {
.next_request(SignalBehavior::Restart)
.expect("error reading packet")
{
let RequestKind::Call(call) = request.kind() else {
continue;
};
let response = call.handle_scheme_mut(&mut scheme);
socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("error writing packet");
match request.kind() {
RequestKind::Call(call) => {
let response = call.handle_sync(&mut scheme);
socket
.write_response(response, SignalBehavior::Restart)
.expect("error writing packet");
}
RequestKind::OnClose { id } => scheme.on_close(id),
_ => {}
}
}
process::exit(0);