From 1cf631ce3f36838ababdbd2b0190d93a6b64a31b Mon Sep 17 00:00:00 2001 From: Ibuki Omatsu Date: Tue, 16 Dec 2025 14:07:01 +0000 Subject: [PATCH] Introduce syscall6. Add unlinkat and remove unlink and rmdir. --- Cargo.toml | 2 +- src/arch/aarch64.rs | 8 ++++-- src/arch/riscv64.rs | 8 ++++-- src/arch/x86.rs | 43 +++++++++++++++++++++++++++++ src/arch/x86_64.rs | 8 ++++-- src/call.rs | 67 +++++++++++++++++++++++++++++++++++++-------- src/flag.rs | 4 +++ src/number.rs | 5 ++-- src/schemev2.rs | 6 ++-- 9 files changed, 128 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1090e6db43..f0981fb304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "redox_syscall" -version = "0.5.18" +version = "0.6.0" description = "A Rust library to access raw Redox system calls" license = "MIT" authors = ["Jeremy Soller "] diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs index a63ab385dd..7ba23e5c6f 100644 --- a/src/arch/aarch64.rs +++ b/src/arch/aarch64.rs @@ -12,9 +12,9 @@ pub const KERNEL_METADATA_SIZE: usize = 4 * PAGE_SIZE; #[cfg(feature = "userspace")] macro_rules! syscall { - ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { + ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, $($g:ident, )?)?)?)?)?)?);)+) => { $( - pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result { + pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize, $($g: usize)?)?)?)?)?)?) -> Result { let ret: usize; core::arch::asm!( @@ -30,6 +30,9 @@ macro_rules! syscall { in("x3") $e, $( in("x4") $f, + $( + in("x5") $g, + )? )? )? )? @@ -53,6 +56,7 @@ syscall! { syscall3(a, b, c, d,); syscall4(a, b, c, d, e,); syscall5(a, b, c, d, e, f,); + syscall6(a, b, c, d, e, f, g,); } #[derive(Copy, Clone, Debug, Default)] diff --git a/src/arch/riscv64.rs b/src/arch/riscv64.rs index 3341bb36a9..ea4ae694a7 100644 --- a/src/arch/riscv64.rs +++ b/src/arch/riscv64.rs @@ -12,9 +12,9 @@ pub const KERNEL_METADATA_SIZE: usize = 4 * PAGE_SIZE; #[cfg(feature = "userspace")] macro_rules! syscall { - ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { + ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, $($g:ident, )?)?)?)?)?)?);)+) => { $( - pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result { + pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize, $($g: usize)?)?)?)?)?)?) -> Result { let ret: usize; asm!( @@ -30,6 +30,9 @@ macro_rules! syscall { in("a3") $e, $( in("a4") $f, + $( + in("a5") $g, + )? )? )? )? @@ -53,6 +56,7 @@ syscall! { syscall3(a, b, c, d,); syscall4(a, b, c, d, e,); syscall5(a, b, c, d, e, f,); + syscall6(a, b, c, d, e, f, g,); } #[derive(Copy, Clone, Debug, Default)] diff --git a/src/arch/x86.rs b/src/arch/x86.rs index d9dba855d4..7c4c01d9ac 100644 --- a/src/arch/x86.rs +++ b/src/arch/x86.rs @@ -52,6 +52,7 @@ syscall! { // Must be done custom because LLVM reserves ESI //syscall4(a, b, c, d, e,); //syscall5(a, b, c, d, e, f,); + //syscall6(a, b, c, d, e, f, g,); } #[cfg(feature = "userspace")] @@ -96,6 +97,48 @@ pub unsafe fn syscall5( Error::demux(a) } +#[cfg(feature = "userspace")] +pub unsafe fn syscall6( + mut a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, +) -> Result { + #[repr(C)] + struct PackedArgs { + arg4: usize, + arg6: usize, + nr: usize, + } + let args = PackedArgs { + arg4: e, + arg6: g, + nr: a, + }; + let args_ptr = &args as *const PackedArgs; + asm!( + "push ebp", + "push esi", + "mov esi, [eax + 0]", // arg4 -> esi + "mov ebp, [eax + 4]", // arg6 -> ebp + "mov eax, [eax + 8]", // nr -> eax + "int 0x80", + "pop esi", + "pop ebp", + inout("eax") args_ptr => a, + in("ebx") b, + in("ecx") c, + in("edx") d, + in("edi") f, + options(nostack), + ); + + Error::demux(a) +} + #[derive(Copy, Clone, Debug, Default)] #[repr(C)] pub struct IntRegisters { diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index 9872dff61a..93277e59c7 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -10,9 +10,9 @@ pub const KERNEL_METADATA_SIZE: usize = 4 * PAGE_SIZE; #[cfg(feature = "userspace")] macro_rules! syscall { - ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { + ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, $($g:ident, )?)?)?)?)?)?);)+) => { $( - pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> crate::error::Result { + pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize, $($g: usize)?)?)?)?)?)?) -> crate::error::Result { core::arch::asm!( "syscall", inout("rax") $a, @@ -26,6 +26,9 @@ macro_rules! syscall { in("r10") $e, $( in("r8") $f, + $( + in("r9") $g, + )? )? )? )? @@ -50,6 +53,7 @@ syscall! { syscall3(a, b, c, d,); syscall4(a, b, c, d, e,); syscall5(a, b, c, d, e, f,); + syscall6(a, b, c, d, e, f, g,); } #[derive(Copy, Clone, Debug, Default)] diff --git a/src/call.rs b/src/call.rs index 03e3425a10..27b0bd87b4 100644 --- a/src/call.rs +++ b/src/call.rs @@ -199,24 +199,67 @@ pub fn openat>( ) } } +/// Open a file at a specific path with filter +pub fn openat_with_filter>( + fd: usize, + path: T, + flags: usize, + fcntl_flags: usize, + euid: u32, + egid: u32, +) -> Result { + let path = path.as_ref(); + unsafe { + syscall6( + SYS_OPENAT_WITH_FILTER, + fd, + path.as_ptr() as usize, + path.len(), + flags | fcntl_flags, + // NOTE: Short-term solution to allow namespace management. + // In the long term, we need to figure out how we should best handle + // Unix permissions using capabilities. + euid as usize, + egid as usize, + ) + } +} + +/// Remove a file at at specific path +pub fn unlinkat>(fd: usize, path: T, flags: usize) -> Result { + let path = path.as_ref(); + unsafe { syscall4(SYS_UNLINKAT, fd, path.as_ptr() as usize, path.len(), flags) } +} +/// Remove a file at at specific path with filter +pub fn unlinkat_with_filter>( + fd: usize, + path: T, + flags: usize, + euid: u32, + egid: u32, +) -> Result { + let path = path.as_ref(); + unsafe { + syscall6( + SYS_UNLINKAT_WITH_FILTER, + fd, + path.as_ptr() as usize, + path.len(), + flags, + // NOTE: Short-term solution to allow namespace management. + // In the long term, we need to figure out how we should best handle + // Unix permissions using capabilities. + euid as usize, + egid as usize, + ) + } +} /// Read from a file descriptor into a buffer pub fn read(fd: usize, buf: &mut [u8]) -> Result { unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } } -/// Remove a directory -pub fn rmdir>(path: T) -> Result { - let path = path.as_ref(); - unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } -} - -/// Remove a file -pub fn unlink>(path: T) -> Result { - let path = path.as_ref(); - unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } -} - /// Write a buffer to a file descriptor /// /// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning diff --git a/src/flag.rs b/src/flag.rs index 263edde005..404e0bef78 100644 --- a/src/flag.rs +++ b/src/flag.rs @@ -204,6 +204,10 @@ pub const O_STAT: usize = 0x2000_0000; pub const O_SYMLINK: usize = 0x4000_0000; pub const O_NOFOLLOW: usize = 0x8000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; +pub const O_FCNTL_MASK: usize = O_NONBLOCK | O_APPEND | O_ASYNC | O_FSYNC; + +/// Remove directory instead of unlinking file. +pub const AT_REMOVEDIR: usize = 0x200; // The top 48 bits of PTRACE_* are reserved, for now diff --git a/src/number.rs b/src/number.rs index b3af71d7d3..e7400cb3a5 100644 --- a/src/number.rs +++ b/src/number.rs @@ -12,8 +12,9 @@ pub const SYS_RET_FILE: usize = 0x0010_0000; pub const SYS_OPEN: usize = SYS_CLASS_PATH | SYS_RET_FILE | 5; pub const SYS_OPENAT: usize = SYS_CLASS_PATH | SYS_RET_FILE | 7; -pub const SYS_RMDIR: usize = SYS_CLASS_PATH | 84; -pub const SYS_UNLINK: usize = SYS_CLASS_PATH | 10; +pub const SYS_OPENAT_WITH_FILTER: usize = SYS_CLASS_PATH | SYS_RET_FILE | 985; +pub const SYS_UNLINKAT: usize = SYS_CLASS_PATH | 263; +pub const SYS_UNLINKAT_WITH_FILTER: usize = SYS_CLASS_PATH | 986; pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6; pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41; diff --git a/src/schemev2.rs b/src/schemev2.rs index 1849fa88e1..ce86653b4a 100644 --- a/src/schemev2.rs +++ b/src/schemev2.rs @@ -134,8 +134,9 @@ pub enum Opcode { OpenAt = 29, // fd, buf_ptr, buf_len, flags Flink = 30, - Recvfd = 31, + + UnlinkAt = 32, // fd, path_ptr, path_len (utf8), flags } impl Opcode { @@ -178,9 +179,10 @@ impl Opcode { 29 => OpenAt, 30 => Flink, - 31 => Recvfd, + 32 => UnlinkAt, + _ => return None, }) }