refactor: Replace unlink and rmdir with unlinkat. Improve fork using ForkScratchPad.

This commit is contained in:
Ibuki Omatsu
2025-12-18 01:32:07 +00:00
committed by Jeremy Soller
parent 2162d50358
commit efa5b73015
14 changed files with 148 additions and 77 deletions
Generated
+8 -6
View File
@@ -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",
]
+2 -2
View File
@@ -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" }
+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.5.8"
redox_syscall = "0.6.0"
[features]
+2 -1
View File
@@ -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" }
+10 -10
View File
@@ -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
+8 -9
View File
@@ -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: ["
+8
View File
@@ -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,
}
+12 -14
View File
@@ -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)
+18 -19
View File
@@ -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
+46 -7
View File
@@ -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::<usize>() * 4] {
let mut buf = [0u8; size_of::<usize>() * 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<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")?;
// 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<usize> {
)?;
}
}
#[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,
+25 -1
View File
@@ -39,7 +39,31 @@ fn wrapper<T>(restart: bool, erestart: bool, mut f: impl FnMut() -> Result<T>) -
return res;
}
}
pub fn unlink<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
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<usize> {
+5 -5
View File
@@ -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"
+1
View File
@@ -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;
+2 -2
View File
@@ -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(())
}