Merge branch 'avoid-blocking-nsmgr' into 'master'

refactor: Move fd allocation logic into userspace

See merge request redox-os/relibc!1479
This commit is contained in:
Jeremy Soller
2026-07-01 08:08:23 -06:00
25 changed files with 1853 additions and 182 deletions
Generated
+6 -6
View File
@@ -262,9 +262,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "libredox"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3"
checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
dependencies = [
"bitflags",
"libc",
@@ -467,9 +467,9 @@ dependencies = [
[[package]]
name = "redox_event"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c07d0d6d291e3a951bd847b1cd4af32fc6243d64116cf7702838c02797688b7"
checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15"
dependencies = [
"bitflags",
"libredox",
@@ -478,9 +478,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.8.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7"
checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759"
dependencies = [
"bitflags",
]
+4 -3
View File
@@ -69,8 +69,9 @@ bitflags = "2"
ioslice = { version = "0.6", default-features = false }
plain = "0.2"
redox-path = "0.3"
redox_protocols = { package = "libredox", version = "0.1.17", default-features = false, features = ["protocol"] }
redox_syscall = "0.8.1"
redox_protocols = { package = "libredox", version = "0.1.18", default-features = false, features = ["protocol"] }
redox_syscall = "0.9.0"
[build-dependencies]
cc = "1"
@@ -123,7 +124,7 @@ sc = "0.2.7"
redox_syscall.workspace = true
redox-rt = { path = "redox-rt" }
redox-path.workspace = true
redox_event = { version = "0.4.7", default-features = false, features = ["redox_syscall"] }
redox_event = { version = "0.4.8", default-features = false, features = ["redox_syscall"] }
ioslice.workspace = true
redox-ioctl = { path = "redox-ioctl" }
redox_protocols.workspace = true
+1 -1
View File
@@ -8,6 +8,6 @@ description = "Ioctl definitions and (de)serialization for Redox"
[dependencies]
drm-sys = "0.8.0"
redox_syscall = "0.8.1"
redox_syscall = "0.9.0"
[features]
+6 -2
View File
@@ -79,11 +79,12 @@ pub struct ArchIntRegs {
pub unsafe fn deactivate_tcb(open_via_dup: &FdGuardUpper) -> Result<()> {
let mut env = syscall::EnvRegisters::default();
let file = open_via_dup.dup(b"regs/env")?;
let file = open_via_dup.dup_into_upper(b"regs/env")?;
env.tpidr_el0 = 0;
file.write(&mut env)?;
crate::TLS_ACTIVATED.store(false, core::sync::atomic::Ordering::Relaxed);
Ok(())
}
@@ -93,7 +94,7 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz
unsafe extern "C" fn child_hook(scratchpad: &ForkScratchpad) {
//let _ = syscall::write(1, alloc::format!("CUR{cur_filetable_fd}PROC{new_proc_fd}THR{new_thr_fd}\n").as_bytes());
let _ = syscall::close(scratchpad.cur_filetable_fd);
let _ = crate::sys::close(scratchpad.cur_filetable_fd);
unsafe {
crate::child_hook_common(crate::ChildHookCommonArgs {
new_thr_fd: FdGuard::new(scratchpad.new_thr_fd),
@@ -102,6 +103,9 @@ unsafe extern "C" fn child_hook(scratchpad: &ForkScratchpad) {
} else {
Some(FdGuard::new(scratchpad.new_proc_fd))
},
new_filetable_fd: FdGuard::new(scratchpad.new_filetable_fd)
.to_upper()
.unwrap(),
})
};
}
+6 -2
View File
@@ -61,12 +61,13 @@ pub struct ArchIntRegs {
pub unsafe fn deactivate_tcb(open_via_dup: &FdGuardUpper) -> Result<()> {
let mut env = syscall::EnvRegisters::default();
let file = open_via_dup.dup(b"regs/env")?;
let file = open_via_dup.dup_into_upper(b"regs/env")?;
env.fsbase = 0;
env.gsbase = 0;
file.write(&mut env)?;
crate::TLS_ACTIVATED.store(false, core::sync::atomic::Ordering::Relaxed);
Ok(())
}
@@ -76,7 +77,7 @@ unsafe extern "fastcall" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize)
// TODO: duplicate code with x86_64
unsafe extern "cdecl" fn child_hook(scratchpad: ForkScratchpad) {
let _ = syscall::close(scratchpad.cur_filetable_fd);
let _ = crate::sys::close(scratchpad.cur_filetable_fd);
unsafe {
crate::child_hook_common(crate::ChildHookCommonArgs {
new_thr_fd: FdGuard::new(scratchpad.new_thr_fd),
@@ -85,6 +86,9 @@ unsafe extern "cdecl" fn child_hook(scratchpad: ForkScratchpad) {
} else {
Some(FdGuard::new(scratchpad.new_proc_fd))
},
new_filetable_fd: FdGuard::new(scratchpad.new_filetable_fd)
.to_upper()
.unwrap(),
})
};
}
+1
View File
@@ -22,6 +22,7 @@ pub mod riscv64;
#[repr(C)]
pub struct ForkScratchpad {
pub cur_filetable_fd: usize,
pub new_filetable_fd: usize,
pub new_proc_fd: usize,
pub new_thr_fd: usize,
}
+6 -2
View File
@@ -55,11 +55,12 @@ pub struct ArchIntRegs {
pub unsafe fn deactivate_tcb(open_via_dup: &FdGuardUpper) -> Result<()> {
let mut env = syscall::EnvRegisters::default();
let file = open_via_dup.dup(b"regs/env")?;
let file = open_via_dup.dup_into_upper(b"regs/env")?;
env.tp = 0;
file.write(&mut env)?;
crate::TLS_ACTIVATED.store(false, core::sync::atomic::Ordering::Relaxed);
Ok(())
}
@@ -68,7 +69,7 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz
}
unsafe extern "C" fn child_hook(scratchpad: &ForkScratchpad) {
let _ = syscall::close(scratchpad.cur_filetable_fd);
let _ = crate::sys::close(scratchpad.cur_filetable_fd);
unsafe {
crate::child_hook_common(crate::ChildHookCommonArgs {
new_thr_fd: FdGuard::new(scratchpad.new_thr_fd),
@@ -77,6 +78,9 @@ unsafe extern "C" fn child_hook(scratchpad: &ForkScratchpad) {
} else {
Some(FdGuard::new(scratchpad.new_proc_fd))
},
new_filetable_fd: FdGuard::new(scratchpad.new_filetable_fd)
.to_upper()
.unwrap(),
})
};
}
+6 -2
View File
@@ -75,12 +75,13 @@ pub struct ArchIntRegs {
pub unsafe fn deactivate_tcb(open_via_dup: &FdGuardUpper) -> Result<()> {
let mut env = syscall::EnvRegisters::default();
let file = open_via_dup.dup(b"regs/env")?;
let file = open_via_dup.dup_into_upper(b"regs/env")?;
env.fsbase = 0;
env.gsbase = 0;
file.write(&mut env)?;
crate::TLS_ACTIVATED.store(false, core::sync::atomic::Ordering::Relaxed);
Ok(())
}
@@ -90,7 +91,7 @@ unsafe extern "sysv64" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) ->
#[allow(unsafe_op_in_unsafe_fn)]
unsafe extern "sysv64" fn child_hook(scratchpad: &ForkScratchpad) {
let _ = syscall::close(scratchpad.cur_filetable_fd);
let _ = crate::sys::close(scratchpad.cur_filetable_fd);
crate::child_hook_common(crate::ChildHookCommonArgs {
new_thr_fd: FdGuard::new(scratchpad.new_thr_fd),
new_proc_fd: if scratchpad.new_proc_fd == usize::MAX {
@@ -98,6 +99,9 @@ unsafe extern "sysv64" fn child_hook(scratchpad: &ForkScratchpad) {
} else {
Some(FdGuard::new(scratchpad.new_proc_fd))
},
new_filetable_fd: FdGuard::new(scratchpad.new_filetable_fd)
.to_upper()
.unwrap(),
});
}
+65 -10
View File
@@ -15,6 +15,7 @@ use syscall::Sigcontrol;
use self::{
proc::{FdGuard, FdGuardUpper, STATIC_PROC_INFO},
sync::Mutex,
sys::FdTbl,
};
extern crate alloc;
@@ -67,6 +68,11 @@ impl RtTcb {
pub type Tcb = GenericTcb<RtTcb>;
// TODO: Remove this by keeping the TCB initialized during exec
// and informing ld.so through some other way.
pub static TLS_ACTIVATED: core::sync::atomic::AtomicBool =
core::sync::atomic::AtomicBool::new(false);
/// OS and architecture specific code to activate TLS - Redox aarch64
#[allow(unsafe_op_in_unsafe_fn)]
#[cfg(target_arch = "aarch64")]
@@ -78,6 +84,7 @@ pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) {
"msr tpidr_el0, {}",
in(reg) abi_ptr,
);
TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
}
/// OS and architecture specific code to activate TLS - Redox x86
@@ -86,16 +93,18 @@ pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) {
pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default();
let file = tcb
.thread_fd()
.dup(b"regs/env")
let file_fd = crate::sys::dup_into_upper_raw(tcb.thread_fd().as_raw_fd(), b"regs/env")
.expect_notls("failed to open handle for process registers");
file.read(&mut env).expect_notls("failed to read gsbase");
syscall::read(file_fd, &mut env).expect_notls("failed to read gsbase");
env.gsbase = tls_end as u32;
file.write(&env).expect_notls("failed to write gsbase");
syscall::write(file_fd, &env).expect_notls("failed to write gsbase");
let _ = crate::sys::close_raw(file_fd);
TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
}
/// OS and architecture specific code to activate TLS - Redox x86_64
@@ -104,16 +113,18 @@ pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end: usize, _tls_len: usize) {
pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end_and_tcb_start: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default();
let file = tcb
.thread_fd()
.dup(b"regs/env")
let file_fd = crate::sys::dup_into_upper_raw(tcb.thread_fd().as_raw_fd(), b"regs/env")
.expect_notls("failed to open handle for process registers");
file.read(&mut env).expect_notls("failed to read fsbase");
syscall::read(file_fd, &mut env).expect_notls("failed to read fsbase");
env.fsbase = tls_end_and_tcb_start as u64;
file.write(&env).expect_notls("failed to write fsbase");
syscall::write(file_fd, &env).expect_notls("failed to write fsbase");
let _ = crate::sys::close_raw(file_fd);
TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
}
/// OS and architecture specific code to activate TLS - Redox riscv64
@@ -129,6 +140,7 @@ pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) {
"mv tp, {}",
in(reg) tls_start
);
TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
}
/// Initialize redox-rt in situations where relibc is not used
@@ -158,6 +170,17 @@ pub unsafe fn initialize_freestanding(this_thr_fd: FdGuardUpper) -> &'static FdG
page.tcb_len = syscall::PAGE_SIZE;
page.tls_end = (page as *mut Tcb).cast();
let cur_filetable_fd = syscall::dup_into(
this_thr_fd.as_raw_fd(),
this_thr_fd.as_raw_fd() + 1,
b"filetable-binary",
)
.expect("failed to open filetable-binary");
*current_filetable() =
FdTbl::from_binary_fd(FdGuard::new(cur_filetable_fd).to_upper().unwrap())
.expect("failed to populate fds");
// Make sure to use ptr::write to prevent dropping the existing FdGuard
page.os_specific.thr_fd.get().write(Some(this_thr_fd));
@@ -176,6 +199,8 @@ pub unsafe fn initialize_freestanding(this_thr_fd: FdGuardUpper) -> &'static FdG
let abi_ptr = core::ptr::addr_of_mut!(page.tcb_ptr) as usize;
core::arch::asm!("mv tp, {}", in(reg) (abi_ptr + 8));
}
TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
initialize();
(*page.os_specific.thr_fd.get()).as_ref().unwrap()
@@ -275,9 +300,30 @@ pub fn current_namespace_fd() -> syscall::Result<usize> {
struct ChildHookCommonArgs {
new_thr_fd: FdGuard,
new_proc_fd: Option<FdGuard>,
new_filetable_fd: FdGuardUpper,
}
unsafe fn child_hook_common(args: ChildHookCommonArgs) {
let new_filetable_fd = args.new_filetable_fd;
let old_filetable_fd;
{
let mut guard = current_filetable();
old_filetable_fd = guard.take();
guard.set_fd(new_filetable_fd);
guard
.override_at(args.new_thr_fd.as_raw_fd(), args.new_thr_fd.as_raw_fd())
.expect("failed to add new_thr_fd");
if let Some(new_proc_fd) = args.new_proc_fd.as_ref() {
guard
.override_at(new_proc_fd.as_raw_fd(), new_proc_fd.as_raw_fd())
.expect("failed to add new_proc_fd");
}
if let Some(ref old) = old_filetable_fd {
let _ = guard.remove(old.as_raw_fd());
}
}
let new_thr_fd = args.new_thr_fd.to_upper().unwrap();
let new_proc_fd = args.new_proc_fd.map(|x| x.to_upper().unwrap());
@@ -310,4 +356,13 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) {
let old_thr_fd = unsafe { RtTcb::current().thr_fd.get().replace(Some(new_thr_fd)) };
drop(old_thr_fd);
drop(old_filetable_fd);
}
static FILETABLE: Mutex<FdTbl> = Mutex::new(FdTbl::new());
#[inline]
pub fn current_filetable() -> crate::sync::MutexGuard<'static, FdTbl> {
FILETABLE.lock()
}
+124 -63
View File
@@ -7,7 +7,7 @@ use crate::{
read_proc_meta,
sys::{fstat, open, proc_call, thread_call},
};
use redox_protocols::protocol::{ProcCall, ThreadCall};
use redox_protocols::protocol::{O_CLOEXEC, ProcCall, ThreadCall};
use alloc::{boxed::Box, vec};
@@ -25,8 +25,8 @@ use goblin::elf64::{
};
use syscall::{
CallFlags, F_GETFD, GrantDesc, GrantFlags, MAP_FIXED_NOREPLACE, MAP_SHARED, Map, O_CLOEXEC,
PAGE_SIZE, PROT_EXEC, PROT_READ, PROT_WRITE, SetSighandlerData,
CallFlags, GrantDesc, GrantFlags, MAP_FIXED_NOREPLACE, MAP_SHARED, Map, PAGE_SIZE, PROT_EXEC,
PROT_READ, PROT_WRITE, SetSighandlerData,
error::*,
flag::{MapFlags, SEEK_SET},
};
@@ -63,6 +63,8 @@ pub struct ExtraInfo<'a> {
pub ns_fd: Option<usize>,
/// CWD handle
pub cwd_fd: Option<usize>,
/// Filetable handle
pub filetable_fd: Option<usize>,
/// If the process for which the image is to be loaded the same as the currently running process
pub same_process: bool,
}
@@ -93,9 +95,10 @@ pub fn fexec_impl(
let grants_fd = if let Some(interp) = interp_override.as_ref() {
FdGuard::new(interp.grants_fd).to_upper()?
} else {
let current_addrspace_fd = thread_fd.dup(b"addrspace")?;
current_addrspace_fd.dup(b"empty")?.to_upper()?
let current_addrspace_fd = thread_fd.dup_into_upper(b"addrspace")?;
current_addrspace_fd.dup_into_upper(b"empty")?
};
grants_fd.fcntl(syscall::F_SETFD, O_CLOEXEC)?;
// Never allow more than 1 MiB of program headers.
const MAX_PH_SIZE: usize = 1024 * 1024;
@@ -404,6 +407,8 @@ pub fn fexec_impl(
push(AT_REDOX_NS_FD)?;
push(extrainfo.cwd_fd.unwrap_or(usize::MAX))?;
push(AT_REDOX_CWD_FD)?;
push(extrainfo.filetable_fd.unwrap_or(usize::MAX))?;
push(AT_REDOX_FILETABLE_FD)?;
push(0)?;
@@ -421,7 +426,7 @@ pub fn fexec_impl(
push(argc)?;
if let Ok(sighandler_fd) = thread_fd.dup(b"sighandler") {
if let Ok(sighandler_fd) = thread_fd.dup_into_upper(b"sighandler") {
let _ = sighandler_fd.write(&SetSighandlerData {
user_handler: 0,
excp_handler: 0,
@@ -456,11 +461,11 @@ pub fn fexec_impl(
);
if interp_override.is_some() {
let mmap_min_fd = grants_fd.dup(b"mmap-min-addr")?;
let mmap_min_fd = grants_fd.dup_into_upper(b"mmap-min-addr")?;
let _ = mmap_min_fd.write(&usize::to_ne_bytes(min_mmap_addr));
}
let addrspace_selection_fd = thread_fd.dup(b"current-addrspace")?.to_upper()?;
let addrspace_selection_fd = thread_fd.dup_into_upper(b"current-addrspace")?;
let _ = addrspace_selection_fd.write(&create_set_addr_space_buf(
grants_fd.as_raw_fd(),
@@ -474,29 +479,55 @@ pub fn fexec_impl(
// scenarios. While execve() is undefined according to POSIX if there exist sibling
// threads, it could still be allowed by keeping certain file descriptors and instead
// set the active file table.
let files_fd = syscall::dup(thread_fd.as_raw_fd(), b"filetable-binary")?;
let mut files_reader = FileBufReader::from_fd(files_fd);
loop {
let fd = match files_reader.read_le_u64()? {
None => break,
Some(fd) => fd,
};
let fd = usize::try_from(fd).unwrap();
let _siglock = crate::signal::tmp_disable_signals();
let fds_to_close = {
let guard = crate::current_filetable();
let mut fds = alloc::vec::Vec::new();
for (fd, flags) in guard.iter() {
if fd == addrspace_selection_fd.as_raw_fd() {
continue; // Will be closed below
}
if fd == addrspace_selection_fd.as_raw_fd() || fd == files_fd {
continue; // Will be closed below
if flags & O_CLOEXEC == O_CLOEXEC || fd == image_file.as_raw_fd() {
fds.push(fd);
}
}
let flags = syscall::fcntl(fd, F_GETFD, 0)?;
fds
};
if flags & O_CLOEXEC == O_CLOEXEC {
let _ = syscall::close(fd);
let fds_to_close_bytes: &[u8] = unsafe {
core::slice::from_raw_parts(
fds_to_close.as_ptr() as *mut u8,
fds_to_close.len() * core::mem::size_of::<usize>(),
)
};
{
let filetable_fd = thread_fd.dup_into_upper(b"filetable-binary")?;
let _ = filetable_fd.call_wo(
fds_to_close_bytes,
CallFlags::empty(),
&[syscall::FileTableVerb::Close as u64],
);
}
{
let mut guard = crate::current_filetable();
for fd in fds_to_close {
let _ = guard.remove(fd);
}
}
unsafe {
deactivate_tcb(&thread_fd)?;
}
let old_filetable_fd = {
let mut guard = crate::current_filetable();
guard.take()
};
drop(old_filetable_fd);
// Dropping this FD will cause the address space switch.
drop(addrspace_selection_fd);
unreachable!();
@@ -705,7 +736,7 @@ impl<'a> Drop for MmapGuard<'a> {
}
}
struct FileBufReader {
pub(crate) struct FileBufReader {
fd: usize,
buf: [u8; 8192],
pos: usize,
@@ -724,10 +755,10 @@ impl FileBufReader {
}
impl FileBufReader {
fn read_le_u64(&mut self) -> Result<Option<u64>> {
pub fn read_le_u64(&mut self) -> Result<Option<u64>> {
if self.pos >= self.cap {
debug_assert!(self.pos == self.cap);
self.cap = crate::sys::posix_read(self.fd, &mut self.buf)?;
self.cap = syscall::read(self.fd, &mut self.buf)?;
self.pos = 0;
}
@@ -746,7 +777,6 @@ impl FileBufReader {
Ok(Some(num))
}
}
#[repr(transparent)]
pub struct FdGuard<const UPPER: bool = false> {
fd: usize,
@@ -757,18 +787,24 @@ impl FdGuard<false> {
pub fn new(fd: usize) -> Self {
Self { fd }
}
#[inline]
pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<Self> {
open(path, flags).map(Self::new)
}
#[inline]
pub fn open_into_upper<T: AsRef<str>>(path: T, flags: usize) -> Result<FdGuardUpper> {
crate::sys::open_into_upper(path, flags)
.map(FdGuard::new)?
.to_upper()
}
#[inline]
pub fn to_upper(self) -> Result<FdGuardUpper> {
// Move to upper table if necessary
let fd = if self.fd & syscall::UPPER_FDTBL_TAG == 0 {
//TODO: use F_DUPFD_CLOEXEC?
let fd = syscall::fcntl(self.fd, syscall::F_DUPFD, syscall::UPPER_FDTBL_TAG)?;
let fd = crate::sys::fcntl(self.fd, syscall::F_DUPFD, syscall::UPPER_FDTBL_TAG)?;
drop(self);
fd
} else {
@@ -791,16 +827,35 @@ impl<const UPPER: bool> FdGuard<UPPER> {
flags: usize,
fcntl_flags: usize,
) -> Result<FdGuard<false>> {
syscall::openat(self.fd, path, flags, fcntl_flags).map(FdGuard::new)
crate::sys::openat(self.fd, path, flags, fcntl_flags).map(FdGuard::new)
}
#[inline]
pub fn openat_into_upper<T: AsRef<str>>(
&self,
path: T,
flags: usize,
fcntl_flags: usize,
) -> Result<FdGuardUpper> {
crate::sys::openat_into_upper(self.fd, path, flags, fcntl_flags)
.map(FdGuard::new)?
.to_upper()
}
#[inline]
pub fn dup(&self, buf: &[u8]) -> Result<FdGuard<false>> {
syscall::dup(self.fd, buf).map(FdGuard::new)
crate::sys::dup(self.fd, buf).map(FdGuard::new)
}
#[inline]
pub fn dup_into_upper(&self, buf: &[u8]) -> Result<FdGuardUpper> {
crate::sys::dup_into_upper(self.fd, buf)
.map(FdGuard::new)?
.to_upper()
}
#[inline]
pub fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
syscall::fcntl(self.fd, cmd, arg)
crate::sys::fcntl(self.fd, cmd, arg)
}
#[inline]
@@ -825,17 +880,17 @@ impl<const UPPER: bool> FdGuard<UPPER> {
#[inline]
pub fn call_ro(&self, payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
syscall::call_ro(self.fd, payload, flags, metadata)
crate::sys::sys_call_ro(self.fd, payload, flags, metadata)
}
#[inline]
pub fn call_wo(&self, payload: &[u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
syscall::call_wo(self.fd, payload, flags, metadata)
crate::sys::sys_call_wo(self.fd, payload, flags, metadata)
}
#[inline]
pub fn call_rw(&self, payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
syscall::call_rw(self.fd, payload, flags, metadata)
crate::sys::sys_call_rw(self.fd, payload, flags, metadata)
}
#[inline]
@@ -853,7 +908,7 @@ impl<const UPPER: bool> FdGuard<UPPER> {
impl<const UPPER: bool> Drop for FdGuard<UPPER> {
#[inline]
fn drop(&mut self) {
let _ = syscall::close(self.fd);
let _ = crate::sys::close(self.fd);
}
}
impl Debug for FdGuard<false> {
@@ -912,7 +967,7 @@ pub enum ForkArgs<'a> {
}
pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
let (cur_filetable_fd, new_proc_fd, new_thr_fd, new_pid);
let (cur_filetable_fd, new_filetable_fd, new_proc_fd, new_thr_fd, new_pid);
{
let cur_thr_fd = match args {
@@ -931,7 +986,8 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
// Copy existing files into new file table, but do not reuse the same file table (i.e. new
// parent FDs will not show up for the child).
let scratchpad = {
cur_filetable_fd = cur_thr_fd.dup(b"filetable")?;
cur_filetable_fd = cur_thr_fd.dup_into_upper(b"filetable-binary")?;
new_filetable_fd = cur_filetable_fd.dup_into_upper(b"copy")?;
// This must be done before the address space is copied.
let proc_fd = new_proc_fd.as_ref().map_or(usize::MAX, |p| p.as_raw_fd());
@@ -939,6 +995,7 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
ForkScratchpad {
cur_filetable_fd: cur_filetable_fd.as_raw_fd(),
new_filetable_fd: new_filetable_fd.as_raw_fd(),
new_proc_fd: proc_fd,
new_thr_fd: new_thr_fd.as_raw_fd(),
}
@@ -960,10 +1017,10 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
// CoW-duplicate address space.
{
let new_addr_space_sel_fd = new_thr_fd.dup(b"current-addrspace")?;
let new_addr_space_sel_fd = new_thr_fd.dup_into_upper(b"current-addrspace")?;
let cur_addr_space_fd = cur_thr_fd.dup(b"addrspace")?.to_upper()?;
let new_addr_space_fd = cur_addr_space_fd.dup(b"exclusive")?.to_upper()?;
let cur_addr_space_fd = cur_thr_fd.dup_into_upper(b"addrspace")?;
let new_addr_space_fd = cur_addr_space_fd.dup_into_upper(b"exclusive")?;
let mut grant_desc_buf = [GrantDesc::default(); 16];
loop {
@@ -1006,7 +1063,7 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
buf = alloc::format!("grant-fd-{:>08x}", grant.base).into_bytes();
}
let grant_fd = cur_addr_space_fd.dup(&buf)?.to_upper()?;
let grant_fd = cur_addr_space_fd.dup_into_upper(&buf)?;
let mut flags = MAP_SHARED | MAP_FIXED_NOREPLACE;
@@ -1049,7 +1106,7 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
// Do this after the address space is cloned, since the kernel will get a shared
// reference to the TCB and whatever pages stores the signal proc control struct.
{
let new_sighandler_fd = new_thr_fd.dup(b"sighandler")?;
let new_sighandler_fd = new_thr_fd.dup_into_upper(b"sighandler")?;
new_sighandler_fd.write(&crate::signal::current_setsighandler_struct())?;
}
if let Some(ref proc_fd) = new_proc_fd {
@@ -1069,25 +1126,26 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
}
{
// Copy environment registers.
let cur_env_regs_fd = cur_thr_fd.dup(b"regs/env")?;
let new_env_regs_fd = new_thr_fd.dup(b"regs/env")?;
let cur_env_regs_fd = cur_thr_fd.dup_into_upper(b"regs/env")?;
let new_env_regs_fd = new_thr_fd.dup_into_upper(b"regs/env")?;
let mut env_regs = syscall::EnvRegisters::default();
cur_env_regs_fd.read(&mut env_regs)?;
new_env_regs_fd.write(&env_regs)?;
}
}
// Copy the file table. We do this last to ensure that all previously used file descriptors are
// closed. The only exception -- the filetable selection fd and the current filetable fd --
// will be closed by the child process.
{
// TODO: Use file descriptor forwarding or something similar to avoid copying the file
// table in the kernel.
let new_filetable_fd = cur_filetable_fd.dup(b"copy")?;
let new_filetable_sel_fd = new_thr_fd.dup(b"current-filetable")?;
let new_filetable_sel_fd = new_thr_fd.dup_into_upper(b"current-filetable")?;
new_filetable_sel_fd.write(&usize::to_ne_bytes(new_filetable_fd.as_raw_fd()))?;
}
let start_fd = new_thr_fd.dup(b"start")?;
new_filetable_fd.call_wo(
&new_filetable_fd.as_raw_fd().to_ne_bytes(),
syscall::CallFlags::FD | syscall::CallFlags::FD_CLONE,
&[new_filetable_fd.as_raw_fd() as u64],
)?;
let start_fd = new_thr_fd.dup_into_upper(b"start")?;
start_fd.write(&[0])?;
Ok(new_pid)
}
@@ -1107,8 +1165,8 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result<NewChildProc> {
.proc_fd
.as_ref()
.expect("cannot use ForkArgs::Managed without an existing proc info");
let child_proc_fd = this_proc_fd.dup(b"fork")?.to_upper()?;
let only_thread_fd = child_proc_fd.dup(b"thread-0")?.to_upper()?;
let child_proc_fd = this_proc_fd.dup_into_upper(b"fork")?;
let only_thread_fd = child_proc_fd.dup_into_upper(b"thread-0")?;
let meta = read_proc_meta(&child_proc_fd)?;
Ok(NewChildProc {
proc_fd: Some(child_proc_fd),
@@ -1121,7 +1179,7 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result<NewChildProc> {
#[cfg(not(feature = "proc"))]
ForkArgs::Init { this_thr_fd, auth } => {
let thr_fd = auth.dup(b"new-context")?.to_upper()?;
let thr_fd = auth.dup_into_upper(b"new-context")?;
let buf = syscall::ProcSchemeAttrs {
pid: 0,
euid: 0,
@@ -1134,8 +1192,8 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result<NewChildProc> {
buf
},
};
let attr_fd =
thr_fd.dup(alloc::format!("auth-{}-attrs", auth.as_raw_fd()).as_bytes())?;
let attr_fd = thr_fd
.dup_into_upper(alloc::format!("auth-{}-attrs", auth.as_raw_fd()).as_bytes())?;
attr_fd.write(&buf)?;
Ok(NewChildProc {
thr_fd,
@@ -1148,24 +1206,27 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result<NewChildProc> {
pub unsafe fn make_init(proc_cap: usize) -> (&'static FdGuardUpper, &'static FdGuardUpper) {
let proc_fd = FdGuard::new(
syscall::openat(proc_cap, "init", syscall::O_CLOEXEC, 0).expect("failed to create init"),
crate::sys::openat_into_upper(proc_cap, "init", 0, 0).expect("failed to create init"),
)
.to_upper()
.unwrap();
syscall::sendfd(
crate::sys::sys_call_wo(
proc_fd.as_raw_fd(),
RtTcb::current().thread_fd().dup(&[]).unwrap().take(),
0,
0,
&RtTcb::current()
.thread_fd()
.dup_into_upper(&[])
.unwrap()
.take()
.to_ne_bytes(),
syscall::CallFlags::FD,
&[],
)
.expect("failed to assign current thread to init process");
let managed_thr_fd = proc_fd
.dup(b"thread-0")
.expect("failed to get managed thread for init")
.to_upper()
.unwrap();
.dup_into_upper(b"thread-0")
.expect("failed to get managed thread for init");
let managed_thr_fd = unsafe { (*RtTcb::current().thr_fd.get()).insert(managed_thr_fd) };
+10 -3
View File
@@ -538,10 +538,14 @@ fn current_sigctl() -> &'static Sigcontrol {
}
pub struct TmpDisableSignalsGuard {
_inner: (),
active: bool,
}
pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
if !crate::TLS_ACTIVATED.load(Ordering::Relaxed) {
return TmpDisableSignalsGuard { active: false };
}
unsafe {
let ctl = &current_sigctl().control_flags;
ctl.store(
@@ -554,10 +558,13 @@ pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
(*Tcb::current().unwrap().os_specific.arch.get()).disable_signals_depth += 1;
}
TmpDisableSignalsGuard { _inner: () }
TmpDisableSignalsGuard { active: true }
}
impl Drop for TmpDisableSignalsGuard {
fn drop(&mut self) {
if !self.active {
return;
}
unsafe {
let depth =
&mut (*Tcb::current().unwrap().os_specific.arch.get()).disable_signals_depth;
@@ -666,7 +673,7 @@ pub fn setup_sighandler(tcb: &RtTcb, first_thread: bool) {
let fd = tcb
.thread_fd()
.dup(b"sighandler")
.dup_into_upper(b"sighandler")
.expect("failed to open sighandler fd");
fd.write(&data).expect("failed to write to sighandler fd");
this_thread_call(
+1453 -25
View File
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -10,12 +10,12 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize, tcb: &RtTcb) -> Result<usize> {
let cur_proc_fd = proc_info.proc_fd.as_ref().unwrap();
let cur_thr_fd = RtTcb::current().thread_fd();
let new_thr_fd = cur_proc_fd.dup(b"new-thread")?.to_upper().unwrap();
let new_thr_fd = cur_proc_fd.dup_into_upper(b"new-thread")?;
// Inherit existing address space
{
let cur_addr_space_fd = cur_thr_fd.dup(b"addrspace")?;
let new_addr_space_sel_fd = new_thr_fd.dup(b"current-addrspace")?;
let cur_addr_space_fd = cur_thr_fd.dup_into_upper(b"addrspace")?;
let new_addr_space_sel_fd = new_thr_fd.dup_into_upper(b"current-addrspace")?;
let buf = create_set_addr_space_buf(
cur_addr_space_fd.as_raw_fd(),
@@ -27,8 +27,8 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize, tcb: &RtTcb) -> Result<usize> {
// Inherit reference to file table
{
let cur_filetable_fd = cur_thr_fd.dup(b"filetable")?;
let new_filetable_sel_fd = new_thr_fd.dup(b"current-filetable")?;
let cur_filetable_fd = cur_thr_fd.dup_into_upper(b"filetable")?;
let new_filetable_sel_fd = new_thr_fd.dup_into_upper(b"current-filetable")?;
new_filetable_sel_fd.write(&usize::to_ne_bytes(cur_filetable_fd.as_raw_fd()))?;
}
@@ -38,7 +38,7 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize, tcb: &RtTcb) -> Result<usize> {
// the same process) will be discarded. Process-specific signals will ignore this new thread,
// until it has initialized its own signal handler.
let start_fd = new_thr_fd.dup(b"start")?;
let start_fd = new_thr_fd.dup_into_upper(b"start")?;
let fd = new_thr_fd.as_raw_fd();
unsafe {
@@ -56,9 +56,12 @@ pub unsafe fn exit_this_thread(stack_base: *mut (), stack_size: usize) -> ! {
let tcb = RtTcb::current();
// TODO: modify interface so it writes directly to the thread fd?
let status_fd = tcb.thread_fd().dup(b"status").unwrap();
let status_fd = tcb.thread_fd().dup_into_upper(b"status").unwrap();
let _ = unsafe { syscall::funmap(tcb as *const RtTcb as usize, syscall::PAGE_SIZE) };
let tcb_ptr = unsafe { crate::Tcb::current_ptr() };
if let Some(tcb_ptr) = tcb_ptr {
let _ = unsafe { syscall::funmap(tcb_ptr as usize, syscall::PAGE_SIZE) };
}
let mut buf = [0; size_of::<usize>() * 3];
plain::slice_from_mut_bytes(&mut buf)
+2 -2
View File
@@ -18,7 +18,7 @@ mod drm;
// TODO: some of the structs passed as T have padding bytes, so casting to a byte slice is UB
fn dup_read<T>(fd: c_int, name: &str, t: &mut T) -> syscall::Result<usize> {
let dup = FdGuard::new(syscall::dup(fd as usize, name.as_bytes())?);
let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?);
let size = mem::size_of::<T>();
@@ -29,7 +29,7 @@ fn dup_read<T>(fd: c_int, name: &str, t: &mut T) -> syscall::Result<usize> {
// FIXME: unsound
fn dup_write<T>(fd: c_int, name: &str, t: &T) -> Result<usize> {
let dup = FdGuard::new(syscall::dup(fd as usize, name.as_bytes())?);
let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?);
let size = mem::size_of::<T>();
+2 -2
View File
@@ -159,7 +159,7 @@ pub unsafe fn init(
{
let file = thr_fd
.dup(b"regs/env")
.dup_into_upper(b"regs/env")
.expect_notls("failed to open handle for process registers");
file.read(&mut env).expect_notls("failed to read gsbase");
@@ -173,7 +173,7 @@ pub unsafe fn init(
{
let file = thr_fd
.dup(b"regs/env")
.dup_into_upper(b"regs/env")
.expect_notls("failed to open handle for process registers");
file.read(&mut env).expect_notls("failed to read fsbase");
+17
View File
@@ -317,6 +317,23 @@ fn stage2(
let thr_fd = crate::platform::get_auxv_raw(auxv, redox_rt::auxv_defs::AT_REDOX_THR_FD)
.expect_notls("no thread fd present");
#[cfg(target_os = "redox")]
{
if redox_rt::current_filetable().fd().is_none() {
let filetable_fd = crate::platform::get_auxv_raw(
sp.auxv().cast(),
redox_rt::auxv_defs::AT_REDOX_FILETABLE_FD,
)
.expect_notls("no filetable fd present");
let filetable_guard = redox_rt::proc::FdGuard::new(filetable_fd)
.to_upper()
.expect_notls("failed to move filetable fd to upper table");
*redox_rt::current_filetable() =
redox_rt::sys::FdTbl::from_binary_fd(filetable_guard)
.expect_notls("failed to initialize FILETABLE");
}
}
let tcb = Tcb::new(0).expect_notls("[ld.so]: failed to allocate bootstrap TCB");
tcb.activate(
#[cfg(target_os = "redox")]
+3
View File
@@ -58,3 +58,6 @@ pub const AT_REDOX_NS_FD: usize = 43;
#[cfg(target_os = "redox")]
pub const AT_REDOX_CWD_FD: usize = 44;
#[cfg(target_os = "redox")]
pub const AT_REDOX_FILETABLE_FD: usize = 45;
+1 -1
View File
@@ -83,5 +83,5 @@ pub unsafe extern "C" fn redox_event_queue_ctl_v1(
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_event_queue_destroy_v1(queue: usize) -> RawResult {
Error::mux(syscall::close(queue))
Error::mux(redox_rt::sys::close(queue))
}
+8
View File
@@ -41,6 +41,10 @@ fn fexec_impl(
)?
.unwrap();
if let Some(filetable_fd) = extrainfo.filetable_fd {
let _ = redox_rt::sys::close(filetable_fd);
}
// According to elf(5), PT_INTERP requires that the interpreter path be
// null-terminated. Violating this should therefore give the "format error" ENOEXEC.
let path_cstr = CStr::from_bytes_with_nul(&path).map_err(|_| Error::new(ENOEXEC))?;
@@ -228,6 +232,9 @@ pub fn execve(
let sigprocmask = redox_rt::signal::get_sigmask().unwrap();
let filetable_binary_fd = RtTcb::current()
.thread_fd()
.dup_into_upper(b"filetable-binary")?;
let extrainfo = ExtraInfo {
cwd: Some(cwd.as_bytes()),
sigignmask: redox_rt::signal::get_sigignmask_to_inherit(),
@@ -239,6 +246,7 @@ pub fn execve(
cwd_fd: super::path::current_dir()
.ok()
.map(|fd| fd.as_ref().unwrap().fd.as_raw_fd()),
filetable_fd: Some(filetable_binary_fd.as_raw_fd()),
same_process: true,
};
+3 -3
View File
@@ -38,9 +38,9 @@ pub fn open(path: &str, flags: usize) -> Result<usize> {
// Linux seems to allow you to read from or write to any of /dev/{stdin,stderr,stdout}
match basename {
"stderr" => syscall::dup(2, &[]),
"stdin" => syscall::dup(0, &[]),
"stdout" => syscall::dup(1, &[]),
"stderr" => redox_rt::sys::dup(2, &[]),
"stdin" => redox_rt::sys::dup(0, &[]),
"stdout" => redox_rt::sys::dup(1, &[]),
"tty" => {
if let Some(tty) = env_str!("TTY") {
return redox_rt::sys::open(tty, flags);
+22 -11
View File
@@ -32,7 +32,7 @@ pub fn openat(dirfd: c_int, path: &str, oflag: c_int, mode: mode_t) -> Result<us
c_int::try_from(usize_fd)
.map_err(|_| {
let _ = syscall::close(usize_fd);
let _ = redox_rt::sys::close(usize_fd);
Error::new(EMFILE)
})
.map(|f| f as usize)
@@ -241,7 +241,7 @@ pub unsafe extern "C" fn redox_openat_v1(
flags: u32,
fcntl_flags: u32,
) -> RawResult {
Error::mux(syscall::openat(
Error::mux(redox_rt::sys::openat(
fd,
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)) },
flags as usize,
@@ -250,7 +250,7 @@ pub unsafe extern "C" fn redox_openat_v1(
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_dup_v1(fd: usize, buf: *const u8, len: usize) -> RawResult {
Error::mux(syscall::dup(fd, unsafe {
Error::mux(redox_rt::sys::dup(fd, unsafe {
core::slice::from_raw_parts(buf, len)
}))
}
@@ -261,7 +261,7 @@ pub unsafe extern "C" fn redox_dup2_v1(
buf: *const u8,
len: usize,
) -> RawResult {
Error::mux(syscall::dup2(old_fd, new_fd, unsafe {
Error::mux(redox_rt::sys::dup2(old_fd, new_fd, unsafe {
core::slice::from_raw_parts(buf, len)
}))
}
@@ -359,7 +359,7 @@ pub unsafe extern "C" fn redox_fpath_v1(fd: usize, dst_base: *mut u8, dst_len: u
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_close_v1(fd: usize) -> RawResult {
Error::mux(syscall::close(fd))
Error::mux(redox_rt::sys::close(fd))
}
#[unsafe(no_mangle)]
@@ -569,12 +569,18 @@ pub unsafe extern "C" fn redox_sys_call_v0(
metadata: *const u64,
metadata_len: usize,
) -> RawResult {
Error::mux(redox_rt::sys::sys_call(
fd,
unsafe { slice::from_raw_parts_mut(payload, payload_len) },
syscall::CallFlags::from_bits_retain(flags),
unsafe { slice::from_raw_parts(metadata, metadata_len) },
))
let flags = syscall::CallFlags::from_bits_retain(flags);
let read = flags.contains(syscall::CallFlags::READ);
let write = flags.contains(syscall::CallFlags::WRITE);
let payload = unsafe { slice::from_raw_parts_mut(payload, payload_len) };
let metadata = unsafe { slice::from_raw_parts(metadata, metadata_len) };
Error::mux(match (read, write) {
(true, true) => redox_rt::sys::sys_call_rw(fd, payload, flags, metadata),
(true, false) => redox_rt::sys::sys_call_ro(fd, payload, flags, metadata),
(false, true) => redox_rt::sys::sys_call_wo(fd, payload, flags, metadata),
(false, false) => redox_rt::sys::sys_call(fd, payload, flags, metadata),
})
}
#[unsafe(no_mangle)]
@@ -630,3 +636,8 @@ pub unsafe extern "C" fn redox_relpathat_v0(
&StdFsCallMeta::new(StdFsCallKind::Relpathat, 0, 0),
))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_fcntl_v0(fd: usize, cmd: usize, arg: usize) -> RawResult {
Error::mux(redox_rt::sys::fcntl(fd, cmd, arg))
}
+59 -23
View File
@@ -239,12 +239,12 @@ impl Pal for Sys {
}
fn close(fd: c_int) -> Result<()> {
syscall::close(fd as usize)?;
redox_rt::sys::close(fd as usize)?;
Ok(())
}
fn dup2(fd1: c_int, fd2: c_int) -> Result<c_int> {
Ok(syscall::dup2(fd1 as usize, fd2 as usize, &[])? as c_int)
Ok(redox_rt::sys::dup2(fd1 as usize, fd2 as usize, &[])? as c_int)
}
fn exit(status: c_int) -> ! {
@@ -442,7 +442,7 @@ impl Pal for Sys {
_ => {}
}
Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
Ok(redox_rt::sys::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
}
fn fdatasync(fd: c_int) -> Result<()> {
@@ -484,7 +484,7 @@ impl Pal for Sys {
let file = openat2(dirfd, path, flags, fcntl::O_PATH)?;
// Close the file descriptor after fstat(2) regardless of success or failure.
let fstat_res = unsafe { libredox::fstat(*file as usize, buf.as_mut_ptr()) };
let close_res = syscall::close(*file as usize);
let close_res = redox_rt::sys::close(*file as usize);
if let Err(err) = fstat_res {
return Err(err.into());
}
@@ -664,7 +664,7 @@ impl Pal for Sys {
"/scheme/rand"
};
let mut open_flags = syscall::O_RDONLY | syscall::O_CLOEXEC;
let mut open_flags = syscall::O_RDONLY | redox_protocols::protocol::O_CLOEXEC;
if flags & sys_random::GRND_NONBLOCK != 0 {
open_flags |= syscall::O_NONBLOCK;
}
@@ -1215,13 +1215,11 @@ impl Pal for Sys {
let mut cwd_fd = FdGuard::open(cwd.as_str(), syscall::O_STAT)?.to_upper()?;
let proc_fd = child.proc_fd.unwrap();
let curr_proc_fd = redox_rt::current_proc_fd();
let file_table = RtTcb::current()
.thread_fd()
.dup(b"filetable")?
.dup(b"copy")?;
let cur_filetable_fd = RtTcb::current().thread_fd().dup_into_upper(b"filetable")?;
let file_table = cur_filetable_fd.dup_into_upper(b"copy")?;
{
let new_file_table = child.thr_fd.dup(b"current-filetable")?;
let new_file_table = child.thr_fd.dup_into_upper(b"current-filetable")?;
new_file_table.write(&file_table.as_raw_fd().to_ne_bytes())?;
}
@@ -1240,7 +1238,7 @@ impl Pal for Sys {
args[0] = &program.to_bytes();
let new_file_table = child.thr_fd.dup(b"filetable")?;
let new_file_table = child.thr_fd.dup_into_upper(b"filetable-binary")?;
if let Some(fac) = fac {
for action in fac {
@@ -1262,11 +1260,10 @@ impl Pal for Sys {
flag,
mode,
)? as usize;
syscall::sendfd(
new_file_table.as_raw_fd(),
src_fd,
0,
u64::try_from(fd).map_err(|_| Errno(EBADFD))?,
new_file_table.call_wo(
&src_fd.to_ne_bytes(),
syscall::CallFlags::FD,
&[u64::try_from(fd).map_err(|_| Errno(EBADFD))?],
)?;
}
crate::header::spawn::Action::Close(fd) => {
@@ -1336,9 +1333,47 @@ impl Pal for Sys {
// );
new_file_table.call_wo(
&[],
syscall::CallFlags::empty(),
&[syscall::flag::FileTableVerb::CloseCloExec as u64],
&new_file_table.as_raw_fd().to_ne_bytes(),
syscall::CallFlags::FD | syscall::CallFlags::FD_CLONE,
&[new_file_table.as_raw_fd() as u64],
)?;
{
let fds_to_close = {
let guard = redox_rt::current_filetable();
let mut fds = alloc::vec::Vec::new();
for (fd, flags) in guard.iter() {
if flags & redox_protocols::protocol::O_CLOEXEC
== redox_protocols::protocol::O_CLOEXEC
|| fd == executable.as_raw_fd()
{
fds.push(fd);
}
}
fds.push(cur_filetable_fd.as_raw_fd());
fds
};
let fds_to_close_bytes: &[u8] = unsafe {
core::slice::from_raw_parts(
fds_to_close.as_ptr() as *mut u8,
fds_to_close.len() * core::mem::size_of::<usize>(),
)
};
let _ = new_file_table.call_wo(
fds_to_close_bytes,
syscall::CallFlags::empty(),
&[syscall::FileTableVerb::Close as u64],
);
}
new_file_table.call_wo(
&cwd_fd.as_raw_fd().to_ne_bytes(),
syscall::CallFlags::FD | syscall::CallFlags::FD_CLONE,
&[cwd_fd.as_raw_fd() as u64],
)?;
let extra_info = redox_rt::proc::ExtraInfo {
@@ -1360,6 +1395,7 @@ impl Pal for Sys {
proc_fd: proc_fd.as_raw_fd(),
ns_fd: redox_rt::current_namespace_fd().ok(),
cwd_fd: Some(cwd_fd.as_raw_fd()),
filetable_fd: Some(new_file_table.as_raw_fd()),
same_process: false,
};
@@ -1460,7 +1496,7 @@ impl Pal for Sys {
.unwrap();
}
let start_fd = child.thr_fd.dup(b"start")?;
let start_fd = child.thr_fd.dup_into_upper(b"start")?;
start_fd.write(&[0])?;
Ok(pid_t::try_from(child.pid).unwrap())
@@ -1507,7 +1543,7 @@ impl Pal for Sys {
CLOCK_MONOTONIC => "/scheme/time/4",
_ => return Err(Errno(EINVAL)),
};
let timerfd = FdGuard::open(&path, syscall::O_RDWR)?.to_upper()?;
let timerfd = FdGuard::open_into_upper(&path, syscall::O_RDWR)?;
let eventfd = FdGuard::new(Error::demux(unsafe {
event::redox_event_queue_create_v1(0)
})?)
@@ -1561,8 +1597,8 @@ impl Pal for Sys {
return Err(Errno(EINVAL));
}
let timer_st = unsafe { timer_internal_t::from_raw(timerid) };
let _ = syscall::close(timer_st.timerfd);
let _ = syscall::close(timer_st.eventfd);
let _ = redox_rt::sys::close(timer_st.timerfd);
let _ = redox_rt::sys::close(timer_st.eventfd);
if !timer_st.thread.is_null() {
let _ = unsafe { pthread_cancel(timer_st.thread) };
}
+3 -4
View File
@@ -9,6 +9,7 @@ use core::{
ffi::c_int,
str::{self, FromStr},
};
use redox_protocols::protocol::O_CLOEXEC;
use redox_rt::{proc::FdGuardUpper, signal::tmp_disable_signals};
use syscall::{data::Stat, error::*, flag::*};
@@ -97,9 +98,7 @@ pub fn chdir(path: &str) -> Result<()> {
.as_ref()
.unwrap()
.fd
.openat(&path, O_STAT, 0)?
.to_upper()
.unwrap();
.openat_into_upper(&path, O_STAT, 0)?;
let mut stat = Stat::default();
if fd.fstat(&mut stat).is_err() || (stat.st_mode & MODE_TYPE) != MODE_DIR {
return Err(Error::new(ENOTDIR));
@@ -138,7 +137,7 @@ pub fn fchdir(fd: c_int) -> Result<()> {
let res = Sys::fpath(fd, buf.as_bytes_mut())?;
buf.set_len(res);
}
let fd = FdGuard::new(syscall::fcntl(
let fd = FdGuard::new(redox_rt::sys::fcntl(
fd as usize,
syscall::F_DUPFD,
syscall::UPPER_FDTBL_TAG,
+16 -9
View File
@@ -1,6 +1,6 @@
use alloc::vec::Vec;
use core::{cmp, mem, ptr, slice, str};
use redox_protocols::protocol::{FsCall, SocketCall};
use redox_protocols::protocol::{FsCall, O_CLOEXEC, SocketCall};
use redox_rt::proc::FdGuard;
use syscall::{self, flag::*};
@@ -83,7 +83,7 @@ unsafe fn bind_or_connect(
},
_ => return Err(Errno(EAFNOSUPPORT)),
};
let fd = syscall::dup(socket as usize, path.as_bytes())?;
let fd = redox_rt::sys::dup(socket as usize, path.as_bytes())?;
Ok(fd)
}
@@ -95,7 +95,7 @@ pub unsafe fn bind_or_connect_into(
) -> Result<c_int, Errno> {
// Duplicate the socket, and then duplicate the copy back to the original fd
let fd = FdGuard::new(unsafe { bind_or_connect(op, socket, address, address_len) }?);
syscall::dup2(fd.as_raw_fd(), socket as usize, &[])?;
redox_rt::sys::dup2(fd.as_raw_fd(), socket as usize, &[])?;
Ok(0)
}
@@ -537,10 +537,10 @@ impl PalSocket for Sys {
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> Result<c_int> {
let stream = syscall::dup(socket as usize, b"listen")?;
let stream = redox_rt::sys::dup(socket as usize, b"listen")?;
if address != ptr::null_mut() && address_len != ptr::null_mut() {
if let Err(err) = unsafe { Self::getpeername(stream as c_int, address, address_len) } {
let _ = syscall::close(stream);
let _ = redox_rt::sys::close(stream);
return Err(err);
}
}
@@ -588,10 +588,17 @@ impl PalSocket for Sys {
let fs_bind_result = (|| -> Result<()> {
let dirfd = FdGuard::open(
&dir_path,
syscall::O_RDONLY | syscall::O_DIRECTORY | syscall::O_CLOEXEC,
syscall::O_RDONLY | syscall::O_DIRECTORY | O_CLOEXEC,
)?;
let fd_to_send =
FdGuard::new(redox_rt::sys::dup_into_upper(socket as usize, &[])?)
.to_upper()
.unwrap();
dirfd.call_wo(
&fd_to_send.as_raw_fd().to_ne_bytes(),
syscall::CallFlags::FD,
&[],
)?;
let fd_to_send = FdGuard::new(syscall::dup(socket as usize, &[])?);
syscall::sendfd(dirfd.as_raw_fd(), fd_to_send.as_raw_fd(), 0, 0)?;
Ok(())
})();
@@ -1027,7 +1034,7 @@ impl PalSocket for Sys {
let timeval = unsafe { &*(option_value as *const timeval) };
let fd = FdGuard::new(syscall::dup(socket as usize, timeout_name)?);
let fd = FdGuard::new(redox_rt::sys::dup(socket as usize, timeout_name)?);
let Some(tv_nsec) = timeval.tv_usec.checked_mul(1000) else {
return Err(Errno(EDOM));
+18
View File
@@ -174,6 +174,24 @@ pub unsafe extern "C" fn relibc_start_v1(
.to_upper()
.expect_notls("failed to move thread fd to upper table");
#[cfg(target_os = "redox")]
{
if redox_rt::current_filetable().fd().is_none() {
let filetable_fd = unsafe {
crate::platform::get_auxv_raw(
sp.auxv().cast(),
redox_rt::auxv_defs::AT_REDOX_FILETABLE_FD,
)
}
.expect_notls("no filetable fd present");
let filetable_guard = redox_rt::proc::FdGuard::new(filetable_fd)
.to_upper()
.expect_notls("failed to move filetable fd to upper table");
*redox_rt::current_filetable() = redox_rt::sys::FdTbl::from_binary_fd(filetable_guard)
.expect_notls("failed to initialize FILETABLE");
}
}
// Initialize TLS, if necessary
unsafe {
ld_so::init(