From 6d72048b1312cb0d3fbbe61931bf085a742124c2 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 13 Apr 2025 12:43:36 +0200 Subject: [PATCH] Store proc_fd in MaybeUninit with external discriminant. --- redox-rt/src/lib.rs | 29 ++++++++++++++++++----------- redox-rt/src/proc.rs | 20 +++++++++++++------- redox-rt/src/thread.rs | 9 ++++----- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 43cfb811cf..f14ccbf4be 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -11,11 +11,11 @@ use core::{ cell::{SyncUnsafeCell, UnsafeCell}, - mem::size_of, + mem::{size_of, MaybeUninit}, }; use generic_rt::{ExpectTlsFree, GenericTcb}; -use syscall::{Sigcontrol, O_CLOEXEC}; +use syscall::Sigcontrol; use self::{proc::FdGuard, protocol::ProcMeta, sync::Mutex}; @@ -196,10 +196,12 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { ppid: metadata.ppid, #[cfg(feature = "proc")] - proc_fd: Some(proc_fd), + proc_fd: MaybeUninit::new(proc_fd), #[cfg(not(feature = "proc"))] - proc_fd: None, + proc_fd: MaybeUninit::uninit(), + + has_proc_fd: cfg!(feature = "proc"), }); #[cfg(feature = "proc")] @@ -216,10 +218,12 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { } } +#[repr(C)] // TODO: is this required? pub(crate) struct StaticProcInfo { pid: u32, ppid: u32, // TODO: dynamic - proc_fd: Option, + proc_fd: MaybeUninit, + has_proc_fd: bool, } struct DynamicProcInfo { pgid: u32, @@ -234,7 +238,8 @@ struct DynamicProcInfo { static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { pid: 0, ppid: 0, - proc_fd: None, + proc_fd: MaybeUninit::uninit(), + has_proc_fd: false, }); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, @@ -252,10 +257,9 @@ pub(crate) fn static_proc_info() -> &'static StaticProcInfo { } #[inline] pub fn current_proc_fd() -> &'static FdGuard { - static_proc_info() - .proc_fd - .as_ref() - .expect("proc fd must be present") + let info = static_proc_info(); + assert!(info.has_proc_fd); + unsafe { info.proc_fd.assume_init_ref() } } struct ChildHookCommonArgs { @@ -281,7 +285,10 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) { .replace(StaticProcInfo { pid: metadata.pid, ppid: metadata.ppid, - proc_fd: args.new_proc_fd, + has_proc_fd: args.new_proc_fd.is_some(), + proc_fd: args + .new_proc_fd + .map_or_else(MaybeUninit::uninit, MaybeUninit::new), }) .proc_fd; drop(old_proc_fd); diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index af8117bf7a..c4bde603f4 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,4 +1,7 @@ -use core::{fmt::Debug, mem::size_of}; +use core::{ + fmt::Debug, + mem::{size_of, MaybeUninit}, +}; use crate::{ arch::*, @@ -887,10 +890,12 @@ struct NewChildProc { pub fn new_child_process(args: &ForkArgs<'_>) -> Result { match *args { ForkArgs::Managed => { - let this_proc_fd = crate::static_proc_info() - .proc_fd - .as_ref() - .expect("cannot use ForkArgs::Managed without an existing proc info"); + let proc_info = crate::static_proc_info(); + assert!( + proc_info.has_proc_fd, + "cannot use ForkArgs::Managed without an existing proc info" + ); + let this_proc_fd = unsafe { proc_info.proc_fd.assume_init_ref() }; let child_proc_fd = FdGuard::new(syscall::dup(**this_proc_fd, b"fork")?); let only_thread_fd = FdGuard::new(syscall::dup(*child_proc_fd, b"thread-0")?); let meta = read_proc_meta(&child_proc_fd)?; @@ -961,7 +966,8 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1, - proc_fd: Some(proc_fd), + proc_fd: MaybeUninit::new(proc_fd), + has_proc_fd: true, }); *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { pgid: 1, @@ -973,7 +979,7 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { sgid: 0, }; [ - (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap(), + (*STATIC_PROC_INFO.get()).proc_fd.assume_init_ref(), managed_thr_fd, ] } diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 953fce5e62..b1bc7e5652 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -1,15 +1,14 @@ use core::mem::size_of; -use syscall::{Error, Result, ESRCH, O_CLOEXEC}; +use syscall::Result; use crate::{arch::*, proc::*, signal::tmp_disable_signals, static_proc_info, RtTcb}; /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { - let cur_proc_fd = static_proc_info() - .proc_fd - .as_ref() - .ok_or(Error::new(ESRCH))?; + let proc_info = static_proc_info(); + assert!(proc_info.has_proc_fd); + let cur_proc_fd = proc_info.proc_fd.assume_init_ref(); let cur_thr_fd = RtTcb::current().thread_fd(); let new_thr_fd = FdGuard::new(syscall::dup(**cur_proc_fd, b"new-thread")?);