From 94b0cfc682abdbe0796e5b4d6159336d2912ee45 Mon Sep 17 00:00:00 2001 From: Ibuki Omatsu Date: Sun, 8 Feb 2026 02:48:59 +0000 Subject: [PATCH] refactor: Reimplement recvmsg and sendmsg using bulk fd passing. --- redox-rt/src/sys.rs | 28 +++++++++++++++ src/header/sys_ioctl/redox/drm.rs | 10 +++--- src/platform/redox/libredox.rs | 4 +-- src/platform/redox/socket.rs | 58 +++++++++++++++++++------------ 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index da8139754d..f5f1f005b7 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -1,6 +1,7 @@ use core::{ mem::{replace, size_of}, ptr::addr_of, + slice, sync::atomic::{AtomicU32, Ordering}, }; @@ -137,6 +138,33 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { } .map(|awoken| awoken as u32) } +pub fn sys_call_ro( + fd: usize, + payload: &mut [u8], + flags: CallFlags, + metadata: &[u64], +) -> Result { + sys_call(fd, payload, flags | CallFlags::READ, metadata) +} +pub fn sys_call_wo(fd: usize, payload: &[u8], flags: CallFlags, metadata: &[u64]) -> Result { + let payload_mut = + unsafe { slice::from_raw_parts_mut(payload.as_ptr() as *mut u8, payload.len()) }; + + sys_call(fd, payload_mut, flags | CallFlags::WRITE, metadata) +} +pub fn sys_call_rw( + fd: usize, + payload: &mut [u8], + flags: CallFlags, + metadata: &[u64], +) -> Result { + sys_call( + fd, + payload, + flags | CallFlags::READ | CallFlags::WRITE, + metadata, + ) +} pub fn sys_call( fd: usize, payload: &mut [u8], diff --git a/src/header/sys_ioctl/redox/drm.rs b/src/header/sys_ioctl/redox/drm.rs index ff47ccb814..3d460bf48a 100644 --- a/src/header/sys_ioctl/redox/drm.rs +++ b/src/header/sys_ioctl/redox/drm.rs @@ -63,7 +63,7 @@ impl Dev { ) -> Result { let mut data = unsafe { buf.read::() }?; let mut wire = unsafe { data.write() }; - let res = redox_rt::sys::sys_call( + let res = redox_rt::sys::sys_call_rw( self.fd as usize, &mut wire, syscall::CallFlags::empty(), @@ -75,11 +75,11 @@ impl Dev { } unsafe fn write_ioctl(&self, mut buf: IoctlBuffer, func: u64) -> Result { - let mut data = unsafe { buf.read::() }?; - let mut wire = unsafe { data.write() }; - let res = redox_rt::sys::sys_call( + let data = unsafe { buf.read::() }?; + let wire = unsafe { data.write() }; + let res = redox_rt::sys::sys_call_wo( self.fd as usize, - &mut wire, + &wire, syscall::CallFlags::empty(), &[func], )?; diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 3aa3b8e219..d64cf7b7c0 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -10,7 +10,7 @@ use redox_rt::{ protocol::{ProcKillTarget, SocketCall, WaitFlags}, sys::{WaitpidTarget, posix_read, posix_write}, }; -use syscall::{EMFILE, ENOSYS, Error, Result}; +use syscall::{CallFlags, EMFILE, ENOSYS, Error, Result}; use crate::{ header::{ @@ -455,7 +455,7 @@ pub unsafe extern "C" fn redox_get_socket_token_v0( payload_len: usize, ) -> RawResult { let metadata = [SocketCall::GetToken as u64]; - Error::mux(redox_rt::sys::sys_call( + Error::mux(redox_rt::sys::sys_call_ro( fd, unsafe { slice::from_raw_parts_mut(payload, payload_len) }, syscall::CallFlags::empty(), diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index 64146a5ff2..26cd6930d3 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -266,14 +266,17 @@ unsafe fn serialize_ancillary_data_to_stream( } let fd_count = data_len / mem::size_of::(); - // Call syscall::sendfd for each fd. if fd_count > 0 { let fds_ptr = unsafe { CMSG_DATA(cmsg) } as *const c_int; - let fds_slice = unsafe { 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_raw_fd(), 0, 0)?; - } + let c_fds = unsafe { slice::from_raw_parts(fds_ptr, fd_count) }; + let fds_usize: Vec = c_fds.iter().map(|&fd| fd as usize).collect(); + let fds_slice = unsafe { + slice::from_raw_parts( + fds_usize.as_ptr() as *const u8, + fds_usize.len() * mem::size_of::(), + ) + }; + redox_rt::sys::sys_call_wo(socket as usize, &fds_slice, CallFlags::FD, &[])?; } // Serialize to ancillary_data_stream. @@ -437,10 +440,19 @@ unsafe fn deserialize_ancillary_data_from_stream( } let fd_count = read_num::(&cmsg_data_from_stream)?; - for _ in 0..fd_count { - // Call syscall::dup to duplicate the fd - let new_fd = syscall::dup(socket as usize, b"recvfd")?; - temp_posix_cmsg_data_buf.extend_from_slice(&(new_fd as c_int).to_le_bytes()); + let mut fds_usize = vec![0usize; fd_count]; + + let fds_bytes = unsafe { + slice::from_raw_parts_mut( + fds_usize.as_mut_ptr() as *mut u8, + fds_usize.len() * mem::size_of::(), + ) + }; + + redox_rt::sys::sys_call_ro(socket as usize, fds_bytes, CallFlags::FD, &[])?; + + for fd in fds_usize { + temp_posix_cmsg_data_buf.extend_from_slice(&(fd as c_int).to_le_bytes()); } actual_posix_cmsg_data_len = temp_posix_cmsg_data_buf.len(); } @@ -552,9 +564,9 @@ impl PalSocket for Sys { let (dir_path, mut fd_path) = dir_path_and_fd_path(&path)?; - redox_rt::sys::sys_call( + redox_rt::sys::sys_call_wo( socket as usize, - unsafe { fd_path.as_bytes_mut() }, + fd_path.as_bytes(), CallFlags::empty(), &[SocketCall::Bind as u64], )?; @@ -570,9 +582,9 @@ impl PalSocket for Sys { })(); if let Err(original_error) = fs_bind_result { - if let Err(unbind_error) = redox_rt::sys::sys_call( + if let Err(unbind_error) = redox_rt::sys::sys_call_wo( socket as usize, - &mut [], + &[], CallFlags::empty(), &[SocketCall::Unbind as u64], ) { @@ -636,16 +648,16 @@ impl PalSocket for Sys { let mut token_buf = [0u8; TOKEN_BUF_SIZE]; - redox_rt::sys::sys_call( + redox_rt::sys::sys_call_ro( socket_file_fd.as_raw_fd(), &mut token_buf, CallFlags::empty(), &[FsCall::Connect as u64], )?; - redox_rt::sys::sys_call( + redox_rt::sys::sys_call_wo( socket as usize, - &mut token_buf, + &token_buf, CallFlags::empty(), &[SocketCall::Connect as u64], )?; @@ -661,7 +673,7 @@ impl PalSocket for Sys { address_len: *mut socklen_t, ) -> Result<()> { let mut buf = [0; 256]; - let len = redox_rt::sys::sys_call( + let len = redox_rt::sys::sys_call_ro( socket as usize, &mut buf, CallFlags::empty(), @@ -733,7 +745,7 @@ impl PalSocket for Sys { unsafe { slice::from_raw_parts_mut(option_value as *mut u8, option_len) }; let call_flags = CallFlags::empty(); unsafe { - *option_len_ptr = redox_rt::sys::sys_call( + *option_len_ptr = redox_rt::sys::sys_call_ro( socket as usize, payload, CallFlags::empty(), @@ -863,7 +875,7 @@ impl PalSocket for Sys { let metadata = [SocketCall::RecvMsg as u64, flags as u64]; let call_flags = CallFlags::empty(); let actual_read_len = - redox_rt::sys::sys_call(socket as usize, &mut msg_stream, call_flags, &metadata)?; + redox_rt::sys::sys_call_rw(socket as usize, &mut msg_stream, call_flags, &metadata)?; msg_stream.truncate(actual_read_len); cursor = 0; @@ -944,7 +956,7 @@ impl PalSocket for Sys { // Send the message stream. let metadata = [SocketCall::SendMsg as u64, flags as u64]; let call_flags = CallFlags::empty(); - let written = redox_rt::sys::sys_call( + let written = redox_rt::sys::sys_call_rw( socket as usize, msg_stream.as_mut_slice(), call_flags, @@ -1036,7 +1048,7 @@ impl PalSocket for Sys { slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize) }; let call_flags = CallFlags::empty(); - redox_rt::sys::sys_call( + redox_rt::sys::sys_call_rw( socket as usize, payload, CallFlags::empty(), @@ -1062,7 +1074,7 @@ impl PalSocket for Sys { fn shutdown(socket: c_int, how: c_int) -> Result<()> { let metadata = [SocketCall::Shutdown as u64, how as u64]; - redox_rt::sys::sys_call(socket as usize, &mut [], CallFlags::empty(), &metadata)?; + redox_rt::sys::sys_call_wo(socket as usize, &[], CallFlags::empty(), &metadata)?; Ok(()) }