From 2738f69224a41b461aba2df3328994f1a35cad23 Mon Sep 17 00:00:00 2001 From: Ibuki Omatsu Date: Sat, 28 Feb 2026 15:15:16 +0000 Subject: [PATCH] feat: Implement std_fs_call handling to initfs, ramfs, acpi and xhci --- Cargo.lock | 124 ++++++------- Cargo.toml | 8 +- bootstrap/Cargo.lock | 17 +- bootstrap/Cargo.toml | 6 +- bootstrap/src/exec.rs | 4 +- bootstrap/src/initfs.rs | 8 +- bootstrap/src/initnsmgr.rs | 7 +- bootstrap/src/procmgr.rs | 4 +- drivers/acpid/src/main.rs | 5 +- drivers/acpid/src/scheme.rs | 4 +- drivers/graphics/bgad/src/main.rs | 8 +- drivers/graphics/driver-graphics/src/lib.rs | 153 +++++++++------- drivers/graphics/fbbootlogd/src/main.rs | 5 +- drivers/graphics/fbcond/src/main.rs | 33 +++- drivers/inputd/src/main.rs | 5 +- drivers/net/driver-network/src/lib.rs | 22 ++- drivers/pcid/src/main.rs | 8 +- drivers/storage/driver-block/src/lib.rs | 192 +++++++++++--------- drivers/usb/xhcid/src/main.rs | 8 +- drivers/usb/xhcid/src/xhci/scheme.rs | 4 +- logd/src/main.rs | 8 +- netstack/src/scheme/mod.rs | 27 ++- netstack/src/scheme/netcfg/mod.rs | 55 +++--- ramfs/src/main.rs | 5 +- ramfs/src/scheme.rs | 87 ++++++++- randd/src/main.rs | 6 +- zerod/src/main.rs | 5 +- 27 files changed, 512 insertions(+), 306 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a7ac88c98..35c1d60ef3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ "pcid", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "spin 0.9.8", ] @@ -48,7 +48,7 @@ dependencies = [ "plain", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "ron", "rustc-hash", "serde", @@ -68,7 +68,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -190,7 +190,7 @@ dependencies = [ "libc", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -221,7 +221,7 @@ dependencies = [ "fdt 0.2.0-alpha1", "libredox", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -236,7 +236,7 @@ dependencies = [ "orbclient", "pcid", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -438,7 +438,7 @@ dependencies = [ "libredox", "log", "redox-log", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -519,7 +519,7 @@ dependencies = [ "libc", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -583,7 +583,7 @@ dependencies = [ "log", "partitionlib", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -597,7 +597,7 @@ dependencies = [ "libredox", "log", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -607,7 +607,7 @@ dependencies = [ "daemon", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -660,7 +660,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -740,7 +740,7 @@ dependencies = [ "ransid", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -759,7 +759,7 @@ dependencies = [ "ransid", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -891,7 +891,7 @@ dependencies = [ [[package]] name = "generic-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#27b4c3ed907f8037145616e653c36b276d8ab7d0" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#02ac27bf4bf493b9a736f66dee681a0cece1c43d" [[package]] name = "getrandom" @@ -949,7 +949,7 @@ dependencies = [ "libredox", "log", "redox-ioctl", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1069,7 +1069,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1084,7 +1084,7 @@ dependencies = [ "pcid", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "spin 0.9.8", ] @@ -1108,7 +1108,7 @@ dependencies = [ "range-alloc", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "void", ] @@ -1147,7 +1147,7 @@ dependencies = [ "log", "orbclient", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1172,7 +1172,7 @@ dependencies = [ "redox-rt", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1198,7 +1198,7 @@ dependencies = [ "libredox", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1231,14 +1231,15 @@ checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags 2.11.0", "ioslice", "libc", - "redox_syscall 0.7.1", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -1262,7 +1263,7 @@ dependencies = [ "driver-block", "libredox", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1287,7 +1288,7 @@ dependencies = [ "daemon", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1384,7 +1385,7 @@ dependencies = [ "partitionlib", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "smallvec 1.15.1", ] @@ -1510,7 +1511,7 @@ dependencies = [ "pico-args", "plain", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "serde", ] @@ -1525,7 +1526,7 @@ dependencies = [ "log", "pcid", "pico-args", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "serde", "toml", ] @@ -1611,7 +1612,7 @@ dependencies = [ "orbclient", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1622,7 +1623,7 @@ dependencies = [ "libredox", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "redox_termios", ] @@ -1655,7 +1656,7 @@ dependencies = [ "indexmap", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "slab", ] @@ -1743,7 +1744,7 @@ dependencies = [ "rand_core 0.5.1", "raw-cpuid", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "sha2", ] @@ -1804,10 +1805,10 @@ dependencies = [ [[package]] name = "redox-ioctl" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#27b4c3ed907f8037145616e653c36b276d8ab7d0" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#02ac27bf4bf493b9a736f66dee681a0cece1c43d" dependencies = [ "drm-sys", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -1830,32 +1831,33 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" [[package]] name = "redox-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#27b4c3ed907f8037145616e653c36b276d8ab7d0" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#02ac27bf4bf493b9a736f66dee681a0cece1c43d" dependencies = [ "bitflags 2.11.0", "generic-rt", "goblin", "ioslice", + "libredox", "plain", "redox-path", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] name = "redox-scheme" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef5279a1ad9567f8a87818ba80320afdf858853db93742c2bb32be31a82ccdb" +checksum = "e58cb7dee1058575f320f9bfa32c7c0eda857e285c2a163a0eb595d37add09cd" dependencies = [ "libredox", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] name = "redox_event" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3514da49aa6ca4cff5088a1b382ef3a0d9149964d29bb49ebd03fd66cc575a18" +checksum = "4ea3e412d205440c7b0218af26247226f979ed1201674cda7a33cc70609084b5" dependencies = [ "bitflags 2.11.0", "libredox", @@ -1873,7 +1875,7 @@ dependencies = [ "redox-rt", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "smoltcp", ] @@ -1888,9 +1890,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags 2.11.0", ] @@ -1910,7 +1912,7 @@ dependencies = [ "libredox", "qemu-exit", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "redox_termios", ] @@ -1986,7 +1988,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -2001,7 +2003,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -2039,7 +2041,7 @@ dependencies = [ "log", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "spin 0.9.8", ] @@ -2479,7 +2481,7 @@ dependencies = [ "inputd", "log", "orbclient", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "rehid", "xhcid", ] @@ -2490,7 +2492,7 @@ version = "0.1.0" dependencies = [ "common", "log", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "xhcid", ] @@ -2504,7 +2506,7 @@ dependencies = [ "libredox", "plain", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "thiserror 1.0.69", "xhcid", ] @@ -2542,7 +2544,7 @@ dependencies = [ "orbclient", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -2571,7 +2573,7 @@ dependencies = [ "orbclient", "ransid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] @@ -2587,7 +2589,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "spin 0.10.0", "static_assertions", "thiserror 1.0.69", @@ -2606,7 +2608,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "static_assertions", "thiserror 1.0.69", ] @@ -2629,7 +2631,7 @@ dependencies = [ "orbclient", "pcid", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "spin 0.9.8", "static_assertions", "virtio-core", @@ -2646,7 +2648,7 @@ dependencies = [ "libredox", "log", "pcid", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "static_assertions", "virtio-core", ] @@ -2979,7 +2981,7 @@ dependencies = [ "plain", "redox-scheme", "redox_event", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", "regex", "serde", "serde_json", @@ -3015,7 +3017,7 @@ dependencies = [ "daemon", "libredox", "redox-scheme", - "redox_syscall 0.7.1", + "redox_syscall 0.7.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6f5ff73588..c7dbcae775 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,14 +76,14 @@ exclude = ["bootstrap"] anyhow = "1" libc = "0.2.181" log = "0.4" -libredox = "0.1.12" +libredox = "0.1.14" orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient" } -redox_event = "0.4.3" +redox_event = "0.4.6" redox-ioctl = { git = "https://gitlab.redox-os.org/redox-os/relibc.git" } redox-log = { git = "https://gitlab.redox-os.org/redox-os/redox-log.git" } redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false } -redox-scheme = "0.9.1" -redox_syscall = "0.7.1" +redox-scheme = "0.11.0" +redox_syscall = "0.7.3" redox_termios = "0.1.3" serde = { version = "1", features = ["derive"] } toml = "1" diff --git a/bootstrap/Cargo.lock b/bootstrap/Cargo.lock index 41bee0aac9..8a49dff49c 100644 --- a/bootstrap/Cargo.lock +++ b/bootstrap/Cargo.lock @@ -41,7 +41,7 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "generic-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#d0593f54804639117ba5e8d554dd118f634917d3" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#fccd849d2230b23e5fbb2cb5b24e5237d37eb8f1" [[package]] name = "goblin" @@ -77,12 +77,13 @@ checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags", "libc", + "plain", "redox_syscall", ] @@ -150,7 +151,7 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" [[package]] name = "redox-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#d0593f54804639117ba5e8d554dd118f634917d3" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#fccd849d2230b23e5fbb2cb5b24e5237d37eb8f1" dependencies = [ "bitflags", "generic-rt", @@ -163,9 +164,9 @@ dependencies = [ [[package]] name = "redox-scheme" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef5279a1ad9567f8a87818ba80320afdf858853db93742c2bb32be31a82ccdb" +checksum = "e58cb7dee1058575f320f9bfa32c7c0eda857e285c2a163a0eb595d37add09cd" dependencies = [ "libredox", "redox_syscall", @@ -173,9 +174,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags", ] diff --git a/bootstrap/Cargo.toml b/bootstrap/Cargo.toml index 03cdddcdc3..44cfad26d5 100644 --- a/bootstrap/Cargo.toml +++ b/bootstrap/Cargo.toml @@ -15,12 +15,12 @@ hashbrown = { version = "0.15", default-features = false, features = [ "default-hasher", ] } linked_list_allocator = "0.10" -libredox = { version = "0.1.12", default-features = false } +libredox = { version = "0.1.14", default-features = false, features = ["protocol"] } log = { version = "0.4", default-features = false } plain = "0.2" redox-initfs = { path = "../initfs", default-features = false } -redox_syscall = { version = "0.7.1", default-features = false } -redox-scheme = { version = "0.9.1", default-features = false } +redox_syscall = "0.7.3" +redox-scheme = { version = "0.11.0", default-features = false } redox-path = "0.3.1" slab = { version = "0.4.9", default-features = false } arrayvec = { version = "0.7.6", default-features = false } diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index f192bad311..4e417f9e66 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -5,10 +5,10 @@ use core::ffi::CStr; use core::str::FromStr; use hashbrown::HashMap; -use syscall::CallFlags; use syscall::data::{GlobalSchemes, KernelSchemeInfo}; use syscall::flag::{O_CLOEXEC, O_RDONLY, O_STAT}; -use syscall::{EINTR, Error}; +use syscall::CallFlags; +use syscall::{Error, EINTR}; use redox_rt::proc::*; diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 640a1f2636..9340cc2dc2 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -9,7 +9,10 @@ use hashbrown::HashMap; use redox_initfs::{InitFs, Inode, InodeDir, InodeKind, InodeStruct, types::Timespec}; use redox_rt::proc::FdGuard; -use redox_scheme::{CallerCtx, OpenResult, RequestKind, scheme::SchemeSync}; +use redox_scheme::{ + CallerCtx, OpenResult, RequestKind, + scheme::{SchemeState, SchemeSync}, +}; use redox_scheme::{SignalBehavior, Socket}; use syscall::PAGE_SIZE; @@ -388,6 +391,7 @@ pub fn run( scheme_creation_cap: usize, ) -> ! { log::info!("bootstrap: starting initfs scheme"); + let mut state = SchemeState::new(); let mut scheme = InitFsScheme::new(bytes); let socket = Socket::create_inner(scheme_creation_cap, false) @@ -421,7 +425,7 @@ pub fn run( }; match req.kind() { RequestKind::Call(req) => { - let resp = req.handle_sync(&mut scheme); + let resp = req.handle_sync(&mut scheme, &mut state); if !socket .write_response(resp, SignalBehavior::Restart) diff --git a/bootstrap/src/initnsmgr.rs b/bootstrap/src/initnsmgr.rs index ad5e1ac2be..103a5a2d2f 100644 --- a/bootstrap/src/initnsmgr.rs +++ b/bootstrap/src/initnsmgr.rs @@ -6,14 +6,14 @@ use core::cell::RefCell; use core::fmt::Debug; use core::mem; use hashbrown::HashMap; +use libredox::protocol::{NsDup, NsPermissions}; use log::{error, warn}; use redox_path::RedoxPath; use redox_path::RedoxScheme; use redox_rt::proc::FdGuard; -use redox_rt::protocol::{NsDup, NsPermissions}; use redox_scheme::{ CallerCtx, OpenResult, RequestKind, Response, SendFdRequest, SignalBehavior, Socket, - scheme::SchemeSync, + scheme::{SchemeState, SchemeSync}, }; use syscall::Stat; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; @@ -495,6 +495,7 @@ pub fn run( let socket = Socket::create_inner(scheme_creation_cap, false) .expect("failed to open init namespace scheme socket"); + let mut state = SchemeState::new(); let mut scheme = NamespaceScheme::new(&socket, schemes, FdGuard::new(scheme_creation_cap)); // send namespace fd to bootstrap @@ -523,7 +524,7 @@ pub fn run( }; match req.kind() { RequestKind::Call(req) => { - let resp = req.handle_sync(&mut scheme); + let resp = req.handle_sync(&mut scheme, &mut state); if !socket .write_response(resp, SignalBehavior::Restart) diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index d81f651bd9..aa7121ab15 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -18,11 +18,11 @@ use arrayvec::ArrayString; use hashbrown::hash_map::{Entry, OccupiedEntry, VacantEntry}; use hashbrown::{DefaultHashBuilder, HashMap, HashSet}; -use redox_rt::proc::FdGuard; -use redox_rt::protocol::{ +use libredox::protocol::{ ProcCall, ProcKillTarget, ProcMeta, RtSigInfo, SIGCHLD, SIGCONT, SIGHUP, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, ThreadCall, WaitFlags, }; +use redox_rt::proc::FdGuard; use redox_scheme::scheme::{IntoTag, Op, OpCall}; use redox_scheme::{ CallerCtx, Id, OpenResult, Request, RequestKind, Response, SendFdRequest, SignalBehavior, diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs index 26ca395adc..0933f63869 100644 --- a/drivers/acpid/src/main.rs +++ b/drivers/acpid/src/main.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use ::acpi::aml::op_region::{RegionHandler, RegionSpace}; use event::{EventFlags, RawEventQueue}; use redox_scheme::{ - scheme::{register_sync_scheme, SchemeSync}, + scheme::{register_sync_scheme, SchemeState, SchemeSync}, RequestKind, Response, SignalBehavior, Socket, }; use syscall::{EAGAIN, EWOULDBLOCK}; @@ -85,6 +85,7 @@ fn daemon(daemon: daemon::Daemon) -> ! { let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue"); let socket = Socket::nonblock().expect("acpid: failed to create disk scheme"); + let mut state = SchemeState::new(); let mut scheme = self::scheme::AcpiScheme::new(&acpi_context, &socket); event_queue @@ -129,7 +130,7 @@ fn daemon(daemon: daemon::Daemon) -> ! { }; match req.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) .expect("acpid: failed to write response"); diff --git a/drivers/acpid/src/scheme.rs b/drivers/acpid/src/scheme.rs index 17ff1afb42..62f36bd3ba 100644 --- a/drivers/acpid/src/scheme.rs +++ b/drivers/acpid/src/scheme.rs @@ -504,10 +504,8 @@ impl SchemeSync for AcpiScheme<'_, '_> { Ok(num_fds) } -} -impl AcpiScheme<'_, '_> { - pub fn on_close(&mut self, id: usize) { + fn on_close(&mut self, id: usize) { self.handles.remove(&id); } } diff --git a/drivers/graphics/bgad/src/main.rs b/drivers/graphics/bgad/src/main.rs index c55db2a6e1..65adf44b11 100644 --- a/drivers/graphics/bgad/src/main.rs +++ b/drivers/graphics/bgad/src/main.rs @@ -2,7 +2,10 @@ use inputd::ProducerHandle; use pcid_interface::PciFunctionHandle; -use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior, Socket}; +use redox_scheme::{ + scheme::{register_sync_scheme, SchemeState}, + RequestKind, SignalBehavior, Socket, +}; use crate::bga::Bga; use crate::scheme::BgaScheme; @@ -39,6 +42,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { let mut bga = unsafe { Bga::new(bar) }; log::debug!("BGA {}x{}", bga.width(), bga.height()); + let mut state = SchemeState::new(); let mut scheme = BgaScheme { bga, display: ProducerHandle::new().ok(), @@ -62,7 +66,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { }; match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index ebd744b0ae..7d2e990b25 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -19,7 +19,7 @@ use graphics_ipc::v1::CursorDamage; use graphics_ipc::v2::Damage; use inputd::{VtEvent, VtEventKind}; use libredox::Fd; -use redox_scheme::scheme::{register_scheme_inner, SchemeSync}; +use redox_scheme::scheme::{register_scheme_inner, SchemeState, SchemeSync}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket}; use syscall::schemev2::NewFdFlags; use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP}; @@ -90,36 +90,8 @@ pub struct CursorPlane { pub trait CursorFramebuffer {} pub struct GraphicsScheme { - adapter: T, - - scheme_name: String, - disable_graphical_debug: Option, - socket: Socket, - objects: DrmObjects, - standard_properties: StandardProperties, - next_id: usize, - handles: BTreeMap>, - - active_vt: usize, - vts: HashMap>, -} - -struct VtState { - display_fbs: Vec>, - cursor_plane: Option>, -} - -enum Handle { - V1Screen { - vt: usize, - screen: usize, - }, - V2 { - vt: usize, - next_id: u32, - fbs: HashMap>, - }, - SchemeRoot, + inner: GraphicsSchemeInner, + state: SchemeState, } impl GraphicsScheme { @@ -153,7 +125,7 @@ impl GraphicsScheme { adapter.probe_connector(&mut objects, &standard_properties, connector_id) } - let mut scheme = GraphicsScheme { + let mut inner = GraphicsSchemeInner { adapter, scheme_name, disable_graphical_debug, @@ -166,41 +138,42 @@ impl GraphicsScheme { vts: HashMap::new(), }; - let cap_id = scheme - .scheme_root() - .expect("failed to get this scheme root"); - register_scheme_inner(&scheme.socket, &scheme.scheme_name, cap_id) + let cap_id = inner.scheme_root().expect("failed to get this scheme root"); + register_scheme_inner(&inner.socket, &inner.scheme_name, cap_id) .expect("failed to register graphics scheme root"); - scheme + Self { + inner, + state: SchemeState::new(), + } } pub fn event_handle(&self) -> &Fd { - self.socket.inner() + self.inner.socket.inner() } pub fn adapter(&self) -> &T { - &self.adapter + &self.inner.adapter } pub fn adapter_mut(&mut self) -> &mut T { - &mut self.adapter + &mut self.inner.adapter } pub fn objects(&self) -> &DrmObjects { - &self.objects + &self.inner.objects } pub fn objects_mut(&mut self) -> &mut DrmObjects { - &mut self.objects + &mut self.inner.objects } pub fn adapter_and_objects_mut(&mut self) -> (&mut T, &mut DrmObjects) { - (&mut self.adapter, &mut self.objects) + (&mut self.inner.adapter, &mut self.inner.objects) } pub fn standard_properties(&self) -> StandardProperties { - self.standard_properties + self.inner.standard_properties } pub fn handle_vt_event(&mut self, vt_event: VtEvent) { @@ -212,21 +185,29 @@ impl GraphicsScheme { // first time. This way the kernel graphical debug remains enabled if the // userspace logging infrastructure doesn't start up because for example a // kernel panic happened prior to it starting up or logd crashed. - if let Some(mut disable_graphical_debug) = self.disable_graphical_debug.take() { + if let Some(mut disable_graphical_debug) = self.inner.disable_graphical_debug.take() + { let _ = disable_graphical_debug.write(&[1]); } - self.active_vt = vt_event.vt; + self.inner.active_vt = vt_event.vt; - let vt_state = - Self::get_or_create_vt(&mut self.adapter, &mut self.vts, vt_event.vt); + let vt_state = GraphicsSchemeInner::get_or_create_vt( + &mut self.inner.adapter, + &mut self.inner.vts, + vt_event.vt, + ); for (display_id, fb) in vt_state.display_fbs.iter().enumerate() { - Self::update_whole_screen(&mut self.adapter, display_id, fb); + GraphicsSchemeInner::update_whole_screen( + &mut self.inner.adapter, + display_id, + fb, + ); } if let Some(cursor_plane) = &vt_state.cursor_plane { - self.adapter.handle_cursor(cursor_plane, true); + self.inner.adapter.handle_cursor(cursor_plane, true); } } @@ -246,7 +227,7 @@ impl GraphicsScheme { /// file. pub fn tick(&mut self) -> io::Result<()> { loop { - let request = match self.socket.next_request(SignalBehavior::Restart) { + let request = match self.inner.socket.next_request(SignalBehavior::Restart) { Ok(Some(request)) => request, Ok(None) => { // Scheme likely got unmounted @@ -258,13 +239,14 @@ impl GraphicsScheme { match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(self); - self.socket + let response = call.handle_sync(&mut self.inner, &mut self.state); + self.inner + .socket .write_response(response, SignalBehavior::Restart) .expect("driver-graphics: failed to write response"); } RequestKind::OnClose { id } => { - self.on_close(id); + self.inner.on_close(id); } _ => (), } @@ -272,20 +254,42 @@ impl GraphicsScheme { Ok(()) } +} - fn update_whole_screen(adapter: &mut T, screen: usize, framebuffer: &T::Framebuffer) { - adapter.update_plane( - screen, - framebuffer, - Damage { - x: 0, - y: 0, - width: framebuffer.width(), - height: framebuffer.height(), - }, - ); - } +struct GraphicsSchemeInner { + adapter: T, + scheme_name: String, + disable_graphical_debug: Option, + socket: Socket, + objects: DrmObjects, + standard_properties: StandardProperties, + next_id: usize, + handles: BTreeMap>, + + active_vt: usize, + vts: HashMap>, +} + +struct VtState { + display_fbs: Vec>, + cursor_plane: Option>, +} + +enum Handle { + V1Screen { + vt: usize, + screen: usize, + }, + V2 { + vt: usize, + next_id: u32, + fbs: HashMap>, + }, + SchemeRoot, +} + +impl GraphicsSchemeInner { fn get_or_create_vt<'a>( adapter: &mut T, vts: &'a mut HashMap>, @@ -312,11 +316,24 @@ impl GraphicsScheme { } }) } + + fn update_whole_screen(adapter: &mut T, screen: usize, framebuffer: &T::Framebuffer) { + adapter.update_plane( + screen, + framebuffer, + Damage { + x: 0, + y: 0, + width: framebuffer.width(), + height: framebuffer.height(), + }, + ); + } } const MAP_FAKE_OFFSET_MULTIPLIER: usize = 0x10_000_000; -impl SchemeSync for GraphicsScheme { +impl SchemeSync for GraphicsSchemeInner { fn scheme_root(&mut self) -> Result { let id = self.next_id; self.next_id += 1; @@ -927,7 +944,7 @@ impl SchemeSync for GraphicsScheme { } } -impl GraphicsScheme { +impl GraphicsSchemeInner { fn on_close(&mut self, id: usize) { self.handles.remove(&id); } diff --git a/drivers/graphics/fbbootlogd/src/main.rs b/drivers/graphics/fbbootlogd/src/main.rs index 78bf3e9cfa..2aa69bb56f 100644 --- a/drivers/graphics/fbbootlogd/src/main.rs +++ b/drivers/graphics/fbbootlogd/src/main.rs @@ -13,7 +13,7 @@ use event::EventQueue; use inputd::ConsumerHandleEvent; use libredox::errno::EAGAIN; use orbclient::Event; -use redox_scheme::{RequestKind, SignalBehavior, Socket}; +use redox_scheme::{scheme::SchemeState, RequestKind, SignalBehavior, Socket}; use crate::scheme::FbbootlogScheme; @@ -34,6 +34,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { let socket = Socket::nonblock().expect("fbbootlogd: failed to create fbbootlog scheme"); + let mut state = SchemeState::new(); let mut scheme = FbbootlogScheme::new(); event_queue @@ -90,7 +91,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) diff --git a/drivers/graphics/fbcond/src/main.rs b/drivers/graphics/fbcond/src/main.rs index fde9044242..eb4f9addb8 100644 --- a/drivers/graphics/fbcond/src/main.rs +++ b/drivers/graphics/fbcond/src/main.rs @@ -3,7 +3,7 @@ use inputd::ConsumerHandleEvent; use libredox::errno::{EAGAIN, EINTR}; use orbclient::Event; use redox_scheme::{ - scheme::{Op, SchemeResponse, SchemeSync}, + scheme::{Op, SchemeResponse, SchemeState, SchemeSync}, CallerCtx, RequestKind, Response, SignalBehavior, Socket, }; use std::env; @@ -44,6 +44,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { ) .expect("fbcond: failed to subscribe to scheme events"); + let mut state = SchemeState::new(); let mut scheme = FbconScheme::new(&vt_ids, &mut event_queue); let _ = daemon.ready_sync_scheme(&socket, &mut scheme); @@ -58,16 +59,23 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { handle_event( &mut socket, &mut scheme, + &mut state, &mut blocked, VtIndex::SCHEMA_SENTINEL, ); for vt_i in scheme.vts.keys().copied().collect::>() { - handle_event(&mut socket, &mut scheme, &mut blocked, vt_i); + handle_event(&mut socket, &mut scheme, &mut state, &mut blocked, vt_i); } for event in event_queue { let event = event.expect("fbcond: failed to read event from event queue"); - handle_event(&mut socket, &mut scheme, &mut blocked, event.user_data); + handle_event( + &mut socket, + &mut scheme, + &mut state, + &mut blocked, + event.user_data, + ); } std::process::exit(0); @@ -76,6 +84,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { fn handle_event( socket: &mut Socket, scheme: &mut FbconScheme, + state: &mut SchemeState, blocked: &mut Vec<(Op, CallerCtx)>, event: VtIndex, ) { @@ -108,7 +117,7 @@ fn handle_event( continue; } }; - match op.handle_sync_dont_consume(&caller, scheme) { + match op.handle_sync_dont_consume(&caller, scheme, state) { SchemeResponse::Opened(Err(e)) | SchemeResponse::Regular(Err(e)) if libredox::error::Error::from(e).is_wouldblock() && !op.is_explicitly_nonblock() => @@ -128,7 +137,15 @@ fn handle_event( ) .expect("fbcond: failed to write responses to fbcon scheme"); } - }; + SchemeResponse::RegularAndNotifyOnDetach(status) => { + let _ = socket + .write_response( + Response::new_notify_on_detach(status, op), + SignalBehavior::Restart, + ) + .expect("fbcond: failed to write scheme"); + } + } } RequestKind::OnClose { id } => { scheme.on_close(id); @@ -179,7 +196,7 @@ fn handle_event( let (op, caller) = blocked .get_mut(i) .expect("vesad: Failed to get blocked request"); - let resp = match op.handle_sync_dont_consume(&caller, scheme) { + let resp = match op.handle_sync_dont_consume(&caller, scheme, state) { SchemeResponse::Opened(Err(e)) | SchemeResponse::Regular(Err(e)) if libredox::error::Error::from(e).is_wouldblock() && !op.is_explicitly_nonblock() => @@ -195,6 +212,10 @@ fn handle_event( let (op, _) = blocked.remove(i); Response::open_dup_like(o, op) } + SchemeResponse::RegularAndNotifyOnDetach(status) => { + let (op, _) = blocked.remove(i); + Response::new_notify_on_detach(status, op) + } }; let _ = socket .write_response(resp, SignalBehavior::Restart) diff --git a/drivers/inputd/src/main.rs b/drivers/inputd/src/main.rs index ba572255e0..614b109224 100644 --- a/drivers/inputd/src/main.rs +++ b/drivers/inputd/src/main.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use inputd::{ControlEvent, VtEvent, VtEventKind}; use libredox::errno::ESTALE; -use redox_scheme::scheme::SchemeSync; +use redox_scheme::scheme::{SchemeState, SchemeSync}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket}; use orbclient::{Event, EventOption}; @@ -569,6 +569,7 @@ impl SchemeSync for InputScheme { fn deamon(daemon: daemon::SchemeDaemon) -> anyhow::Result<()> { // Create the ":input" scheme. let socket_file = Socket::create()?; + let mut state = SchemeState::new(); let mut scheme = InputScheme::new(); let _ = daemon.ready_sync_scheme(&socket_file, &mut scheme); @@ -583,7 +584,7 @@ fn deamon(daemon: daemon::SchemeDaemon) -> anyhow::Result<()> { match request.kind() { RequestKind::Call(call_request) => { socket_file.write_response( - call_request.handle_sync(&mut scheme), + call_request.handle_sync(&mut scheme, &mut state), SignalBehavior::Restart, )?; } diff --git a/drivers/net/driver-network/src/lib.rs b/drivers/net/driver-network/src/lib.rs index a4f5418907..894ecadd29 100644 --- a/drivers/net/driver-network/src/lib.rs +++ b/drivers/net/driver-network/src/lib.rs @@ -4,7 +4,7 @@ use std::{cmp, io}; use libredox::flag::O_NONBLOCK; use libredox::Fd; use redox_scheme::{ - scheme::{IntoTag, Op, SchemeResponse, SchemeSync}, + scheme::{IntoTag, Op, SchemeResponse, SchemeState, SchemeSync}, CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket, }; use syscall::schemev2::NewFdFlags; @@ -33,6 +33,7 @@ pub trait NetworkAdapter { pub struct NetworkScheme { scheme: NetworkSchemeInner, + state: SchemeState, blocked: Vec<(Op, CallerCtx)>, socket: Socket, } @@ -61,6 +62,7 @@ impl NetworkScheme { daemon.ready(); Self { scheme, + state: SchemeState::new(), blocked: Vec::new(), socket, } @@ -91,7 +93,7 @@ impl NetworkScheme { let mut i = 0; while i < self.blocked.len() { let (op, caller) = &mut self.blocked[i]; - let res = op.handle_sync_dont_consume(caller, &mut self.scheme); + let res = op.handle_sync_dont_consume(caller, &mut self.scheme, &mut self.state); match res { SchemeResponse::Opened(Err(Error { errno: syscall::EWOULDBLOCK, @@ -115,6 +117,16 @@ impl NetworkScheme { .write_response(Response::open_dup_like(o, op), SignalBehavior::Restart) .expect("driver-network: failed to write scheme"); } + SchemeResponse::RegularAndNotifyOnDetach(status) => { + let (op, _) = self.blocked.remove(i); + let _ = self + .socket + .write_response( + Response::new_notify_on_detach(status, op), + SignalBehavior::Restart, + ) + .expect("driver-network: failed to write scheme"); + } } } @@ -160,7 +172,8 @@ impl NetworkScheme { } }; - let resp = match op.handle_sync_dont_consume(&caller, &mut self.scheme) { + let resp = match op.handle_sync_dont_consume(&caller, &mut self.scheme, &mut self.state) + { SchemeResponse::Opened(Err(Error { errno: syscall::EWOULDBLOCK, })) @@ -172,6 +185,9 @@ impl NetworkScheme { } SchemeResponse::Regular(r) => Response::new(r, op), SchemeResponse::Opened(o) => Response::open_dup_like(o, op), + SchemeResponse::RegularAndNotifyOnDetach(status) => { + Response::new_notify_on_detach(status, op) + } }; let _ = self.socket.write_response(resp, SignalBehavior::Restart)?; } diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs index 5d8100f5da..ec0dd54bb6 100644 --- a/drivers/pcid/src/main.rs +++ b/drivers/pcid/src/main.rs @@ -10,7 +10,10 @@ use pci_types::{ Bar as TyBar, CommandRegister, EndpointHeader, HeaderType, PciAddress, PciHeader as TyPciHeader, PciPciBridgeHeader, }; -use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior}; +use redox_scheme::{ + scheme::{register_sync_scheme, SchemeState}, + RequestKind, SignalBehavior, +}; use crate::cfg_access::Pcie; use pcid_interface::{FullDeviceId, LegacyInterruptLine, PciBar, PciFunction, PciRom}; @@ -249,6 +252,7 @@ fn daemon(daemon: daemon::Daemon) -> ! { info!("PCI SG-BS:DV.F VEND:DEVI CL.SC.IN.RV"); + let mut state = SchemeState::new(); let mut scheme = scheme::PciScheme::new(pcie); let socket = redox_scheme::Socket::create().expect("failed to open pci scheme socket"); @@ -316,7 +320,7 @@ fn daemon(daemon: daemon::Daemon) -> ! { }; match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) diff --git a/drivers/storage/driver-block/src/lib.rs b/drivers/storage/driver-block/src/lib.rs index 35241f6eeb..b95071eee9 100644 --- a/drivers/storage/driver-block/src/lib.rs +++ b/drivers/storage/driver-block/src/lib.rs @@ -11,7 +11,7 @@ use std::task::Poll; use executor::LocalExecutor; use libredox::Fd; use partitionlib::{LogicalBlockSize, PartitionTable}; -use redox_scheme::scheme::{register_scheme_inner, SchemeAsync}; +use redox_scheme::scheme::{register_scheme_inner, SchemeAsync, SchemeState}; use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket}; use syscall::dirent::DirentBuf; use syscall::schemev2::NewFdFlags; @@ -254,6 +254,103 @@ impl DiskWrapper { } } +pub struct DiskScheme { + inner: DiskSchemeInner, + state: SchemeState, +} + +impl DiskScheme { + pub fn new( + daemon: Option, + scheme_name: String, + disks: BTreeMap, + executor: &impl ExecutorTrait, + ) -> Self { + assert!(scheme_name.starts_with("disk")); + let socket = Socket::nonblock().expect("failed to create disk scheme"); + + let mut inner = DiskSchemeInner { + scheme_name: scheme_name, + socket, + disks: disks + .into_iter() + .map(|(k, disk)| (k, DiskWrapper::new(disk, executor))) + .collect(), + next_id: 0, + handles: BTreeMap::new(), + }; + + let cap_id = inner.scheme_root().expect("failed to get this scheme root"); + register_scheme_inner(&inner.socket, &inner.scheme_name, cap_id) + .expect("failed to register disk scheme root"); + + if let Some(daemon) = daemon { + daemon.ready(); + } + + Self { + inner, + state: SchemeState::new(), + } + } + + pub fn event_handle(&self) -> &Fd { + self.inner.socket.inner() + } + + /// Process pending and new requests. + /// + /// This needs to be called each time there is a new event on the scheme. + pub async fn tick(&mut self) -> io::Result<()> { + // Handle new scheme requests + loop { + let request = match self.inner.socket.next_request(SignalBehavior::Interrupt) { + Ok(Some(request)) => request, + Ok(None) => { + // Scheme likely got unmounted + // TODO: return this to caller instead + std::process::exit(0); + } + Err(error) if error.errno == EWOULDBLOCK || error.errno == EAGAIN => break, + Err(err) if err.errno == EINTR => continue, + Err(err) => return Err(err.into()), + }; + + let response = match request.kind() { + RequestKind::Call(call_request) => { + // TODO: Spawn a separate task for each scheme call. This would however require the + // use of a smarter buffer pool (or direct IO, or a buffer per fd) in order to do + // parallel IO. It might also require async-aware locks so that a close() is + // correctly ordered wrt IO on the same fd. + call_request + .handle_async(&mut self.inner, &mut self.state) + .await + } + RequestKind::SendFd(request) => Response::err(EOPNOTSUPP, request), + RequestKind::RecvFd(request) => Response::err(EOPNOTSUPP, request), + RequestKind::Cancellation(_cancellation_request) => { + // FIXME implement cancellation + continue; + } + RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => { + unreachable!() + } + RequestKind::OnClose { id } => { + self.inner.on_close(id); + continue; + } + RequestKind::RecvFd(_) => continue, + RequestKind::OnDetach { .. } => continue, + }; + self.inner + .socket + .write_response(response, SignalBehavior::Restart)?; + } + + Ok(()) + } +} + enum Handle { List(Vec), // entries Disk(u32), // disk num @@ -261,7 +358,7 @@ enum Handle { SchemeRoot, } -pub struct DiskScheme { +struct DiskSchemeInner { scheme_name: String, socket: Socket, disks: BTreeMap>, @@ -303,92 +400,7 @@ impl ExecutorTrait for TrivialExecutor { } } -impl DiskScheme { - pub fn new( - daemon: Option, - scheme_name: String, - disks: BTreeMap, - executor: &impl ExecutorTrait, - ) -> Self { - assert!(scheme_name.starts_with("disk")); - let socket = Socket::nonblock().expect("failed to create disk scheme"); - - let mut scheme = Self { - scheme_name: scheme_name, - socket, - disks: disks - .into_iter() - .map(|(k, disk)| (k, DiskWrapper::new(disk, executor))) - .collect(), - next_id: 0, - handles: BTreeMap::new(), - }; - - let cap_id = scheme - .scheme_root() - .expect("failed to get this scheme root"); - register_scheme_inner(&scheme.socket, &scheme.scheme_name, cap_id) - .expect("failed to register disk scheme root"); - - if let Some(daemon) = daemon { - daemon.ready(); - } - - scheme - } - - pub fn event_handle(&self) -> &Fd { - self.socket.inner() - } - - /// Process pending and new requests. - /// - /// This needs to be called each time there is a new event on the scheme. - pub async fn tick(&mut self) -> io::Result<()> { - // Handle new scheme requests - loop { - let request = match self.socket.next_request(SignalBehavior::Interrupt) { - Ok(Some(request)) => request, - Ok(None) => { - // Scheme likely got unmounted - // TODO: return this to caller instead - std::process::exit(0); - } - Err(error) if error.errno == EWOULDBLOCK || error.errno == EAGAIN => break, - Err(err) if err.errno == EINTR => continue, - Err(err) => return Err(err.into()), - }; - - let response = match request.kind() { - RequestKind::Call(call_request) => { - // TODO: Spawn a separate task for each scheme call. This would however require the - // use of a smarter buffer pool (or direct IO, or a buffer per fd) in order to do - // parallel IO. It might also require async-aware locks so that a close() is - // correctly ordered wrt IO on the same fd. - call_request.handle_async(self).await - } - RequestKind::SendFd(request) => Response::err(EOPNOTSUPP, request), - RequestKind::RecvFd(request) => Response::err(EOPNOTSUPP, request), - RequestKind::Cancellation(_cancellation_request) => { - // FIXME implement cancellation - continue; - } - RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => { - unreachable!() - } - RequestKind::OnClose { id } => { - self.on_close(id); - continue; - } - RequestKind::RecvFd(_) => continue, - }; - self.socket - .write_response(response, SignalBehavior::Restart)?; - } - - Ok(()) - } - +impl DiskSchemeInner { // Checks if any conflicting handles already exist fn check_locks(&self, disk_i: u32, part_i_opt: Option) -> Result<()> { for (_, handle) in self.handles.iter() { @@ -419,7 +431,7 @@ impl DiskScheme { } } -impl SchemeAsync for DiskScheme { +impl SchemeAsync for DiskSchemeInner { fn scheme_root(&mut self) -> Result { let id = self.next_id; self.next_id += 1; @@ -683,7 +695,7 @@ impl SchemeAsync for DiskScheme { } } -impl DiskScheme { +impl DiskSchemeInner { pub fn on_close(&mut self, id: usize) { let _ = self.handles.remove(&id); } diff --git a/drivers/usb/xhcid/src/main.rs b/drivers/usb/xhcid/src/main.rs index 5c9c3c6090..25b2fdd673 100644 --- a/drivers/usb/xhcid/src/main.rs +++ b/drivers/usb/xhcid/src/main.rs @@ -37,7 +37,10 @@ use pcid_interface::irq_helpers::{ }; use pcid_interface::{PciFeature, PciFeatureInfo, PciFunctionHandle}; -use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior, Socket}; +use redox_scheme::{ + scheme::{register_sync_scheme, SchemeState}, + RequestKind, SignalBehavior, Socket, +}; use crate::xhci::{InterruptMethod, Xhci}; @@ -145,6 +148,7 @@ fn daemon_with_context_size( let scheme_name = format!("usb.{}", name); let socket = Socket::create().expect("xhcid: failed to create usb scheme"); + let mut state = SchemeState::new(); let hci = Arc::new( Xhci::::new(scheme_name.clone(), address, interrupt_method, pcid_handle) .expect("xhcid: failed to allocate device"), @@ -170,7 +174,7 @@ fn daemon_with_context_size( match request.kind() { RequestKind::Call(call_request) => { - let resp = call_request.handle_sync(&mut &*hci); + let resp = call_request.handle_sync(&mut &*hci, &mut state); socket .write_response(resp, SignalBehavior::Restart) .expect("xhcid: failed to write scheme"); diff --git a/drivers/usb/xhcid/src/xhci/scheme.rs b/drivers/usb/xhcid/src/xhci/scheme.rs index 9c9f3d6a1b..f2d439a450 100644 --- a/drivers/usb/xhcid/src/xhci/scheme.rs +++ b/drivers/usb/xhcid/src/xhci/scheme.rs @@ -33,8 +33,8 @@ use redox_scheme::{CallerCtx, OpenResult}; use syscall::schemev2::NewFdFlags; use syscall::{ Error, Result, Stat, EACCES, EBADF, EBADFD, EBADMSG, EINVAL, EIO, EISDIR, ENOENT, ENOSYS, - ENOTDIR, EPROTO, ESPIPE, MODE_CHR, MODE_DIR, MODE_FILE, O_DIRECTORY, O_RDWR, O_STAT, O_WRONLY, - SEEK_CUR, SEEK_END, SEEK_SET, + ENOTDIR, EOPNOTSUPP, EPROTO, ESPIPE, MODE_CHR, MODE_DIR, MODE_FILE, O_DIRECTORY, O_RDWR, + O_STAT, O_WRONLY, SEEK_CUR, SEEK_END, SEEK_SET, }; use super::{port, usb}; diff --git a/logd/src/main.rs b/logd/src/main.rs index 43c81e2707..b1db6d2beb 100644 --- a/logd/src/main.rs +++ b/logd/src/main.rs @@ -1,4 +1,7 @@ -use redox_scheme::{scheme::SchemeSync, RequestKind, Response, SignalBehavior, Socket}; +use redox_scheme::{ + scheme::{SchemeState, SchemeSync}, + RequestKind, Response, SignalBehavior, Socket, +}; use std::process; use crate::scheme::LogScheme; @@ -8,6 +11,7 @@ mod scheme; fn daemon(daemon: daemon::SchemeDaemon) -> ! { let socket = Socket::create().expect("logd: failed to create log scheme"); + let mut state = SchemeState::new(); let mut scheme = LogScheme::new(&socket); let _ = daemon.ready_sync_scheme(&socket, &mut scheme); @@ -35,7 +39,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { _ => continue, }; - let response = request.handle_sync(&mut scheme); + let response = request.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) .expect("logd: failed to write responses to log scheme"); diff --git a/netstack/src/scheme/mod.rs b/netstack/src/scheme/mod.rs index b59ac44f24..476daf2d34 100644 --- a/netstack/src/scheme/mod.rs +++ b/netstack/src/scheme/mod.rs @@ -8,7 +8,7 @@ use crate::scheme::socket::{Handle, SchemeSocket, SocketScheme}; use libredox::flag; use libredox::Fd; use redox_scheme::{ - scheme::{IntoTag, Op, SchemeResponse, SchemeSync}, + scheme::{IntoTag, Op, SchemeResponse, SchemeState, SchemeSync}, CallerCtx, RequestKind, Response, SignalBehavior, Socket, }; use smoltcp; @@ -316,6 +316,7 @@ where SocketT: SchemeSocket + AnySocket<'static>, { scheme: socket::SocketScheme, + state: SchemeState, wait_queue: WaitQueue, } impl SchemeWrapper @@ -334,6 +335,7 @@ where .map_err(|e| { Error::from_syscall_error(e, &format!("failed to initialize {} scheme", name)) })?, + state: SchemeState::new(), wait_queue: Vec::new(), }) } @@ -397,7 +399,8 @@ where continue; } }; - let resp = match op.handle_sync_dont_consume(&caller, &mut self.scheme) { + let resp = match op.handle_sync_dont_consume(&caller, &mut self.scheme, &mut self.state) + { SchemeResponse::Opened(Err(SyscallError { errno: syscall::EWOULDBLOCK, })) @@ -433,6 +436,9 @@ where } SchemeResponse::Regular(r) => Response::new(r, op), SchemeResponse::Opened(o) => Response::open_dup_like(o, op), + SchemeResponse::RegularAndNotifyOnDetach(status) => { + Response::new_notify_on_detach(status, op) + } }; let _ = self .scheme @@ -449,6 +455,7 @@ where // Notify non-blocking sockets let scheme = &mut self.scheme; + let state = &mut self.state; for (&fd, handle) in &mut scheme.handles { let Handle::File(file) = handle else { @@ -469,7 +476,7 @@ where while i < queue.len() { let handle = &mut queue[i]; let (op, caller) = &mut handle.packet; - let res = op.handle_sync_dont_consume(caller, scheme); + let res = op.handle_sync_dont_consume(caller, scheme, state); match res { SchemeResponse::Opened(Err(SyscallError { @@ -531,7 +538,19 @@ where Error::from_syscall_error(e.into(), "failed to write response") })?; } - }; + SchemeResponse::RegularAndNotifyOnDetach(status) => { + let (op, _) = queue.swap_remove(i).packet; + let _ = scheme + .scheme_file + .write_response( + Response::new_notify_on_detach(status, op), + SignalBehavior::Restart, + ) + .map_err(|e| { + Error::from_syscall_error(e.into(), "failed to write response") + })?; + } + } } Ok(()) diff --git a/netstack/src/scheme/netcfg/mod.rs b/netstack/src/scheme/netcfg/mod.rs index bef9318c21..150df71e72 100644 --- a/netstack/src/scheme/netcfg/mod.rs +++ b/netstack/src/scheme/netcfg/mod.rs @@ -3,8 +3,8 @@ mod nodes; mod notifier; use redox_scheme::{ - scheme::register_scheme_inner, scheme::SchemeSync, CallerCtx, OpenResult, RequestKind, - Response, SignalBehavior, Socket, + scheme::{register_scheme_inner, SchemeState, SchemeSync}, + CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket, }; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}; use std::cell::RefCell; @@ -325,17 +325,9 @@ impl NetCfgFile { } } -enum Handle { - SchemeRoot, - File(NetCfgFile), -} - pub struct NetCfgScheme { - scheme_file: Socket, - next_fd: usize, - handles: BTreeMap, - root_node: CfgNodeRef, - notifier: NotifierRef, + inner: NetCfgSchemeInner, + state: SchemeState, } impl NetCfgScheme { @@ -349,7 +341,7 @@ impl NetCfgScheme { let dns_config = Rc::new(RefCell::new(DNSConfig { name_server: Ipv4Address::new(8, 8, 8, 8), })); - let mut scheme = NetCfgScheme { + let mut inner = NetCfgSchemeInner { scheme_file, next_fd: 1, handles: BTreeMap::new(), @@ -362,18 +354,21 @@ impl NetCfgScheme { ), notifier, }; - let cap_id = scheme + let cap_id = inner .scheme_root() .map_err(|e| Error::from_syscall_error(e, "failed to get scheme root id"))?; - register_scheme_inner(&scheme.scheme_file, "netcfg", cap_id).map_err(|e| { + register_scheme_inner(&inner.scheme_file, "netcfg", cap_id).map_err(|e| { Error::from_syscall_error(e, "failed to register netcfg scheme to namespace") })?; - Ok(scheme) + Ok(Self { + inner, + state: SchemeState::new(), + }) } pub fn on_scheme_event(&mut self) -> Result> { let result = loop { - let request = match self.scheme_file.next_request(SignalBehavior::Restart) { + let request = match self.inner.scheme_file.next_request(SignalBehavior::Restart) { Ok(Some(req)) => req, Ok(None) => { break Some(()); @@ -394,7 +389,7 @@ impl NetCfgScheme { let req = match request.kind() { RequestKind::Call(c) => c, RequestKind::OnClose { id } => { - self.on_close(id); + self.inner.on_close(id); continue; } _ => { @@ -405,23 +400,39 @@ impl NetCfgScheme { let op = match req.op() { Ok(op) => op, Err(req) => { - self.scheme_file.write_response( + self.inner.scheme_file.write_response( Response::err(syscall::EOPNOTSUPP, req), SignalBehavior::Restart, ); continue; } }; - let resp = op.handle_sync(caller, self); + let resp = op.handle_sync(caller, &mut self.inner, &mut self.state); let _ = self + .inner .scheme_file .write_response(resp, SignalBehavior::Restart) .map_err(|e| Error::from_syscall_error(e.into(), "failed to write response"))?; }; - self.notify_scheduled_fds(); + self.inner.notify_scheduled_fds(); Ok(result) } +} +enum Handle { + SchemeRoot, + File(NetCfgFile), +} + +struct NetCfgSchemeInner { + scheme_file: Socket, + next_fd: usize, + handles: BTreeMap, + root_node: CfgNodeRef, + notifier: NotifierRef, +} + +impl NetCfgSchemeInner { fn notify_scheduled_fds(&mut self) { let fds_to_notify = self.notifier.borrow_mut().get_notified_fds(); for fd in fds_to_notify { @@ -430,7 +441,7 @@ impl NetCfgScheme { } } -impl SchemeSync for NetCfgScheme { +impl SchemeSync for NetCfgSchemeInner { fn scheme_root(&mut self) -> SyscallResult { let id = self.next_fd; self.next_fd += 1; diff --git a/ramfs/src/main.rs b/ramfs/src/main.rs index 1f10421948..51709fb588 100644 --- a/ramfs/src/main.rs +++ b/ramfs/src/main.rs @@ -3,7 +3,7 @@ use std::{env, process}; mod filesystem; mod scheme; -use redox_scheme::{RequestKind, SignalBehavior}; +use redox_scheme::{scheme::SchemeState, RequestKind, SignalBehavior}; use self::scheme::Scheme; @@ -16,6 +16,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { let socket = redox_scheme::Socket::create().expect("ramfs: failed to create socket"); + let mut state = SchemeState::new(); let mut scheme = Scheme::new(scheme_name.clone()).expect("ramfs: failed to initialize scheme"); let _ = daemon.ready_sync_scheme(&socket, &mut scheme); @@ -31,7 +32,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { }; match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) diff --git a/ramfs/src/scheme.rs b/ramfs/src/scheme.rs index 0b164062da..e73736055b 100644 --- a/ramfs/src/scheme.rs +++ b/ramfs/src/scheme.rs @@ -3,17 +3,19 @@ use std::convert::{TryFrom, TryInto}; use std::io::{Cursor, Seek}; use std::iter; use std::os::unix::io::AsRawFd; +use std::{mem, str}; use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; use syscall::error::{ EACCES, EBADF, EBADFD, EEXIST, EINVAL, EIO, EISDIR, ENOMEM, ENOSYS, ENOTDIR, ENOTEMPTY, - EOVERFLOW, + EOPNOTSUPP, EOVERFLOW, EPERM, }; use syscall::flag::{ - O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_STAT, O_TRUNC, O_WRONLY, + StdFsCallKind, O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_STAT, O_TRUNC, + O_WRONLY, }; use syscall::schemev2::NewFdFlags; -use syscall::{Error, EventFlags, Result, Stat, StatVfs, TimeSpec, ENOENT}; +use syscall::{Error, EventFlags, Result, Stat, StatVfs, StdFsCallMeta, TimeSpec, ENOENT}; use syscall::{MODE_DIR, MODE_FILE, MODE_PERM, MODE_TYPE}; use indexmap::IndexMap; @@ -36,6 +38,7 @@ pub struct Scheme { filesystem: Filesystem, handles: HashMap, next_id: usize, + proc_creds_capability: libredox::Fd, } impl Scheme { /// Create the scheme, with the name being used for `fpath`. @@ -45,6 +48,13 @@ impl Scheme { filesystem: Filesystem::new()?, handles: HashMap::new(), next_id: 0, + proc_creds_capability: { + libredox::Fd::open( + "/scheme/proc/proc-creds-capability", + libredox::flag::O_RDONLY, + 0, + )? + }, }) } /// Remove a directory entry, where the entry can be both a file or a directory. Used by `unlinkat`. @@ -641,6 +651,48 @@ impl SchemeSync for Scheme { Ok(()) } + + fn std_fs_call( + &mut self, + id: usize, + kind: StdFsCallKind, + payload: &mut [u8], + metadata: StdFsCallMeta, + ctx: &CallerCtx, + ) -> Result { + match kind { + StdFsCallKind::Fchown => { + let (new_uid, new_gid) = (metadata.arg1 as u32, metadata.arg1 >> 32 as u32); + let (_pid, uid, gid) = get_uid_gid_from_pid(&self.proc_creds_capability, ctx.pid)?; + if uid != 0 && (uid != ctx.uid || gid != ctx.gid) { + return Err(Error::new(EPERM)); + } + self.fchown(id, new_uid, new_gid as u32, ctx).map(|_| 0) + } + /* TODO: Support Unlinkat using std_fs_call + Unlinkat => { + let path = unsafe { str::from_utf8_unchecked(payload) }; + let flags = metadata.arg1; { + if !matches!( + self.handles.get(&id).ok_or(Error::new(EBADF))?, + Handle::SchemeRoot + ) { + return Err(Error::new(EACCES)); + } + } + let (_pid, uid, gid) = get_uid_gid_from_pid(&self.proc_creds_capability, ctx.pid)?; + self.remove_dentry( + path, + uid, + gid, + *flags as usize & syscall::AT_REMOVEDIR == syscall::AT_REMOVEDIR, + ) + .map(|_| 0) + } + */ + _ => Err(Error::new(EOPNOTSUPP)), + } + } } impl Scheme { pub fn on_close(&mut self, fd: usize) { @@ -682,3 +734,32 @@ fn check_permissions(flags: usize, single_mode: u8) -> Result<()> { } Ok(()) } + +fn get_uid_gid_from_pid(cap_fd: &libredox::Fd, target_pid: usize) -> Result<(u32, u32, u32)> { + let mut buffer = [0u8; mem::size_of::()]; + let _ = libredox::call::get_proc_credentials(cap_fd.raw(), target_pid, &mut buffer).map_err( + |e| { + eprintln!( + "Failed to get process credentials for pid {}: {:?}", + target_pid, e + ); + Error::new(EINVAL) + }, + )?; + let mut cursor = 0; + let pid = read_u32(&buffer, cursor)?; + cursor += mem::size_of::() * 3; + let uid = read_u32(&buffer, cursor)?; + cursor += mem::size_of::() * 3; + let gid = read_u32(&buffer, cursor)?; + Ok((pid, uid, gid)) +} + +fn read_u32(buffer: &[u8], offset: usize) -> Result { + let bytes = buffer + .get(offset..offset + 4) + .and_then(|slice| slice.try_into().ok()) + .ok_or_else(|| Error::new(EINVAL))?; + + Ok(u32::from_le_bytes(bytes)) +} diff --git a/randd/src/main.rs b/randd/src/main.rs index c5fda18122..0abd73b634 100644 --- a/randd/src/main.rs +++ b/randd/src/main.rs @@ -14,7 +14,8 @@ pub const MODE_READ: u16 = 0o4; use raw_cpuid::CpuId; use redox_scheme::{ - scheme::SchemeSync, CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket, + scheme::{SchemeState, SchemeSync}, + CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket, }; use syscall::data::Stat; use syscall::flag::{EventFlags, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_WRONLY}; @@ -467,6 +468,7 @@ impl SchemeSync for RandScheme { fn daemon(daemon: daemon::SchemeDaemon) -> ! { let socket = Socket::create().expect("randd: failed to create rand scheme"); + let mut state = SchemeState::new(); let mut scheme = RandScheme::new(); let _ = daemon.ready_sync_scheme(&socket, &mut scheme); @@ -479,7 +481,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { { match request.kind() { RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme); + let response = call.handle_sync(&mut scheme, &mut state); socket .write_response(response, SignalBehavior::Restart) .expect("error writing packet"); diff --git a/zerod/src/main.rs b/zerod/src/main.rs index bde902d892..dcfb58970f 100644 --- a/zerod/src/main.rs +++ b/zerod/src/main.rs @@ -1,4 +1,4 @@ -use redox_scheme::{RequestKind, SignalBehavior, Socket}; +use redox_scheme::{scheme::SchemeState, RequestKind, SignalBehavior, Socket}; use scheme::ZeroScheme; @@ -21,6 +21,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { }; let socket = Socket::create().expect("zerod: failed to create zero scheme"); + let mut state = SchemeState::new(); let mut zero_scheme = ZeroScheme(ty); let _ = daemon.ready_sync_scheme(&socket, &mut zero_scheme); @@ -36,7 +37,7 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! { }; match request.kind() { RequestKind::Call(request) => { - let response = request.handle_sync(&mut zero_scheme); + let response = request.handle_sync(&mut zero_scheme, &mut state); socket .write_response(response, SignalBehavior::Restart)