diff --git a/Cargo.toml b/Cargo.toml index 8c7370749d..b7b2b3366f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["staticlib"] [dependencies] hashbrown = { version = "0.14", default-features = false, features = [ "inline-more", + "ahash", ] } linked_list_allocator = "0.10" redox-initfs = { git = "https://gitlab.redox-os.org/redox-os/redox-initfs.git", default-features = false } @@ -20,6 +21,7 @@ redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } #redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc", default-features = false } redox-rt = { git = "https://gitlab.redox-os.org/4lDO2/relibc.git", branch = "userspace_proc", default-features = false } redox-path = "0.3.1" +slab = { version = "0.4.9", default-features = false } [profile.release] panic = "abort" diff --git a/src/aarch64.rs b/src/aarch64.rs index 56aecc3ee5..6e1a732175 100644 --- a/src/aarch64.rs +++ b/src/aarch64.rs @@ -1,9 +1,5 @@ use core::mem; -use syscall::{ - data::Map, - flag::MapFlags, - number::SYS_FMAP, -}; +use syscall::{data::Map, flag::MapFlags, number::SYS_FMAP}; pub const USERMODE_END: usize = 0x0000_8000_0000_0000; pub const STACK_START: usize = USERMODE_END - STACK_SIZE; @@ -13,9 +9,9 @@ static MAP: Map = Map { offset: 0, size: STACK_SIZE, flags: MapFlags::PROT_READ - .union(MapFlags::PROT_WRITE) - .union(MapFlags::MAP_PRIVATE) - .union(MapFlags::MAP_FIXED_NOREPLACE), + .union(MapFlags::PROT_WRITE) + .union(MapFlags::MAP_PRIVATE) + .union(MapFlags::MAP_FIXED_NOREPLACE), address: STACK_START, // highest possible user address }; diff --git a/src/exec.rs b/src/exec.rs index b9ba4d51e2..9d6f491a0e 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -49,7 +49,9 @@ pub fn main() -> ! { ); }); - spawn("process manager", move |write_fd| crate::procmngr::run(write_fd)); + spawn("process manager", move |write_fd| { + crate::procmngr::run(write_fd) + }); const CWD: &[u8] = b"/scheme/initfs"; const DEFAULT_SCHEME: &[u8] = b"initfs"; @@ -73,12 +75,13 @@ pub fn main() -> ! { let image_file = FdGuard::new(syscall::open(path, O_RDONLY).expect("failed to open init")); let open_via_dup = FdGuard::new( - syscall::open("/scheme/thisproc/current", 0) - .expect("failed to open open_via_dup"), + syscall::open("/scheme/thisproc/current", 0).expect("failed to open open_via_dup"), ); let memory = FdGuard::new(syscall::open("/scheme/memory", 0).expect("failed to open memory")); - redox_rt::proc::make_init(); + unsafe { + redox_rt::proc::make_init(); + } fexec_impl( image_file, diff --git a/src/initfs.rs b/src/initfs.rs index ee7ccb10d1..7568b15e9f 100644 --- a/src/initfs.rs +++ b/src/initfs.rs @@ -9,14 +9,9 @@ use hashbrown::HashMap; use redox_initfs::{types::Timespec, InitFs, Inode, InodeDir, InodeKind, InodeStruct}; use redox_path::canonicalize_to_standard; -use redox_scheme::CallerCtx; -use redox_scheme::OpenResult; -use redox_scheme::RequestKind; -use redox_scheme::SchemeMut; +use redox_scheme::{CallerCtx, OpenResult, RequestKind, Scheme}; -use redox_scheme::SignalBehavior; -use redox_scheme::Socket; -use redox_scheme::V2; +use redox_scheme::{SignalBehavior, Socket}; use syscall::data::Stat; use syscall::dirent::DirEntry; use syscall::dirent::DirentBuf; @@ -93,7 +88,7 @@ fn inode_len(inode: InodeStruct<'static>) -> Result { }) } -impl SchemeMut for InitFsScheme { +impl Scheme for InitFsScheme { fn xopen(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result { let mut components = path // trim leading and trailing slash @@ -317,7 +312,7 @@ impl SchemeMut for InitFsScheme { pub fn run(bytes: &'static [u8], sync_pipe: usize) -> ! { let mut scheme = InitFsScheme::new(bytes); - let socket = Socket::::create("initfs").expect("failed to open initfs scheme socket"); + let socket = Socket::create("initfs").expect("failed to open initfs scheme socket"); let _ = syscall::write(sync_pipe, &[0]); let _ = syscall::close(sync_pipe); @@ -332,7 +327,7 @@ pub fn run(bytes: &'static [u8], sync_pipe: usize) -> ! { }) else { continue; }; - let resp = req.handle_scheme_mut(&mut scheme); + let resp = req.handle_scheme(&mut scheme); if !socket .write_response(resp, SignalBehavior::Restart) diff --git a/src/procmngr.rs b/src/procmngr.rs index b70defe239..01b67dc3cc 100644 --- a/src/procmngr.rs +++ b/src/procmngr.rs @@ -1,14 +1,21 @@ use core::cell::RefCell; use alloc::rc::Rc; +use alloc::vec::Vec; +use alloc::vec; + use hashbrown::hash_map::DefaultHashBuilder; use hashbrown::{HashMap, HashSet}; use redox_rt::proc::FdGuard; -use redox_scheme::{CallerCtx, OpenResult, RequestKind, SchemeMut, SignalBehavior, Socket, V2}; -use syscall::{Result, O_CREAT}; +use redox_scheme::{ + CallerCtx, OpenResult, RequestKind, Response, Scheme, SendFdRequest, SignalBehavior, Socket, +}; +use slab::Slab; +use syscall::schemev2::NewFdFlags; +use syscall::{Error, FobtainFdFlags, Result, EBADF, EBADFD, EEXIST, EINVAL, ENOENT, O_CREAT}; pub fn run(write_fd: usize) { - let socket = Socket::::create("proc").expect("failed to open proc scheme socket"); + let socket = Socket::create("proc").expect("failed to open proc scheme socket"); let mut scheme = ProcScheme::new(); let _ = syscall::write(1, b"process manager started\n").unwrap(); @@ -16,16 +23,17 @@ pub fn run(write_fd: usize) { let _ = syscall::close(write_fd); loop { - let RequestKind::Call(req) = (match socket + let Some(req) = socket .next_request(SignalBehavior::Restart) .expect("bootstrap: failed to read scheme request from kernel") - { - Some(req) => req.kind(), - None => break, - }) else { + else { continue; }; - let resp = req.handle_scheme_mut(&mut scheme); + let resp = match req.kind() { + RequestKind::Call(req) => req.handle_scheme(&mut scheme), + RequestKind::SendFd(req) => scheme.on_sendfd(&socket, &req), + _ => continue, + }; if !socket .write_response(resp, SignalBehavior::Restart) @@ -43,6 +51,13 @@ struct Process { ppid: ProcessId, pgid: ProcessId, sid: ProcessId, + + ruid: u32, + euid: u32, + rgid: u32, + egid: u32, + rns: u32, + ens: u32, } struct Thread { fd: FdGuard, @@ -51,22 +66,142 @@ struct Thread { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct ProcessId(usize); +const INIT_PID: ProcessId = ProcessId(1); + struct ProcScheme { processes: HashMap, process_groups: HashSet, sessions: HashSet, + handles: Slab, + + init_claimed: bool, + next_id: ProcessId, } + +enum Handle { + Init, + Proc(ProcessId), +} + impl ProcScheme { pub fn new() -> ProcScheme { ProcScheme { processes: HashMap::new(), process_groups: HashSet::new(), sessions: HashSet::new(), + handles: Slab::new(), + init_claimed: false, + next_id: ProcessId(2), + } + } + fn new_id(&mut self) -> ProcessId { + let id = self.next_id; + self.next_id.0 += 1; + id + } + fn on_sendfd(&mut self, socket: &Socket, req: &SendFdRequest) -> Response { + match self.handles[req.id()] { + ref mut st @ Handle::Init => { + let mut fd_out = usize::MAX; + if let Err(e) = req.obtain_fd(socket, FobtainFdFlags::empty(), Err(&mut fd_out)) { + return Response::for_sendfd(&req, Err(e)); + }; + let thread = Rc::new(RefCell::new(Thread { + fd: FdGuard::new(fd_out), + })); + self.processes.insert( + INIT_PID, + Process { + threads: vec![thread], + ppid: INIT_PID, + sid: INIT_PID, + pgid: INIT_PID, + ruid: 0, + euid: 0, + rgid: 0, + egid: 0, + rns: 1, + ens: 1, + }, + ); + self.process_groups.insert(INIT_PID); + self.sessions.insert(INIT_PID); + + *st = Handle::Proc(INIT_PID); + Response::for_sendfd(&req, Ok(0)) + } + _ => Response::for_sendfd(&req, Err(Error::new(EBADF))), + } + } + fn fork(&mut self, parent_pid: ProcessId) -> Result { + let child_pid = self.new_id(); + + let Process { + pgid, + sid, + euid, + ruid, + egid, + rgid, + ens, + rns, + .. + } = *self.processes.get(&parent_pid).ok_or(Error::new(EBADFD))?; + + self.processes.insert( + child_pid, + Process { + threads: Vec::new(), + ppid: parent_pid, + pgid, + sid, + ruid, + rgid, + euid, + egid, + rns, + ens, + }, + ); + Ok(child_pid) + } + fn new_thread(&mut self, pid: ProcessId) -> Result { + let proc = self.processes.get_mut(&pid).ok_or(Error::new(EBADFD))?; + proc.threads + .push(Rc::new(RefCell::new(Thread { fd: todo!() }))); + } +} +impl Scheme for ProcScheme { + fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result { + if path == "init" { + if core::mem::replace(&mut self.init_claimed, true) { + return Err(Error::new(EEXIST)); + } + return Ok(OpenResult::ThisScheme { + number: self + .handles + .insert(Handle::Init), + flags: NewFdFlags::empty(), + }); + } + Err(Error::new(ENOENT)) + } + fn xdup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result { + match self.handles[old_id] { + Handle::Proc(pid) => match buf { + b"fork" => { + let child_pid = self.fork(pid)?; + Ok(OpenResult::ThisScheme { + number: self.handles.insert(Handle::Proc(child_pid)), + flags: NewFdFlags::empty(), + }) + }, + b"new-thread" => Ok(OpenResult::OtherScheme { + fd: self.new_thread(pid)?.take(), + }), + _ => return Err(Error::new(EINVAL)), + }, + Handle::Init => Err(Error::new(EBADF)), } } } -impl SchemeMut for ProcScheme { - fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result { - - } -}