Add 'randd/' from commit '80e27cb3d923e3a2c91b59122376e18233111a99'

git-subtree-dir: randd
git-subtree-mainline: 2179992ac3
git-subtree-split: 80e27cb3d9
This commit is contained in:
bjorn3
2025-02-18 21:32:14 +01:00
6 changed files with 691 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/target/
+240
View File
@@ -0,0 +1,240 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "libc"
version = "0.2.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
"redox_syscall",
]
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
[[package]]
name = "randd"
version = "0.1.0"
dependencies = [
"libredox",
"rand_chacha",
"rand_core",
"raw-cpuid",
"redox-daemon",
"redox-scheme",
"redox_syscall",
"sha2",
]
[[package]]
name = "raw-cpuid"
version = "11.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0"
dependencies = [
"bitflags",
]
[[package]]
name = "redox-daemon"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbdeffdb03cf2961b211a2023e683d71f2c225ea93404da5dc34b0dc94f0341"
dependencies = [
"libc",
"libredox",
]
[[package]]
name = "redox-scheme"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95624e20d2c1808f7ca0820720d30aad9f5d2fc404e1ef379431ad7a790c3f7e"
dependencies = [
"libredox",
"redox_syscall",
]
[[package]]
name = "redox_syscall"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
]
[[package]]
name = "sha2"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
dependencies = [
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
[[package]]
name = "syn"
version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
+16
View File
@@ -0,0 +1,16 @@
[package]
name = "randd"
version = "0.1.0"
edition = "2021"
[dependencies]
rand_chacha = "0.2"
rand_core = "0.5"
redox-daemon = "0.1.2"
redox_syscall = "0.5"
libredox = "0.1.3"
sha2 = "0.8"
redox-scheme = "0.2.1"
[target.'cfg(target_arch = "x86_64")'.dependencies]
raw-cpuid = "11.0.1"
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Redox OS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
# randd
Random number generator daemon.
## How To Contribute
To learn how to contribute to this system component you need to read the following document:
- [CONTRIBUTING.md](https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md)
## Development
To learn how to do development with this system component inside the Redox build system you need to read the [Build System](https://doc.redox-os.org/book/build-system-reference.html) and [Coding and Building](https://doc.redox-os.org/book/coding-and-building.html) pages.
### How To Build
To build this system component you need to download the Redox build system, you can learn how to do it on the [Building Redox](https://doc.redox-os.org/book/podman-build.html) page.
This is necessary because they only work with cross-compilation to a Redox virtual machine, but you can do some testing from Linux.
+394
View File
@@ -0,0 +1,394 @@
use std::process;
use std::arch::asm;
use rand_chacha::ChaCha20Rng;
use rand_core::RngCore;
pub const MODE_PERM: u16 = 0x0FFF;
pub const MODE_EXEC: u16 = 0o1;
pub const MODE_WRITE: u16 = 0o2;
pub const MODE_READ: u16 = 0o4;
#[cfg(target_arch = "x86_64")]
use raw_cpuid::CpuId;
use redox_scheme::{RequestKind, SchemeMut, SignalBehavior, Socket, V2};
use syscall::data::Stat;
use syscall::flag::EventFlags;
use syscall::{
Error, Result, EBADF, EBADFD, EEXIST, EINVAL, ENOENT, EPERM, MODE_CHR, O_CLOEXEC, O_CREAT,
O_EXCL, O_RDONLY, O_RDWR, O_STAT, O_WRONLY,
};
// Create an RNG Seed to create initial seed from the rdrand intel instruction
use rand_core::SeedableRng;
use sha2::{Digest, Sha256};
use std::collections::BTreeMap;
use std::num::Wrapping;
// This Daemon implements a Cryptographically Secure Random Number Generator
// that does not block on read - i.e. it is equivalent to linux /dev/urandom
// We do not implement blocking reads as per linux /dev/random for the reasons outlined
// here: https://www.2uo.de/myths-about-urandom/
// Default file access mode for PRNG
const DEFAULT_PRNG_MODE: u16 = 0o644;
// Rand crate recommends at least 256 bits of entropy to seed the RNG
const SEED_BYTES: usize = 32;
/// Create a true random seed for the RNG from the Intel x64 rdrand instruction if present.
/// Will seed with a zero (insecure) if rdrand not present.
fn create_rdrand_seed() -> [u8; SEED_BYTES] {
let mut rng = [0; SEED_BYTES];
let mut have_seeded = false;
#[cfg(target_arch = "x86_64")]
{
if CpuId::new().get_feature_info().unwrap().has_rdrand() {
for i in 0..SEED_BYTES / 8 {
// We get 8 bytes at a time from rdrand instruction
let rand: u64;
unsafe {
asm!("rdrand rax", out("rax") rand);
}
rng[i * 8..(i * 8 + 8)].copy_from_slice(&rand.to_le_bytes());
}
have_seeded = true;
}
} // TODO integrate alternative entropy sources
if !have_seeded {
println!("randd: Seeding failed, no entropy source. Random numbers on this platform are NOT SECURE");
}
rng
}
/// Contains information about an open file
struct OpenFileInfo {
o_flags: usize,
/// Flags used when opening file.
uid: u32,
gid: u32,
file_stat: Stat,
}
impl OpenFileInfo {
/// Tests if the current user has enough permissions to view the file, op is the operation,
/// like read and write, these modes are MODE_EXEC, MODE_READ, and MODE_WRITE
/// Copied from redoxfs
fn permission(&self, op: u16) -> bool {
let mut perm = self.file_stat.st_mode & 0o7;
if self.uid == self.file_stat.st_uid {
// If self.mode is 101100110, >> 6 would be 000000101
// 0o7 is octal for 111, or, when expanded to 9 digits is 000000111
perm |= (self.file_stat.st_mode >> 6) & 0o7;
// Since we erased the GID and OTHER bits when >>6'ing, |= will keep those bits in place.
}
if self.gid == self.file_stat.st_gid || self.file_stat.st_gid == 0 {
perm |= (self.file_stat.st_mode >> 3) & 0o7;
}
if self.uid == 0 {
//set the `other` bits to 111
perm |= 0o7;
}
perm & op == op
}
fn o_flag_set(&self, f: usize) -> bool {
return (f & self.o_flags) == f;
}
}
/// Struct to represent the rand scheme.
struct RandScheme {
socket: Socket,
prng: ChaCha20Rng,
// ChaCha20 is a Cryptographically Secure PRNG
// https://docs.rs/rand/0.5.0/rand/prng/chacha/struct.ChaChaRng.html
// Allows 2^64 streams of random numbers, which we will equate with file numbers
prng_stat: Stat,
open_descriptors: BTreeMap<usize, OpenFileInfo>, // Cannot use HashMap as the implementation
// calls the system RNG (us) for entropy to protect against HashDOS attacks.
// Trying to create a HashMap causes a system crash.
// <file number, information about the open file>
next_fd: Wrapping<usize>,
}
impl RandScheme {
/// Create new rand scheme from a message socket
fn new(socket: Socket) -> RandScheme {
RandScheme {
socket,
prng: ChaCha20Rng::from_seed(create_rdrand_seed()),
prng_stat: Stat {
st_mode: MODE_CHR | DEFAULT_PRNG_MODE,
st_gid: 0,
st_uid: 0,
..Default::default()
},
open_descriptors: BTreeMap::new(),
next_fd: Wrapping(0),
}
}
/// Gets the open file info for a file descriptor if it is open - error otherwise.
fn get_fd(&self, fd: usize) -> Result<&OpenFileInfo> {
// Check we've got a valid file descriptor
let file_info = match self.open_descriptors.get(&fd) {
Some(m) => m,
None => return Err(Error::new(EBADF)),
};
Ok(file_info)
}
/// Checks to see if the op (MODE_READ, MODE_WRITE) can be performed on the open file
/// descriptor - Will return the open file info if successful, and error if the file
/// descriptor is invalid, or the permission is denied.
fn can_perform_op_on_fd(&self, fd: usize, op: u16) -> Result<&OpenFileInfo> {
let file_info = self.get_fd(fd)?;
if !file_info.permission(op) {
return Err(Error::new(EPERM));
}
Ok(file_info)
}
/// Reseed the CSPRNG with the supplied entropy.
/// TODO add this to an entropy pool and give a limited estimate to the amount of entropy
/// TODO consider having trusted and untrusted entropy URIs, with different permissions.
fn reseed_prng(&mut self, entropy: &[u8]) {
// Need to fill a fixed size array for the from_seed, so we'll do 256 bit
// array and has the entropy into it.
let mut digest = Sha256::new();
digest.input(entropy);
let hash = digest.result();
let mut entropy_array: [u8; SEED_BYTES] = [0; SEED_BYTES];
entropy_array.copy_from_slice(hash.as_slice());
self.prng = ChaCha20Rng::from_seed(entropy_array);
}
}
#[test]
fn test_scheme_perms() {
let mut scheme = RandScheme::new(File::open(".").unwrap());
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());
scheme.prng_stat.st_mode = MODE_CHR | 0o400;
let mut fd = scheme.open("", O_RDONLY, 1, 1).unwrap();
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());
assert!(scheme.open("", O_WRONLY, 1, 1).is_err());
assert!(scheme.open("", O_RDWR, 1, 1).is_err());
scheme.prng_stat.st_mode = MODE_CHR | 0o600;
fd = scheme.open("", O_RDWR, 1, 1).unwrap();
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());
fd = scheme.open("", O_STAT, 2, 2).unwrap();
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();
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());
// Try another user in group (no group perms)
fd = scheme.open("", O_STAT | O_CLOEXEC, 2, 1).unwrap();
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.prng_stat.st_mode = MODE_CHR | 0o660;
fd = scheme.open("", O_STAT | O_CLOEXEC, 2, 1).unwrap();
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());
// Check root can do anything
scheme.prng_stat.st_mode = MODE_CHR | 0o000;
fd = scheme.open("", O_STAT | O_CLOEXEC, 0, 0).unwrap();
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());
// 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();
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());
}
impl SchemeMut for RandScheme {
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
// 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" {
return Err(Error::new(ENOENT));
}
if flags & (O_CREAT | O_EXCL) == O_CREAT | O_EXCL {
return Err(Error::new(EEXIST));
}
let fd = self.next_fd;
let open_file_info = OpenFileInfo {
o_flags: flags,
file_stat: self.prng_stat,
uid,
gid,
};
if (open_file_info.o_flag_set(O_RDONLY) || open_file_info.o_flag_set(O_RDWR))
&& !open_file_info.permission(MODE_READ)
{
return Err(Error::new(EPERM));
}
if (open_file_info.o_flag_set(O_WRONLY) || open_file_info.o_flag_set(O_RDWR))
&& !open_file_info.permission(MODE_WRITE)
{
return Err(Error::new(EPERM));
}
self.open_descriptors.insert(fd.0, open_file_info);
// Get the next file descriptor
self.next_fd += Wrapping(1);
// If we've looped round there's a small chance that the file descriptor still exists, so loop till we get one that doesn't
loop {
if !self.open_descriptors.contains_key(&self.next_fd.0) {
break;
} else {
self.next_fd += Wrapping(1);
}
}
Ok(fd.0)
}
/* Resource operations */
fn read(&mut self, file: usize, buf: &mut [u8], _offset: u64, _flags: u32) -> Result<usize> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_READ)?;
// Setting the stream will ensure that if two clients are reading concurrently, they won't get the same numbers
self.prng.set_stream(file as u64); // Should probably find a way to re-instate the counter for this stream, but
// not doing so won't make the output any less 'random'
self.prng.fill_bytes(buf);
Ok(buf.len())
}
fn write(&mut self, file: usize, buf: &[u8], _offset: u64, _flags: u32) -> Result<usize> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_WRITE)?;
// TODO - when we support other entropy sources, just add this to an entropy pool
// TODO - consider having trusted and untrusted entropy writing paths
// We have a healthy mistrust of the entropy we're being given, so we won't seed just with
// that as the resulting numbers would be predictable based on this input
// we'll take 512 bits (arbitrary) from the current PRNG, and seed with that
// and the supplied data.
let mut rng_buf: [u8; SEED_BYTES] = [0; SEED_BYTES];
self.prng.fill_bytes(&mut rng_buf);
let mut rng_vec = Vec::new();
rng_vec.extend(&rng_buf);
rng_vec.extend(buf);
self.reseed_prng(&rng_vec);
Ok(buf.len())
}
fn fchmod(&mut self, file: usize, mode: u16) -> Result<usize> {
// Check fd and permissions
let file_info = self.get_fd(file)?;
// only root and owner can chmod
if file_info.uid != file_info.file_stat.st_uid && file_info.uid != 0 {
return Err(Error::new(EPERM));
}
self.prng_stat.st_mode = MODE_CHR | mode;
Ok(0)
}
fn fchown(&mut self, file: usize, uid: u32, gid: u32) -> Result<usize> {
// Check fd and permissions
let file_info = self.get_fd(file)?;
// only root and owner can chmod
if file_info.uid != file_info.file_stat.st_uid && file_info.uid != 0 {
return Err(Error::new(EPERM));
}
self.prng_stat.st_uid = uid;
self.prng_stat.st_gid = gid;
Ok(0)
}
fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
// Just ignore this.
Ok(0)
}
fn fevent(&mut self, _id: usize, _flags: EventFlags) -> Result<EventFlags> {
Ok(EventFlags::EVENT_READ)
}
fn fpath(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
let mut i = 0;
let scheme_path = b"rand";
while i < buf.len() && i < scheme_path.len() {
buf[i] = scheme_path[i];
i += 1;
}
Ok(i)
}
fn fstat(&mut self, file: usize, stat: &mut Stat) -> Result<usize> {
// Check fd and permissions
self.can_perform_op_on_fd(file, MODE_READ)?;
*stat = self.prng_stat.clone();
Ok(0)
}
fn close(&mut self, file: usize) -> Result<usize> {
// just remove the file descriptor from the open descriptors
match self.open_descriptors.remove(&file) {
Some(_) => Ok(0),
None => Err(Error::new(EBADFD)),
}
}
}
fn daemon(daemon: redox_daemon::Daemon) -> ! {
let socket = Socket::<V2>::create("rand").expect("randd: failed to create rand scheme");
let mut scheme = RandScheme::new(socket);
daemon
.ready()
.expect("randd: failed to mark daemon as ready");
libredox::call::setrens(0, 0).expect("randd: failed to enter null namespace");
while let Some(request) = scheme
.socket
.next_request(SignalBehavior::Restart)
.expect("error reading packet")
{
let RequestKind::Call(call) = request.kind() else {
continue;
};
let response = call.handle_scheme_mut(&mut scheme);
scheme
.socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("error writing packet");
}
process::exit(0);
}
fn main() {
redox_daemon::Daemon::new(daemon).expect("randd: failed to daemonize");
}