From efa5b73015de5710ce925b893a1ca969c428f68c Mon Sep 17 00:00:00 2001 From: Ibuki Omatsu Date: Thu, 18 Dec 2025 01:32:07 +0000 Subject: [PATCH] refactor: Replace unlink and rmdir with unlinkat. Improve fork using ForkScratchPad. --- Cargo.lock | 14 ++++++---- Cargo.toml | 4 +-- redox-ioctl/Cargo.toml | 2 +- redox-rt/Cargo.toml | 3 +- redox-rt/src/arch/aarch64.rs | 20 +++++++------- redox-rt/src/arch/i686.rs | 17 ++++++------ redox-rt/src/arch/mod.rs | 8 ++++++ redox-rt/src/arch/riscv64.rs | 26 ++++++++---------- redox-rt/src/arch/x86_64.rs | 37 ++++++++++++------------- redox-rt/src/proc.rs | 53 +++++++++++++++++++++++++++++++----- redox-rt/src/sys.rs | 26 +++++++++++++++++- renamesyms.sh | 10 +++---- src/header/fcntl/redox.rs | 1 + src/platform/redox/mod.rs | 4 +-- 14 files changed, 148 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42bed02ac7..0db061bdcc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,9 +250,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" dependencies = [ "bitflags", "libc", @@ -439,13 +439,15 @@ dependencies = [ "generic-rt", "goblin", "plain", + "redox-path", "redox_syscall", ] [[package]] name = "redox_event" -version = "0.4.0" -source = "git+https://gitlab.redox-os.org/redox-os/event.git#36ac5a57a8573f7546d7dc0893596ebe99bd2b7f" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eafe403549fab08a0c0862769493ad992625bb5a694aae2df6901e7e4fd05a" dependencies = [ "bitflags", "libredox", @@ -454,8 +456,8 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.18" -source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#15aa8e32ef0f3328dd9d48cc8ca02e148a362069" +version = "0.6.0" +source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#1cf631ce3f36838ababdbd2b0190d93a6b64a31b" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index c5191f508e..b24e914694 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,10 +62,10 @@ features = ["c_api"] sc = "0.2.7" [target.'cfg(target_os = "redox")'.dependencies] -redox_syscall = "0.5.13" +redox_syscall = "0.6.0" redox-rt = { path = "redox-rt" } redox-path = "0.3" -redox_event = { git = "https://gitlab.redox-os.org/redox-os/event.git", default-features = false, features = [ +redox_event = { version = "0.4.2", default-features = false, features = [ "redox_syscall", ] } redox-ioctl = { path = "redox-ioctl" } diff --git a/redox-ioctl/Cargo.toml b/redox-ioctl/Cargo.toml index 1096248d3a..396b5a70bf 100644 --- a/redox-ioctl/Cargo.toml +++ b/redox-ioctl/Cargo.toml @@ -8,6 +8,6 @@ description = "Ioctl definitions and (de)serialization for Redox" [dependencies] drm-sys = "0.8.0" -redox_syscall = "0.5.8" +redox_syscall = "0.6.0" [features] diff --git a/redox-rt/Cargo.toml b/redox-rt/Cargo.toml index 4f8a910c12..3ccd0dc36a 100644 --- a/redox-rt/Cargo.toml +++ b/redox-rt/Cargo.toml @@ -12,7 +12,8 @@ description = "Libc-independent runtime for Redox" bitflags = "2" goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] } plain = "0.2" -redox_syscall = "0.5.8" +redox_syscall = "0.6.0" +redox-path = "0.3.0" generic-rt = { path = "../generic-rt" } diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index b34a2a74a3..51229b5edb 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -9,6 +9,8 @@ use crate::{ signal::{PROC_CONTROL_STRUCT, PosixStackt, RtSigarea, SigStack, inner_c}, }; +use super::ForkScratchpad; + // Setup a stack starting from the very end of the address space, and then growing downwards. pub const STACK_TOP: usize = 1 << 47; pub const STACK_SIZE: usize = 1024 * 1024; @@ -89,15 +91,15 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { +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(cur_filetable_fd); + let _ = syscall::close(scratchpad.cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { - new_thr_fd: FdGuard::new(new_thr_fd), - new_proc_fd: if new_proc_fd == usize::MAX { + new_thr_fd: FdGuard::new(scratchpad.new_thr_fd), + new_proc_fd: if scratchpad.new_proc_fd == usize::MAX { None } else { - Some(FdGuard::new(new_proc_fd)) + Some(FdGuard::new(scratchpad.new_proc_fd)) }, }); } @@ -110,15 +112,12 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" stp x21, x22, [sp, #-16]! stp x19, x20, [sp, #-16]! - sub sp, sp, #32 - //TODO: store floating point regs // x0: &ForkArgs mov x1, sp bl {fork_impl} - add sp, sp, #32 ldp x19, x20, [sp], #16 ldp x21, x22, [sp], #16 ldp x23, x24, [sp], #16 @@ -129,8 +128,9 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" "] <= [fork_impl = sym fork_impl]); asmfunction!(__relibc_internal_fork_ret: [" - ldp x0, x1, [sp], #16 - ldp x2, x3, [sp], #16 + # scratchpad is in x1, move to x0 for child_hook + mov x0, x1 + bl {child_hook} //TODO: load floating point regs diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 3733f4a87a..a2006895ae 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -9,6 +9,8 @@ use crate::{ signal::{PROC_CONTROL_STRUCT, PosixStackt, RtSigarea, SigStack, inner_fastcall}, }; +use super::ForkScratchpad; + // Setup a stack starting from the very end of the address space, and then growing downwards. pub const STACK_TOP: usize = 1 << 31; pub const STACK_SIZE: usize = 1024 * 1024; @@ -74,18 +76,14 @@ unsafe extern "fastcall" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) } // TODO: duplicate code with x86_64 -unsafe extern "cdecl" fn child_hook( - cur_filetable_fd: usize, - new_proc_fd: usize, - new_thr_fd: usize, -) { - let _ = syscall::close(cur_filetable_fd); +unsafe extern "cdecl" fn child_hook(scratchpad: ForkScratchpad) { + let _ = syscall::close(scratchpad.cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { - new_thr_fd: FdGuard::new(new_thr_fd), - new_proc_fd: if new_proc_fd == usize::MAX { + new_thr_fd: FdGuard::new(scratchpad.new_thr_fd), + new_proc_fd: if scratchpad.new_proc_fd == usize::MAX { None } else { - Some(FdGuard::new(new_proc_fd)) + Some(FdGuard::new(scratchpad.new_proc_fd)) }, }); } @@ -133,6 +131,7 @@ asmfunction!(__relibc_internal_fork_ret: [" pop ebx pop ebp + ret "] <= [child_hook = sym child_hook]); asmfunction!(__relibc_internal_sigentry: [" diff --git a/redox-rt/src/arch/mod.rs b/redox-rt/src/arch/mod.rs index 7f38e32bb9..282f28ed5d 100644 --- a/redox-rt/src/arch/mod.rs +++ b/redox-rt/src/arch/mod.rs @@ -17,3 +17,11 @@ pub mod x86_64; pub use self::riscv64::*; #[cfg(target_arch = "riscv64")] pub mod riscv64; + +#[derive(Debug)] +#[repr(C)] +pub struct ForkScratchpad { + pub cur_filetable_fd: usize, + pub new_proc_fd: usize, + pub new_thr_fd: usize, +} diff --git a/redox-rt/src/arch/riscv64.rs b/redox-rt/src/arch/riscv64.rs index d729a03e1b..ce3253edc5 100644 --- a/redox-rt/src/arch/riscv64.rs +++ b/redox-rt/src/arch/riscv64.rs @@ -9,6 +9,8 @@ use crate::{ use core::{mem::offset_of, ptr::NonNull, sync::atomic::Ordering}; use syscall::{data::*, error::*}; +use super::ForkScratchpad; + // Setup a stack starting from the very end of the address space, and then growing downwards. pub const STACK_TOP: usize = 1 << 47; pub const STACK_SIZE: usize = 1024 * 1024; @@ -65,14 +67,14 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { - let _ = syscall::close(cur_filetable_fd); +unsafe extern "C" fn child_hook(scratchpad: &ForkScratchpad) { + let _ = syscall::close(scratchpad.cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { - new_thr_fd: FdGuard::new(new_thr_fd), - new_proc_fd: if new_proc_fd == usize::MAX { + new_thr_fd: FdGuard::new(scratchpad.new_thr_fd), + new_proc_fd: if scratchpad.new_proc_fd == usize::MAX { None } else { - Some(FdGuard::new(new_proc_fd)) + Some(FdGuard::new(scratchpad.new_proc_fd)) }, }); } @@ -107,13 +109,10 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" fsd fs10, 184(sp) fsd fs11, 192(sp) - addi sp, sp, -32 // a0 is forwarded from this function mv a1, sp jal {fork_impl} - addi sp, sp, 32 - ld s0, 0(sp) ld s1, 8(sp) ld s2, 16(sp) @@ -147,14 +146,13 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" asmfunction!(__relibc_internal_fork_ret: [" .attribute arch, \"rv64gc\" # rust bug 80608 - ld a0, 0(sp) // cur_filetable_fd - ld a1, 8(sp) // new_proc_fd - ld a2, 16(sp) // new_thr_fd + + # scratchpad is in a1, move to a0 for child_hook + mv a0, a1 + jal {child_hook} - mv a0, x0 - - addi sp, sp, 32 + mv a0, zero ld s0, 0(sp) ld s1, 8(sp) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 2c92aec9d7..dc175c7827 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -17,6 +17,8 @@ use crate::{ signal::{PROC_CONTROL_STRUCT, PosixStackt, RtSigarea, SigStack, get_sigaltstack, inner_c}, }; +use super::ForkScratchpad; + // Setup a stack starting from the very end of the address space, and then growing downwards. pub const STACK_TOP: usize = 1 << 47; pub const STACK_SIZE: usize = 1024 * 1024; @@ -87,18 +89,14 @@ unsafe extern "sysv64" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> } #[allow(unsafe_op_in_unsafe_fn)] -unsafe extern "sysv64" fn child_hook( - cur_filetable_fd: usize, - new_proc_fd: usize, - new_thr_fd: usize, -) { - let _ = syscall::close(cur_filetable_fd); +unsafe extern "sysv64" fn child_hook(scratchpad: &ForkScratchpad) { + let _ = syscall::close(scratchpad.cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { - new_thr_fd: FdGuard::new(new_thr_fd), - new_proc_fd: if new_proc_fd == usize::MAX { + new_thr_fd: FdGuard::new(scratchpad.new_thr_fd), + new_proc_fd: if scratchpad.new_proc_fd == usize::MAX { None } else { - Some(FdGuard::new(new_proc_fd)) + Some(FdGuard::new(scratchpad.new_proc_fd)) }, }); } @@ -114,33 +112,34 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" push r14 push r15 - sub rsp, 48 + sub rsp, 16 - stmxcsr [rsp+32] - fnstcw [rsp+40] + stmxcsr [rsp+16] + fnstcw [rsp+8] // rdi: &ForkArgs + // rsi: initial_rsp mov rsi, rsp call {fork_impl} - add rsp, 96 + add rsp, 64 pop rbp ret "] <= [fork_impl = sym fork_impl]); asmfunction!(__relibc_internal_fork_ret: [" - mov rdi, [rsp] - mov rsi, [rsp + 8] - mov rdx, [rsp + 16] + # scratchpad is in rsi, move to rdi for child_hook + mov rdi, rsi + call {child_hook} - ldmxcsr [rsp + 32] - fldcw [rsp + 40] + ldmxcsr [rsp + 16] + mov rcx, [rsp + 8] xor rax, rax - add rsp, 48 + add rsp, 16 pop r15 pop r14 pop r13 diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 470609dc1f..1306d7efbc 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -803,6 +803,16 @@ pub fn create_set_addr_space_buf( buf } +pub fn create_set_addr_space_buf_for_fork( + space: usize, + ip: usize, + sp: usize, + arg1: usize, +) -> [u8; size_of::() * 4] { + let mut buf = [0u8; size_of::() * 4]; + buf.copy_from_slice([space, sp, ip, arg1].map(usize::to_ne_bytes).as_flattened()); + buf +} /// Spawns a new context which will not share the same address space as the current one. File /// descriptors from other schemes are reobtained with `dup`, and grants referencing such file @@ -848,16 +858,34 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { // 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")?; // 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()); + //let _ = syscall::write(1, alloc::format!("FDTBL{}PROC{}THR{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); + + ForkScratchpad { + cur_filetable_fd: cur_filetable_fd.as_raw_fd(), + new_proc_fd: proc_fd, + new_thr_fd: new_thr_fd.as_raw_fd(), + } + }; + + #[cfg(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "riscv64" + ))] + let arg1 = { + let scratchpad_ptr: *const ForkScratchpad = &scratchpad; + scratchpad_ptr as usize + }; + #[cfg(target_arch = "x86")] + { + let scratchpad_ptr = initial_rsp as *mut ForkScratchpad; unsafe { - let proc_fd = new_proc_fd.as_ref().map_or(usize::MAX, |p| p.as_raw_fd()); - //let _ = syscall::write(1, alloc::format!("FDTBL{}PROC{}THR{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); - initial_rsp.write(cur_filetable_fd.as_raw_fd()); - initial_rsp.add(1).write(proc_fd); - initial_rsp.add(2).write(new_thr_fd.as_raw_fd()); + scratchpad_ptr.write(scratchpad); } } @@ -927,7 +955,18 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { )?; } } - + #[cfg(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "riscv64" + ))] + let buf = create_set_addr_space_buf_for_fork( + new_addr_space_fd.as_raw_fd(), + __relibc_internal_fork_ret as usize, + initial_rsp as usize, + arg1, + ); + #[cfg(target_arch = "x86")] let buf = create_set_addr_space_buf( new_addr_space_fd.as_raw_fd(), __relibc_internal_fork_ret as usize, diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 065080e0c6..c96c72d9ab 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -39,7 +39,31 @@ fn wrapper(restart: bool, erestart: bool, mut f: impl FnMut() -> Result) - return res; } } - +pub fn unlink>(path: T, flags: usize) -> Result { + let redox_path = redox_path::RedoxPath::from_absolute(path.as_ref()) + .expect("path must be canonicalized beforehand"); + let (scheme, reference) = redox_path.as_parts().unwrap(); + let root_path = if scheme.as_ref().is_empty() { + alloc::string::String::from(":") + } else { + alloc::format!("/scheme/{}", scheme) + }; + // TODO: Temporary workaround to remove unlink and rmdir + let root_fd = crate::proc::FdGuard::open( + &root_path, + syscall::O_DIRECTORY | syscall::O_RDONLY | syscall::O_CLOEXEC, + )?; + let path = reference.as_ref(); + unsafe { + syscall::syscall4( + syscall::SYS_UNLINKAT, + root_fd.as_raw_fd(), + path.as_ptr() as usize, + path.len(), + flags, + ) + } +} // TODO: uninitialized memory? #[inline] pub fn posix_read(fd: usize, buf: &mut [u8]) -> Result { diff --git a/renamesyms.sh b/renamesyms.sh index f5a7e27970..4ab73f8d54 100755 --- a/renamesyms.sh +++ b/renamesyms.sh @@ -34,11 +34,6 @@ special_syms=( __rust_dealloc __rust_no_alloc_shim_is_unstable __rust_realloc - _RNvCsdRcTtHUCxqF_7___rustc12___rust_alloc - _RNvCsdRcTtHUCxqF_7___rustc19___rust_alloc_zeroed - _RNvCsdRcTtHUCxqF_7___rustc14___rust_dealloc - _RNvCsdRcTtHUCxqF_7___rustc14___rust_realloc - _RNvCsdRcTtHUCxqF_7___rustc8___rg_oom ) for dep in `find $deps_dir -type f -name "*.rlib"`; do @@ -49,6 +44,11 @@ for special_sym in "${special_syms[@]}"; do echo "$special_sym __relibc_$special_sym" >> $symbols_file done +mangled_alloc_syms=$("${NM}" --format=posix -g "$target" 2>/dev/null | awk '{print $1}' | grep "7___rustc" || true) +for sym in $mangled_alloc_syms; do + echo "$sym __relibc_$sym" >> $symbols_file +done + sorted_file=`mktemp` sort -u "$symbols_file" > "$sorted_file" rm -f "$symbols_file" diff --git a/src/header/fcntl/redox.rs b/src/header/fcntl/redox.rs index ee006a8850..8db73246d8 100644 --- a/src/header/fcntl/redox.rs +++ b/src/header/fcntl/redox.rs @@ -32,3 +32,4 @@ pub const O_NDELAY: c_int = O_NONBLOCK; pub const AT_FDCWD: c_int = -100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x0200; pub const AT_EMPTY_PATH: c_int = 0x4000; +pub const AT_REMOVEDIR: c_int = 0x200; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 1e3427756b..31e70cb821 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -1041,7 +1041,7 @@ impl Pal for Sys { fn rmdir(path: CStr) -> Result<()> { let path = path.to_str().map_err(|_| Errno(EINVAL))?; let canon = canonicalize(path)?; - syscall::rmdir(&canon)?; + redox_rt::sys::unlink(&canon, fcntl::AT_REMOVEDIR as usize)?; Ok(()) } @@ -1358,7 +1358,7 @@ impl Pal for Sys { fn unlink(path: CStr) -> Result<()> { let path = path.to_str().map_err(|_| Errno(EINVAL))?; let canon = canonicalize(path)?; - syscall::unlink(&canon)?; + redox_rt::sys::unlink(&canon, 0)?; Ok(()) }