From fe3f09133d5bb1cf12417b38d9a31347e36d866e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:58:46 +0100 Subject: [PATCH 1/6] bootstrap: Use FdGuard for scheme_creation_cap --- bootstrap/src/exec.rs | 33 +++++++++++++++++++-------------- bootstrap/src/initfs.rs | 6 +++--- bootstrap/src/initnsmgr.rs | 6 +++--- bootstrap/src/procmgr.rs | 8 ++++---- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index 4e417f9e66..4fa78014c0 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::CallFlags; -use syscall::{Error, EINTR}; +use syscall::{EINTR, Error}; use redox_rt::proc::*; @@ -49,8 +49,7 @@ pub fn main() -> ! { }; let scheme_creation_cap = unsafe { let base_ptr = cursor as *const u8; - let cap = *(base_ptr as *const usize); - cap + FdGuard::new(*(base_ptr as *const usize)) }; let kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos); @@ -126,12 +125,13 @@ pub fn main() -> ! { (*(core::ptr::addr_of!(__initfs_header) as *const redox_initfs::types::Header)).initfs_size }; - let initfs_fd = spawn( + let (scheme_creation_cap, initfs_fd) = spawn( "initfs daemon", &auth, &this_thr_fd, + scheme_creation_cap, pipe_fd, - |write_fd| unsafe { + |write_fd, scheme_creation_cap| unsafe { // Creating a reference to NULL is UB. Mask the UB for now using black_box. // FIXME use a raw pointer and inline asm for reading instead for the initfs header. let initfs_start = core::ptr::addr_of!(__initfs_header); @@ -146,20 +146,24 @@ pub fn main() -> ! { }, ); - let proc_fd = spawn( + let (scheme_creation_cap, proc_fd) = spawn( "process manager", &auth, &this_thr_fd, + scheme_creation_cap, pipe_fd, - |write_fd| crate::procmgr::run(write_fd, &auth, &kernel_schemes, scheme_creation_cap), + |write_fd, scheme_creation_cap| { + crate::procmgr::run(write_fd, &auth, &kernel_schemes, scheme_creation_cap) + }, ); - let initns_fd = spawn( + let (_, initns_fd) = spawn( "init namespace manager", &auth, &this_thr_fd, + scheme_creation_cap, pipe_fd, - move |write_fd| { + move |write_fd, scheme_creation_cap| { let mut schemes = HashMap::default(); for (scheme, fd) in kernel_schemes.0.into_iter() { schemes.insert(scheme.as_str().to_string(), Arc::new(FdGuard::new(fd))); @@ -249,9 +253,10 @@ pub(crate) fn spawn( name: &str, auth: &FdGuard, this_thr_fd: &FdGuardUpper, + scheme_creation_cap: FdGuard, pipe_fd: usize, - inner: impl FnOnce(FdGuard) -> !, -) -> usize { + inner: impl FnOnce(FdGuard, FdGuard) -> !, +) -> (FdGuard, usize) { let read = FdGuard::new( syscall::openat(pipe_fd, "", O_CLOEXEC, 0).expect("failed to open sync read pipe"), ); @@ -292,8 +297,8 @@ pub(crate) fn spawn( } } - return new_fd; + return (scheme_creation_cap, new_fd); } } - inner(write) + inner(write, scheme_creation_cap) } diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 9340cc2dc2..8ec23d52e5 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -388,15 +388,15 @@ pub fn run( bytes: &'static [u8], sync_pipe: FdGuard, kernel_schemes: &KernelSchemeMap, - scheme_creation_cap: usize, + scheme_creation_cap: FdGuard, ) -> ! { 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) + let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), false) .expect("failed to open initfs scheme socket"); - let _ = syscall::close(scheme_creation_cap); + drop(scheme_creation_cap); for fd in kernel_schemes.0.values() { let _ = syscall::close(*fd); diff --git a/bootstrap/src/initnsmgr.rs b/bootstrap/src/initnsmgr.rs index 103a5a2d2f..f73af73521 100644 --- a/bootstrap/src/initnsmgr.rs +++ b/bootstrap/src/initnsmgr.rs @@ -490,13 +490,13 @@ where pub fn run( sync_pipe: FdGuard, schemes: HashMap>, - scheme_creation_cap: usize, + scheme_creation_cap: FdGuard, ) -> ! { - let socket = Socket::create_inner(scheme_creation_cap, false) + let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), 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)); + let mut scheme = NamespaceScheme::new(&socket, schemes, scheme_creation_cap); // send namespace fd to bootstrap let new_id = scheme.next_id; diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index aa7121ab15..ec3dad9f58 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -52,11 +52,11 @@ pub fn run( write_fd: FdGuard, auth: &FdGuard, kernel_schemes: &KernelSchemeMap, - scheme_creation_cap: usize, + scheme_creation_cap: FdGuard, ) -> ! { - let socket = - Socket::create_inner(scheme_creation_cap, true).expect("failed to open proc scheme socket"); - let _ = syscall::close(scheme_creation_cap); + let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), true) + .expect("failed to open proc scheme socket"); + drop(scheme_creation_cap); // TODO? let socket_ident = socket.inner().raw(); From 0d957f8d2038b94612d09210b03789ad3f8f4f67 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:13:24 +0100 Subject: [PATCH 2/6] bootstrap: Return FdGuard for the scheme root in spawn --- bootstrap/src/exec.rs | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index 4fa78014c0..e99f767c54 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -163,26 +163,33 @@ pub fn main() -> ! { &this_thr_fd, scheme_creation_cap, pipe_fd, - move |write_fd, scheme_creation_cap| { + |write_fd, scheme_creation_cap| { let mut schemes = HashMap::default(); for (scheme, fd) in kernel_schemes.0.into_iter() { schemes.insert(scheme.as_str().to_string(), Arc::new(FdGuard::new(fd))); } - schemes.insert("proc".to_string(), Arc::new(FdGuard::new(proc_fd))); - schemes.insert("initfs".to_string(), Arc::new(FdGuard::new(initfs_fd))); + schemes.insert( + "proc".to_string(), + // A bit dirty, but necessary as the parent process still needs access to it. Rust + // doesn't know that the fd got cloned by fork. + Arc::new(FdGuard::new(proc_fd.as_raw_fd())), + ); + schemes.insert("initfs".to_string(), Arc::new(initfs_fd)); crate::initnsmgr::run(write_fd, schemes, scheme_creation_cap) }, ); - let (init_proc_fd, init_thr_fd) = unsafe { make_init(proc_fd) }; + let (init_proc_fd, init_thr_fd) = unsafe { make_init(proc_fd.take()) }; // from this point, this_thr_fd is no longer valid const CWD: &[u8] = b"/scheme/initfs"; - let cwd_fd = - FdGuard::new(syscall::openat(initfs_fd, "", O_STAT, 0).expect("failed to open cwd fd")) - .to_upper() - .unwrap(); + let cwd_fd = FdGuard::new( + syscall::openat(initns_fd.as_raw_fd(), "/scheme/initfs", O_STAT, 0) + .expect("failed to open cwd fd"), + ) + .to_upper() + .unwrap(); let extrainfo = ExtraInfo { cwd: Some(CWD), sigprocmask: 0, @@ -190,14 +197,15 @@ pub fn main() -> ! { umask: redox_rt::sys::get_umask(), thr_fd: init_thr_fd.as_raw_fd(), proc_fd: init_proc_fd.as_raw_fd(), - ns_fd: Some(initns_fd), + ns_fd: Some(initns_fd.take()), cwd_fd: Some(cwd_fd.as_raw_fd()), }; - let path = "/bin/init"; + let path = "/scheme/initfs/bin/init"; let image_file = FdGuard::new( - syscall::openat(initfs_fd, path, O_RDONLY | O_CLOEXEC, 0).expect("failed to open init"), + syscall::openat(extrainfo.ns_fd.unwrap(), path, O_RDONLY | O_CLOEXEC, 0) + .expect("failed to open init"), ) .to_upper() .unwrap(); @@ -224,7 +232,7 @@ pub fn main() -> ! { let interp_cstr = CStr::from_bytes_with_nul(&interp_path).expect("interpreter not valid C str"); let interp_file = FdGuard::new( syscall::openat( - initns_fd, // initns, not initfs! + extrainfo.ns_fd.unwrap(), // initns, not initfs! interp_cstr.to_str().expect("interpreter not UTF-8"), O_RDONLY | O_CLOEXEC, 0, @@ -256,7 +264,7 @@ pub(crate) fn spawn( scheme_creation_cap: FdGuard, pipe_fd: usize, inner: impl FnOnce(FdGuard, FdGuard) -> !, -) -> (FdGuard, usize) { +) -> (FdGuard, FdGuard) { let read = FdGuard::new( syscall::openat(pipe_fd, "", O_CLOEXEC, 0).expect("failed to open sync read pipe"), ); @@ -297,7 +305,7 @@ pub(crate) fn spawn( } } - return (scheme_creation_cap, new_fd); + return (scheme_creation_cap, FdGuard::new(new_fd)); } } inner(write, scheme_creation_cap) From b641ed37412298518be556dc1c336c08a7bb5fc8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 21:55:30 +0100 Subject: [PATCH 3/6] bootstrap: Pass proc auth FdGuard by-value --- bootstrap/src/exec.rs | 43 ++++++++++++++++++++++------------------ bootstrap/src/procmgr.rs | 17 +++++++--------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index e99f767c54..a8c0070627 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -52,11 +52,12 @@ pub fn main() -> ! { FdGuard::new(*(base_ptr as *const usize)) }; - let kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos); + let mut kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos); let auth = FdGuard::new( - *kernel_schemes - .get(GlobalSchemes::Proc) + kernel_schemes + .0 + .remove(&GlobalSchemes::Proc) .expect("failed to get proc fd"), ); let pipe_fd = *kernel_schemes @@ -125,13 +126,13 @@ pub fn main() -> ! { (*(core::ptr::addr_of!(__initfs_header) as *const redox_initfs::types::Header)).initfs_size }; - let (scheme_creation_cap, initfs_fd) = spawn( + let (scheme_creation_cap, auth, initfs_fd) = spawn( "initfs daemon", - &auth, + auth, &this_thr_fd, scheme_creation_cap, pipe_fd, - |write_fd, scheme_creation_cap| unsafe { + |write_fd, scheme_creation_cap, _| unsafe { // Creating a reference to NULL is UB. Mask the UB for now using black_box. // FIXME use a raw pointer and inline asm for reading instead for the initfs header. let initfs_start = core::ptr::addr_of!(__initfs_header); @@ -146,24 +147,24 @@ pub fn main() -> ! { }, ); - let (scheme_creation_cap, proc_fd) = spawn( + let (scheme_creation_cap, auth, proc_fd) = spawn( "process manager", - &auth, + auth, &this_thr_fd, scheme_creation_cap, pipe_fd, - |write_fd, scheme_creation_cap| { - crate::procmgr::run(write_fd, &auth, &kernel_schemes, scheme_creation_cap) + |write_fd, scheme_creation_cap, auth| { + crate::procmgr::run(write_fd, auth, &kernel_schemes, scheme_creation_cap) }, ); - let (_, initns_fd) = spawn( + let (_, _, initns_fd) = spawn( "init namespace manager", - &auth, + auth, &this_thr_fd, scheme_creation_cap, pipe_fd, - |write_fd, scheme_creation_cap| { + |write_fd, scheme_creation_cap, _| { let mut schemes = HashMap::default(); for (scheme, fd) in kernel_schemes.0.into_iter() { schemes.insert(scheme.as_str().to_string(), Arc::new(FdGuard::new(fd))); @@ -259,12 +260,12 @@ pub fn main() -> ! { pub(crate) fn spawn( name: &str, - auth: &FdGuard, + auth: FdGuard, this_thr_fd: &FdGuardUpper, scheme_creation_cap: FdGuard, pipe_fd: usize, - inner: impl FnOnce(FdGuard, FdGuard) -> !, -) -> (FdGuard, FdGuard) { + inner: impl FnOnce(FdGuard, FdGuard, FdGuard) -> !, +) -> (FdGuard, FdGuard, FdGuard) { let read = FdGuard::new( syscall::openat(pipe_fd, "", O_CLOEXEC, 0).expect("failed to open sync read pipe"), ); @@ -274,13 +275,18 @@ pub(crate) fn spawn( syscall::dup(read.as_raw_fd(), b"write").expect("failed to open sync write pipe"), ); - match fork_impl(&ForkArgs::Init { this_thr_fd, auth }) { + match fork_impl(&ForkArgs::Init { + this_thr_fd, + auth: &auth, + }) { Err(err) => { panic!("Failed to fork in order to start {name}: {err}"); } // Continue serving the scheme as the child. Ok(0) => { drop(read); + + inner(write, scheme_creation_cap, auth) } // Return in order to execute init, as the parent. Ok(_) => { @@ -305,8 +311,7 @@ pub(crate) fn spawn( } } - return (scheme_creation_cap, FdGuard::new(new_fd)); + (scheme_creation_cap, auth, FdGuard::new(new_fd)) } } - inner(write, scheme_creation_cap) } diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index ec3dad9f58..70b63bac4d 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -50,7 +50,7 @@ enum VirtualId { pub fn run( write_fd: FdGuard, - auth: &FdGuard, + auth: FdGuard, kernel_schemes: &KernelSchemeMap, scheme_creation_cap: FdGuard, ) -> ! { @@ -67,10 +67,7 @@ pub fn run( .expect("failed to get event fd"), ) .expect("failed to create event queue"); - for (scheme, fd) in kernel_schemes.0.iter() { - if *scheme == GlobalSchemes::Proc { - continue; - } + for fd in kernel_schemes.0.values() { let _ = syscall::close(*fd); } @@ -520,7 +517,7 @@ struct ProcScheme<'a> { next_id: ProcessId, queue: &'a RawEventQueue, - auth: &'a FdGuard, + auth: FdGuard, } #[derive(Debug, Default)] struct Pgrp { @@ -598,7 +595,7 @@ impl RawEventQueue { } impl<'a> ProcScheme<'a> { - pub fn new(auth: &'a FdGuard, queue: &'a RawEventQueue) -> ProcScheme<'a> { + pub fn new(auth: FdGuard, queue: &'a RawEventQueue) -> ProcScheme<'a> { ProcScheme { processes: HashMap::new(), groups: HashMap::new(), @@ -745,7 +742,7 @@ impl<'a> ProcScheme<'a> { })); if let Err(err) = new_process .borrow_mut() - .sync_kernel_attrs(child_pid, self.auth) + .sync_kernel_attrs(child_pid, &self.auth) { log::warn!("Failed to set kernel attrs when forking: {err}"); } @@ -1611,7 +1608,7 @@ impl<'a> ProcScheme<'a> { if let Some(new_sgid) = new_sgid { proc.sgid = new_sgid; } - if let Err(err) = proc.sync_kernel_attrs(pid, self.auth) { + if let Err(err) = proc.sync_kernel_attrs(pid, &self.auth) { log::warn!("Failed to sync proc attrs in setresugid: {err}"); } Ok(()) @@ -2393,7 +2390,7 @@ impl<'a> ProcScheme<'a> { .borrow_mut(); proc.name = ArrayString::from_str(&new_name[..new_name.len().min(NAME_CAPAC)]).unwrap(); - if let Err(err) = proc.sync_kernel_attrs(pid, self.auth) { + if let Err(err) = proc.sync_kernel_attrs(pid, &self.auth) { log::warn!("Failed to set kernel attrs when renaming proc: {err}"); } Ok(()) From 890f3253682cf2947a894f4764ed7547a58990ed Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:10:49 +0100 Subject: [PATCH 4/6] bootstrap: Store FdGuard's in KernelSchemeMap --- bootstrap/src/exec.rs | 67 +++++++++++++++++++++++----------------- bootstrap/src/initfs.rs | 13 +------- bootstrap/src/lib.rs | 7 +++-- bootstrap/src/procmgr.rs | 11 +++---- 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index a8c0070627..03678ac5bc 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -54,15 +54,10 @@ pub fn main() -> ! { let mut kernel_schemes = KernelSchemeMap::new(kernel_scheme_infos); - let auth = FdGuard::new( - kernel_schemes - .0 - .remove(&GlobalSchemes::Proc) - .expect("failed to get proc fd"), - ); - let pipe_fd = *kernel_schemes - .get(GlobalSchemes::Pipe) - .expect("failed to get pipe fd"); + let auth = kernel_schemes + .0 + .remove(&GlobalSchemes::Proc) + .expect("failed to get proc fd"); let this_thr_fd = auth .dup(b"cur-context") @@ -75,9 +70,10 @@ pub fn main() -> ! { let mut envs = { let fd = FdGuard::new( syscall::openat( - *kernel_schemes + kernel_schemes .get(GlobalSchemes::Sys) - .expect("failed to get sys fd"), + .expect("failed to get sys fd") + .as_raw_fd(), "env", O_RDONLY | O_CLOEXEC, 0, @@ -126,13 +122,13 @@ pub fn main() -> ! { (*(core::ptr::addr_of!(__initfs_header) as *const redox_initfs::types::Header)).initfs_size }; - let (scheme_creation_cap, auth, initfs_fd) = spawn( + let (scheme_creation_cap, auth, kernel_schemes, initfs_fd) = spawn( "initfs daemon", auth, &this_thr_fd, scheme_creation_cap, - pipe_fd, - |write_fd, scheme_creation_cap, _| unsafe { + kernel_schemes, + |write_fd, scheme_creation_cap, _, _| unsafe { // Creating a reference to NULL is UB. Mask the UB for now using black_box. // FIXME use a raw pointer and inline asm for reading instead for the initfs header. let initfs_start = core::ptr::addr_of!(__initfs_header); @@ -141,33 +137,32 @@ pub fn main() -> ! { crate::initfs::run( core::slice::from_raw_parts(initfs_start, initfs_length), write_fd, - &kernel_schemes, scheme_creation_cap, ); }, ); - let (scheme_creation_cap, auth, proc_fd) = spawn( + let (scheme_creation_cap, auth, kernel_schemes, proc_fd) = spawn( "process manager", auth, &this_thr_fd, scheme_creation_cap, - pipe_fd, - |write_fd, scheme_creation_cap, auth| { - crate::procmgr::run(write_fd, auth, &kernel_schemes, scheme_creation_cap) + kernel_schemes, + |write_fd, scheme_creation_cap, auth, kernel_schemes| { + crate::procmgr::run(write_fd, auth, kernel_schemes, scheme_creation_cap) }, ); - let (_, _, initns_fd) = spawn( + let (_, _, _, initns_fd) = spawn( "init namespace manager", auth, &this_thr_fd, scheme_creation_cap, - pipe_fd, - |write_fd, scheme_creation_cap, _| { + kernel_schemes, + |write_fd, scheme_creation_cap, _, kernel_schemes| { let mut schemes = HashMap::default(); for (scheme, fd) in kernel_schemes.0.into_iter() { - schemes.insert(scheme.as_str().to_string(), Arc::new(FdGuard::new(fd))); + schemes.insert(scheme.as_str().to_string(), Arc::new(fd)); } schemes.insert( "proc".to_string(), @@ -263,11 +258,20 @@ pub(crate) fn spawn( auth: FdGuard, this_thr_fd: &FdGuardUpper, scheme_creation_cap: FdGuard, - pipe_fd: usize, - inner: impl FnOnce(FdGuard, FdGuard, FdGuard) -> !, -) -> (FdGuard, FdGuard, FdGuard) { + kernel_schemes: KernelSchemeMap, + inner: impl FnOnce(FdGuard, FdGuard, FdGuard, KernelSchemeMap) -> !, +) -> (FdGuard, FdGuard, KernelSchemeMap, FdGuard) { let read = FdGuard::new( - syscall::openat(pipe_fd, "", O_CLOEXEC, 0).expect("failed to open sync read pipe"), + syscall::openat( + kernel_schemes + .get(GlobalSchemes::Pipe) + .expect("failed to get pipe fd") + .as_raw_fd(), + "", + O_CLOEXEC, + 0, + ) + .expect("failed to open sync read pipe"), ); // The write pipe will not inherit O_CLOEXEC, but is closed by the daemon later. @@ -286,7 +290,7 @@ pub(crate) fn spawn( Ok(0) => { drop(read); - inner(write, scheme_creation_cap, auth) + inner(write, scheme_creation_cap, auth, kernel_schemes) } // Return in order to execute init, as the parent. Ok(_) => { @@ -311,7 +315,12 @@ pub(crate) fn spawn( } } - (scheme_creation_cap, auth, FdGuard::new(new_fd)) + ( + scheme_creation_cap, + auth, + kernel_schemes, + FdGuard::new(new_fd), + ) } } } diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 8ec23d52e5..0f5f070b01 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -24,8 +24,6 @@ use syscall::error::*; use syscall::flag::*; use syscall::schemev2::NewFdFlags; -use crate::KernelSchemeMap; - enum Handle { Node(Node), SchemeRoot, @@ -384,12 +382,7 @@ impl SchemeSync for InitFsScheme { } } -pub fn run( - bytes: &'static [u8], - sync_pipe: FdGuard, - kernel_schemes: &KernelSchemeMap, - scheme_creation_cap: FdGuard, -) -> ! { +pub fn run(bytes: &'static [u8], sync_pipe: FdGuard, scheme_creation_cap: FdGuard) -> ! { log::info!("bootstrap: starting initfs scheme"); let mut state = SchemeState::new(); let mut scheme = InitFsScheme::new(bytes); @@ -398,10 +391,6 @@ pub fn run( .expect("failed to open initfs scheme socket"); drop(scheme_creation_cap); - for fd in kernel_schemes.0.values() { - let _ = syscall::close(*fd); - } - // send open-capability to bootstrap let new_id = scheme.next_id(); scheme.handles.insert(new_id, Handle::SchemeRoot); diff --git a/bootstrap/src/lib.rs b/bootstrap/src/lib.rs index 0c4ec3fe5d..c99076ce8a 100644 --- a/bootstrap/src/lib.rs +++ b/bootstrap/src/lib.rs @@ -29,6 +29,7 @@ extern crate alloc; use core::cell::UnsafeCell; use alloc::collections::btree_map::BTreeMap; +use redox_rt::proc::FdGuard; use syscall::data::Map; use syscall::data::{GlobalSchemes, KernelSchemeInfo}; use syscall::flag::MapFlags; @@ -135,18 +136,18 @@ unsafe impl alloc::alloc::GlobalAlloc for Allocator { } } -pub struct KernelSchemeMap(BTreeMap); +pub struct KernelSchemeMap(BTreeMap); impl KernelSchemeMap { fn new(kernel_scheme_infos: &[KernelSchemeInfo]) -> Self { let mut map = BTreeMap::new(); for info in kernel_scheme_infos { if let Some(scheme_id) = GlobalSchemes::try_from_raw(info.scheme_id) { - map.insert(scheme_id, info.fd); + map.insert(scheme_id, FdGuard::new(info.fd)); } } Self(map) } - fn get(&self, scheme: GlobalSchemes) -> Option<&usize> { + fn get(&self, scheme: GlobalSchemes) -> Option<&FdGuard> { self.0.get(&scheme) } } diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index 70b63bac4d..64b049666c 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -51,7 +51,7 @@ enum VirtualId { pub fn run( write_fd: FdGuard, auth: FdGuard, - kernel_schemes: &KernelSchemeMap, + kernel_schemes: KernelSchemeMap, scheme_creation_cap: FdGuard, ) -> ! { let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), true) @@ -62,14 +62,13 @@ pub fn run( let socket_ident = socket.inner().raw(); let queue = RawEventQueue::new( - *kernel_schemes + kernel_schemes .get(GlobalSchemes::Event) - .expect("failed to get event fd"), + .expect("failed to get event fd") + .as_raw_fd(), ) .expect("failed to create event queue"); - for fd in kernel_schemes.0.values() { - let _ = syscall::close(*fd); - } + drop(kernel_schemes); queue .subscribe(socket.inner().raw(), socket_ident, EventFlags::EVENT_READ) From b31f48cb59fe7c10af7ef55f432b2383e43fdf20 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:17:35 +0100 Subject: [PATCH 5/6] bootstrap: Directly pass event cap fd to procmgr --- bootstrap/src/exec.rs | 9 +++++++-- bootstrap/src/procmgr.rs | 20 +++----------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index 03678ac5bc..4570b51495 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -148,8 +148,13 @@ pub fn main() -> ! { &this_thr_fd, scheme_creation_cap, kernel_schemes, - |write_fd, scheme_creation_cap, auth, kernel_schemes| { - crate::procmgr::run(write_fd, auth, kernel_schemes, scheme_creation_cap) + |write_fd, scheme_creation_cap, auth, mut kernel_schemes| { + let event = kernel_schemes + .0 + .remove(&GlobalSchemes::Event) + .expect("failed to get event fd"); + drop(kernel_schemes); + crate::procmgr::run(write_fd, auth, event, scheme_creation_cap) }, ); diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index 64b049666c..f478a5874e 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -29,7 +29,6 @@ use redox_scheme::{ Socket, Tag, }; use slab::Slab; -use syscall::data::GlobalSchemes; use syscall::schemev2::NewFdFlags; use syscall::{ CallFlags, ContextStatus, ContextVerb, CtxtStsBuf, EACCES, EAGAIN, EBADF, EBADFD, ECANCELED, @@ -39,8 +38,6 @@ use syscall::{ sig_bit, }; -use crate::KernelSchemeMap; - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] enum VirtualId { KernelId(Id), @@ -48,12 +45,7 @@ enum VirtualId { InternalId(u64), } -pub fn run( - write_fd: FdGuard, - auth: FdGuard, - kernel_schemes: KernelSchemeMap, - scheme_creation_cap: FdGuard, -) -> ! { +pub fn run(write_fd: FdGuard, auth: FdGuard, event: FdGuard, scheme_creation_cap: FdGuard) -> ! { let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), true) .expect("failed to open proc scheme socket"); drop(scheme_creation_cap); @@ -61,14 +53,8 @@ pub fn run( // TODO? let socket_ident = socket.inner().raw(); - let queue = RawEventQueue::new( - kernel_schemes - .get(GlobalSchemes::Event) - .expect("failed to get event fd") - .as_raw_fd(), - ) - .expect("failed to create event queue"); - drop(kernel_schemes); + let queue = RawEventQueue::new(event.as_raw_fd()).expect("failed to create event queue"); + drop(event); queue .subscribe(socket.inner().raw(), socket_ident, EventFlags::EVENT_READ) From 311e1800194a499e5c540feda419d824a64b5319 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:23:00 +0100 Subject: [PATCH 6/6] bootstrap: Move scheme socket creation to spawn --- bootstrap/src/exec.rs | 28 ++++++++++++++++++++-------- bootstrap/src/initfs.rs | 6 +----- bootstrap/src/initnsmgr.rs | 4 +--- bootstrap/src/procmgr.rs | 6 +----- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index 4570b51495..bed91a03a9 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use core::ffi::CStr; use core::str::FromStr; use hashbrown::HashMap; +use redox_scheme::Socket; use syscall::CallFlags; use syscall::data::{GlobalSchemes, KernelSchemeInfo}; @@ -128,7 +129,8 @@ pub fn main() -> ! { &this_thr_fd, scheme_creation_cap, kernel_schemes, - |write_fd, scheme_creation_cap, _, _| unsafe { + false, + |write_fd, socket, _, _| unsafe { // Creating a reference to NULL is UB. Mask the UB for now using black_box. // FIXME use a raw pointer and inline asm for reading instead for the initfs header. let initfs_start = core::ptr::addr_of!(__initfs_header); @@ -137,7 +139,7 @@ pub fn main() -> ! { crate::initfs::run( core::slice::from_raw_parts(initfs_start, initfs_length), write_fd, - scheme_creation_cap, + socket, ); }, ); @@ -148,23 +150,28 @@ pub fn main() -> ! { &this_thr_fd, scheme_creation_cap, kernel_schemes, - |write_fd, scheme_creation_cap, auth, mut kernel_schemes| { + true, + |write_fd, socket, auth, mut kernel_schemes| { let event = kernel_schemes .0 .remove(&GlobalSchemes::Event) .expect("failed to get event fd"); drop(kernel_schemes); - crate::procmgr::run(write_fd, auth, event, scheme_creation_cap) + crate::procmgr::run(write_fd, socket, auth, event) }, ); + let scheme_creation_cap_dup = scheme_creation_cap + .dup(b"") + .expect("failed to dup scheme creation cap"); let (_, _, _, initns_fd) = spawn( "init namespace manager", auth, &this_thr_fd, scheme_creation_cap, kernel_schemes, - |write_fd, scheme_creation_cap, _, kernel_schemes| { + false, + |write_fd, socket, _, kernel_schemes| { let mut schemes = HashMap::default(); for (scheme, fd) in kernel_schemes.0.into_iter() { schemes.insert(scheme.as_str().to_string(), Arc::new(fd)); @@ -177,7 +184,7 @@ pub fn main() -> ! { ); schemes.insert("initfs".to_string(), Arc::new(initfs_fd)); - crate::initnsmgr::run(write_fd, schemes, scheme_creation_cap) + crate::initnsmgr::run(write_fd, socket, schemes, scheme_creation_cap_dup) }, ); @@ -264,7 +271,8 @@ pub(crate) fn spawn( this_thr_fd: &FdGuardUpper, scheme_creation_cap: FdGuard, kernel_schemes: KernelSchemeMap, - inner: impl FnOnce(FdGuard, FdGuard, FdGuard, KernelSchemeMap) -> !, + nonblock: bool, + inner: impl FnOnce(FdGuard, Socket, FdGuard, KernelSchemeMap) -> !, ) -> (FdGuard, FdGuard, KernelSchemeMap, FdGuard) { let read = FdGuard::new( syscall::openat( @@ -295,7 +303,11 @@ pub(crate) fn spawn( Ok(0) => { drop(read); - inner(write, scheme_creation_cap, auth, kernel_schemes) + let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), nonblock) + .expect("failed to open proc scheme socket"); + drop(scheme_creation_cap); + + inner(write, socket, auth, kernel_schemes) } // Return in order to execute init, as the parent. Ok(_) => { diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 0f5f070b01..209e771f37 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -382,15 +382,11 @@ impl SchemeSync for InitFsScheme { } } -pub fn run(bytes: &'static [u8], sync_pipe: FdGuard, scheme_creation_cap: FdGuard) -> ! { +pub fn run(bytes: &'static [u8], sync_pipe: FdGuard, socket: Socket) -> ! { 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.as_raw_fd(), false) - .expect("failed to open initfs scheme socket"); - drop(scheme_creation_cap); - // send open-capability to bootstrap let new_id = scheme.next_id(); scheme.handles.insert(new_id, Handle::SchemeRoot); diff --git a/bootstrap/src/initnsmgr.rs b/bootstrap/src/initnsmgr.rs index f73af73521..11a8a10405 100644 --- a/bootstrap/src/initnsmgr.rs +++ b/bootstrap/src/initnsmgr.rs @@ -489,12 +489,10 @@ where pub fn run( sync_pipe: FdGuard, + socket: Socket, schemes: HashMap>, scheme_creation_cap: FdGuard, ) -> ! { - let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), false) - .expect("failed to open init namespace scheme socket"); - let mut state = SchemeState::new(); let mut scheme = NamespaceScheme::new(&socket, schemes, scheme_creation_cap); diff --git a/bootstrap/src/procmgr.rs b/bootstrap/src/procmgr.rs index f478a5874e..5e65a92664 100644 --- a/bootstrap/src/procmgr.rs +++ b/bootstrap/src/procmgr.rs @@ -45,11 +45,7 @@ enum VirtualId { InternalId(u64), } -pub fn run(write_fd: FdGuard, auth: FdGuard, event: FdGuard, scheme_creation_cap: FdGuard) -> ! { - let socket = Socket::create_inner(scheme_creation_cap.as_raw_fd(), true) - .expect("failed to open proc scheme socket"); - drop(scheme_creation_cap); - +pub fn run(write_fd: FdGuard, socket: Socket, auth: FdGuard, event: FdGuard) -> ! { // TODO? let socket_ident = socket.inner().raw();