WIP: use upper fd table

This commit is contained in:
Jeremy Soller
2025-11-14 12:31:48 -07:00
parent 74e3ad1c2c
commit 0844e6fc90
25 changed files with 404 additions and 451 deletions
+4 -1
View File
@@ -419,7 +419,10 @@ unsafe fn find_env(search: *const c_char) -> Option<(usize, *mut c_char)> {
let mut search = search;
loop {
let end_of_query = *search == 0 || *search == b'=' as c_char;
assert_ne!(*item, 0, "environ has an item without value");
if *item == 0 {
//TODO: environ has an item without value, is this a problem?
break;
}
if *item == b'=' as c_char || end_of_query {
if *item == b'=' as c_char && end_of_query {
// Both keys env here
+5 -11
View File
@@ -41,17 +41,13 @@ pub const SIOCATMARK: c_ulong = 0x8905;
// 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 = syscall::dup(fd as usize, name.as_bytes())?;
let dup = FdGuard::new(syscall::dup(fd as usize, name.as_bytes())?);
let size = mem::size_of::<T>();
let res = syscall::read(dup, unsafe {
slice::from_raw_parts_mut(t as *mut T as *mut u8, size)
});
let bytes = dup.read(unsafe { slice::from_raw_parts_mut(t as *mut T as *mut u8, size) })?;
let _ = syscall::close(dup);
res.map(|bytes| bytes / size)
Ok(bytes / size)
}
// FIXME: unsound
@@ -60,11 +56,9 @@ fn dup_write<T>(fd: c_int, name: &str, t: &T) -> Result<usize> {
let size = mem::size_of::<T>();
let bytes_written = syscall::write(*dup, unsafe {
slice::from_raw_parts(t as *const T as *const u8, size)
})?;
let bytes = dup.write(unsafe { slice::from_raw_parts(t as *const T as *const u8, size) })?;
Ok(bytes_written / size)
Ok(bytes / size)
}
unsafe fn ioctl_inner(fd: c_int, request: c_ulong, out: *mut c_void) -> Result<c_int> {
+5 -5
View File
@@ -579,14 +579,14 @@ impl DSO {
}
}
};
let voff = ph.p_vaddr(endian) % ph.p_align(endian);
let vsize = ((ph.p_memsz(endian) + voff) as usize)
let _voff = ph.p_vaddr(endian) % ph.p_align(endian);
let _vsize = ((ph.p_memsz(endian) + _voff) as usize)
.next_multiple_of(ph.p_align(endian) as usize);
trace!(
" copy {:#x}, {:#x}: {:#x}, {:#x}",
ph.p_vaddr(endian) - voff,
vsize,
voff,
ph.p_vaddr(endian) - _voff,
_vsize,
_voff,
obj_data.len()
);
mmap_data.copy_from_slice(obj_data);
+14 -12
View File
@@ -40,7 +40,7 @@ static mut STATIC_TCB_MASTER: Master = Master {
#[inline(never)]
pub fn static_init(
sp: &'static Stack,
#[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard,
#[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuardUpper,
) {
const SIZEOF_PHDR64: usize = mem::size_of::<ProgramHeader64<Endianness>>();
const SIZEOF_PHDR32: usize = mem::size_of::<ProgramHeader32<Endianness>>();
@@ -135,7 +135,7 @@ pub fn static_init(
#[cfg(any(target_os = "linux", target_os = "redox"))]
pub unsafe fn init(
sp: &'static Stack,
#[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard,
#[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuardUpper,
) {
let tp: usize;
@@ -157,12 +157,13 @@ pub unsafe fn init(
{
let mut env = syscall::EnvRegisters::default();
let file = syscall::dup(*thr_fd, b"regs/env")
.expect_notls("failed to open handle for process registers");
{
let file = thr_fd
.dup(b"regs/env")
.expect_notls("failed to open handle for process registers");
let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase");
let _ = syscall::close(file);
file.read(&mut env).expect_notls("failed to read gsbase");
}
tp = env.gsbase as usize;
}
@@ -170,12 +171,13 @@ pub unsafe fn init(
{
let mut env = syscall::EnvRegisters::default();
let file = syscall::dup(*thr_fd, b"regs/env")
.expect_notls("failed to open handle for process registers");
{
let file = thr_fd
.dup(b"regs/env")
.expect_notls("failed to open handle for process registers");
let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase");
let _ = syscall::close(file);
file.read(&mut env).expect_notls("failed to read fsbase");
}
tp = env.fsbase as usize;
}
+8 -2
View File
@@ -163,7 +163,9 @@ pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: us
let tcb = Tcb::new(0).expect_notls("ld.so: failed to allocate bootstrap TCB");
tcb.activate(
#[cfg(target_os = "redox")]
redox_rt::proc::FdGuard::new(thr_fd),
redox_rt::proc::FdGuard::new(thr_fd)
.to_upper()
.expect_notls("failed to move thread fd to upper table"),
);
#[cfg(target_os = "redox")]
{
@@ -173,7 +175,11 @@ pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: us
)
.expect_notls("no proc fd present");
redox_rt::initialize(redox_rt::proc::FdGuard::new(proc_fd));
redox_rt::initialize(
redox_rt::proc::FdGuard::new(proc_fd)
.to_upper()
.expect_notls("failed to move proc fd to upper table"),
);
redox_rt::signal::setup_sighandler(&tcb.os_specific, true);
}
}
+5 -2
View File
@@ -205,7 +205,10 @@ impl Tcb {
}
/// Activate TLS
pub unsafe fn activate(&mut self, #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard) {
pub unsafe fn activate(
&mut self,
#[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuardUpper,
) {
unsafe {
Self::os_arch_activate(
&self.os_specific,
@@ -345,7 +348,7 @@ impl Tcb {
os: &OsSpecific,
tls_end: usize,
tls_len: usize,
thr_fd: redox_rt::proc::FdGuard,
thr_fd: redox_rt::proc::FdGuardUpper,
) {
unsafe {
os.thr_fd.get().write(Some(thr_fd));
+1 -1
View File
@@ -334,7 +334,7 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) {
let Some(proc_fd) = get_auxv(&auxvs, AT_REDOX_PROC_FD) else {
panic!("Missing proc and thread fd!");
};
redox_rt::initialize(FdGuard::new(proc_fd));
redox_rt::initialize(FdGuard::new(proc_fd).to_upper().unwrap());
// TODO: Is it safe to assume setup_sighandler has been called at this point?
redox_rt::sys::this_proc_call(
+13 -8
View File
@@ -16,13 +16,13 @@ use crate::{
use redox_rt::{
RtTcb,
proc::{ExtraInfo, FdGuard, FexecResult, InterpOverride},
proc::{ExtraInfo, FdGuard, FdGuardUpper, FexecResult, InterpOverride},
sys::Resugid,
};
use syscall::{data::Stat, error::*, flag::*};
fn fexec_impl(
exec_file: FdGuard,
exec_file: FdGuardUpper,
path: &[u8],
args: &[&[u8]],
envs: &[&[u8]],
@@ -30,7 +30,7 @@ fn fexec_impl(
extrainfo: &ExtraInfo,
interp_override: Option<InterpOverride>,
) -> Result<Infallible> {
let memory = FdGuard::new(syscall::open("/scheme/memory", 0)?);
let memory = FdGuard::open("/scheme/memory", 0)?.to_upper()?;
let addrspace_selection_fd = match redox_rt::proc::fexec_impl(
exec_file,
@@ -231,8 +231,13 @@ pub fn execve(
// 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 =
File::new(syscall::dup(**RtTcb::current().thread_fd(), b"filetable")? as c_int);
let files_fd = File::new(
c_int::try_from(syscall::dup(
RtTcb::current().thread_fd().as_raw_fd(),
b"filetable",
)?)
.unwrap(),
);
for line in BufReader::new(files_fd).lines() {
let line = match line {
Ok(l) => l,
@@ -252,7 +257,7 @@ pub fn execve(
}
// TODO: Convert image_file to FdGuard earlier?
let exec_fd_guard = FdGuard::new(image_file.fd as usize);
let exec_fd_guard = FdGuard::new(image_file.fd as usize).to_upper().unwrap();
core::mem::forget(image_file);
let sigprocmask = redox_rt::signal::get_sigmask().unwrap();
@@ -263,8 +268,8 @@ pub fn execve(
sigignmask: redox_rt::signal::get_sigignmask_to_inherit(),
sigprocmask,
umask: redox_rt::sys::get_umask(),
thr_fd: **RtTcb::current().thread_fd(),
proc_fd: **redox_rt::current_proc_fd(),
thr_fd: RtTcb::current().thread_fd().as_raw_fd(),
proc_fd: redox_rt::current_proc_fd().as_raw_fd(),
};
fexec_impl(
exec_fd_guard,
+6 -6
View File
@@ -22,14 +22,14 @@ pub unsafe extern "C" fn redox_fpath(fd: c_int, buf: *mut c_void, count: size_t)
pub fn pipe2(flags: usize) -> syscall::error::Result<[c_int; 2]> {
let read_flags = flags | O_RDONLY;
let write_flags = flags | O_WRONLY;
let mut read_fd = FdGuard::new(syscall::open("/scheme/pipe", read_flags)?);
let mut write_fd = FdGuard::new(syscall::dup(*read_fd, b"write")?);
syscall::fcntl(*write_fd, F_SETFL, write_flags)?;
syscall::fcntl(*write_fd, F_SETFD, write_flags)?;
let mut read_fd = FdGuard::open("/scheme/pipe", read_flags)?;
let mut write_fd = read_fd.dup(b"write")?;
write_fd.fcntl(F_SETFL, write_flags)?;
write_fd.fcntl(F_SETFD, write_flags)?;
let fds = [
c_int::try_from(*read_fd).map_err(|_| Error::new(EMFILE))?,
c_int::try_from(*write_fd).map_err(|_| Error::new(EMFILE))?,
c_int::try_from(read_fd.as_raw_fd()).map_err(|_| Error::new(EMFILE))?,
c_int::try_from(write_fd.as_raw_fd()).map_err(|_| Error::new(EMFILE))?,
];
read_fd.take();
+3 -2
View File
@@ -146,6 +146,7 @@ pub unsafe extern "C" fn redox_openat_v1(
fd,
str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)),
flags as usize,
0, //TODO: openat fcntl_flags
))
}
#[unsafe(no_mangle)]
@@ -386,12 +387,12 @@ pub unsafe extern "C" fn redox_mkns_v1(
// ABI-UNSTABLE
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_cur_procfd_v0() -> usize {
**redox_rt::current_proc_fd()
redox_rt::current_proc_fd().as_raw_fd()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_cur_thrfd_v0() -> usize {
**redox_rt::RtTcb::current().thread_fd()
redox_rt::RtTcb::current().thread_fd().as_raw_fd()
}
#[unsafe(no_mangle)]
+7 -7
View File
@@ -112,7 +112,7 @@ impl Pal for Sys {
let mut stat = syscall::Stat::default();
syscall::fstat(*fd as usize, &mut stat)?;
fd.fstat(&mut stat)?;
let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid();
@@ -500,8 +500,8 @@ impl Pal for Sys {
}
//TODO: store fd internally
let fd = FdGuard::new(syscall::open(path, open_flags)?);
Ok(syscall::read(*fd, buf)?)
let fd = FdGuard::open(path, open_flags)?;
Ok(fd.read(buf)?)
}
fn getresgid(
@@ -578,8 +578,8 @@ impl Pal for Sys {
fn gettid() -> pid_t {
// This is used by pthread mutexes for reentrant checks and must be nonzero
// and unique for each thread in the same process (but not cross-process)
Self::current_os_tid()
.thread_fd
let thread_fd = Self::current_os_tid().thread_fd;
(thread_fd & !syscall::UPPER_FDTBL_TAG)
.checked_add(1)
.unwrap()
.try_into()
@@ -861,7 +861,7 @@ impl Pal for Sys {
}
fn current_os_tid() -> crate::pthread::OsTid {
crate::pthread::OsTid {
thread_fd: **RtTcb::current().thread_fd(),
thread_fd: RtTcb::current().thread_fd().as_raw_fd(),
}
}
@@ -1070,7 +1070,7 @@ impl Pal for Sys {
}
let path = format!("/scheme/time/{clock_id}");
let timerfd = FdGuard::new(libredox::open(&path, O_RDWR, 0)?);
let timerfd = FdGuard::open(&path, syscall::O_RDWR)?;
let eventfd = FdGuard::new(Error::demux(unsafe {
event::redox_event_queue_create_v1(0)
})?);
+1 -1
View File
@@ -156,7 +156,7 @@ pub fn open(path: &str, flags: usize) -> Result<usize> {
let resolve_flags = O_CLOEXEC | O_SYMLINK | O_RDONLY;
let resolve_fd = FdGuard::new(syscall::open(&*canon, resolve_flags)?);
let bytes_read = syscall::read(*resolve_fd, &mut resolve_buf)?;
let bytes_read = resolve_fd.read(&mut resolve_buf)?;
// TODO: make resolve_buf PATH_MAX + 1 bytes?
if bytes_read == resolve_buf.len() {
return Err(Error::new(ENAMETOOLONG));
+21 -17
View File
@@ -281,7 +281,7 @@ unsafe fn serialize_ancillary_data_to_stream(
let fds_slice = slice::from_raw_parts(fds_ptr, fd_count);
for &fd in fds_slice.iter() {
let fd_to_send = FdGuard::new(syscall::dup(fd as usize, b"")?);
syscall::sendfd(socket as usize, *fd_to_send as usize, 0, 0)?;
syscall::sendfd(socket as usize, fd_to_send.as_raw_fd(), 0, 0)?;
}
}
@@ -562,12 +562,12 @@ impl PalSocket for Sys {
)?;
let fs_bind_result = (|| -> Result<()> {
let dirfd = FdGuard::new(syscall::open(
let dirfd = FdGuard::open(
&dir_path,
syscall::O_RDONLY | syscall::O_DIRECTORY | syscall::O_CLOEXEC,
)?);
)?;
let fd_to_send = FdGuard::new(syscall::dup(socket as usize, &[])?);
let _ = syscall::sendfd(*dirfd, *fd_to_send, 0, 0)?;
syscall::sendfd(dirfd.as_raw_fd(), fd_to_send.as_raw_fd(), 0, 0)?;
Ok(())
})();
@@ -628,14 +628,14 @@ impl PalSocket for Sys {
let (_, fd_path) = dir_path_and_fd_path(&path)?;
let target_path = format!("/{fd_path}");
let socket_file_fd = FdGuard::new(syscall::open(&target_path, syscall::O_RDWR)?);
let socket_file_fd = FdGuard::open(&target_path, syscall::O_RDWR)?;
const TOKEN_BUF_SIZE: usize = 16;
let mut token_buf = [0u8; TOKEN_BUF_SIZE];
redox_rt::sys::sys_call(
*socket_file_fd,
socket_file_fd.as_raw_fd(),
&mut token_buf,
CallFlags::empty(),
&[FsCall::Connect as u64],
@@ -809,9 +809,11 @@ impl PalSocket for Sys {
Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
} else {
let fd = FdGuard::new(syscall::dup(socket as usize, b"listen")?);
Self::getpeername(*fd as c_int, address, address_len)?;
Self::read(*fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len))
Self::getpeername(fd.as_c_fd().unwrap(), address, address_len)?;
Self::read(
fd.as_c_fd().unwrap(),
slice::from_raw_parts_mut(buf as *mut u8, len),
)
}
}
@@ -976,7 +978,10 @@ impl PalSocket for Sys {
Self::write(socket, slice::from_raw_parts(buf as *const u8, len))
} else {
let fd = FdGuard::new(bind_or_connect!(connect copy, socket, dest_addr, dest_len)?);
Self::write(*fd as c_int, slice::from_raw_parts(buf as *const u8, len))
Self::write(
fd.as_c_fd().unwrap(),
slice::from_raw_parts(buf as *const u8, len),
)
}
}
@@ -1009,7 +1014,7 @@ impl PalSocket for Sys {
tv_nsec,
};
Self::write(*fd as c_int, &timespec)?;
Self::write(fd.as_c_fd().unwrap(), &timespec)?;
Ok(())
};
@@ -1078,28 +1083,27 @@ impl PalSocket for Sys {
match (domain, kind) {
(AF_UNIX, SOCK_STREAM) => {
let listener = FdGuard::new(syscall::open("/scheme/uds_stream", flags | O_CREAT)?);
let listener = FdGuard::open("/scheme/uds_stream", flags | O_CREAT)?;
// For now, uds_stream: lets connects be instant, and instead blocks
// on any I/O performed. So we don't need to mark this as
// nonblocking.
let mut fd0 = FdGuard::new(syscall::dup(*listener, b"connect")?);
let mut fd1 = FdGuard::new(syscall::dup(*listener, b"listen")?);
let mut fd0 = listener.dup(b"connect")?;
let mut fd1 = listener.dup(b"listen")?;
sv[0] = fd0.take() as c_int;
sv[1] = fd1.take() as c_int;
Ok(())
}
(AF_UNIX, SOCK_DGRAM) => {
let listener = FdGuard::new(syscall::open("/scheme/uds_dgram", flags | O_CREAT)?);
let listener = FdGuard::open("/scheme/uds_dgram", flags | O_CREAT)?;
// For now, uds_dgram: lets connects be instant, and instead blocks
// on any I/O performed. So we don't need to mark this as
// nonblocking.
let mut fd0 = FdGuard::new(syscall::dup(*listener, b"connect")?);
let mut fd0 = listener.dup(b"connect")?;
sv[0] = fd0.take() as c_int;
sv[1] = listener.take() as c_int;
+5 -1
View File
@@ -229,7 +229,11 @@ unsafe extern "C" fn new_thread_shim(
}
#[cfg(target_os = "redox")]
{
tcb.activate(redox_rt::proc::FdGuard::new(tid.thread_fd));
tcb.activate(
redox_rt::proc::FdGuard::new(tid.thread_fd)
.to_upper()
.unwrap(),
);
redox_rt::signal::setup_sighandler(&tcb.os_specific, false);
}
}
+3 -1
View File
@@ -153,7 +153,9 @@ pub unsafe extern "C" fn relibc_start_v1(
let thr_fd = redox_rt::proc::FdGuard::new(
crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD)
.expect_notls("no thread fd present"),
);
)
.to_upper()
.expect_notls("failed to move thread fd to upper table");
// Initialize TLS, if necessary
ld_so::init(