refactor: Reimplement recvmsg and sendmsg using bulk fd passing.

This commit is contained in:
Ibuki Omatsu
2026-02-08 02:48:59 +00:00
committed by Jeremy Soller
parent 3724e7892d
commit 94b0cfc682
4 changed files with 70 additions and 30 deletions
+28
View File
@@ -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<u32> {
}
.map(|awoken| awoken as u32)
}
pub fn sys_call_ro(
fd: usize,
payload: &mut [u8],
flags: CallFlags,
metadata: &[u64],
) -> Result<usize> {
sys_call(fd, payload, flags | CallFlags::READ, metadata)
}
pub fn sys_call_wo(fd: usize, payload: &[u8], flags: CallFlags, metadata: &[u64]) -> Result<usize> {
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<usize> {
sys_call(
fd,
payload,
flags | CallFlags::READ | CallFlags::WRITE,
metadata,
)
}
pub fn sys_call(
fd: usize,
payload: &mut [u8],
+5 -5
View File
@@ -63,7 +63,7 @@ impl Dev {
) -> Result<c_int> {
let mut data = unsafe { buf.read::<T>() }?;
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<T: IoctlData>(&self, mut buf: IoctlBuffer, func: u64) -> Result<c_int> {
let mut data = unsafe { buf.read::<T>() }?;
let mut wire = unsafe { data.write() };
let res = redox_rt::sys::sys_call(
let data = unsafe { buf.read::<T>() }?;
let wire = unsafe { data.write() };
let res = redox_rt::sys::sys_call_wo(
self.fd as usize,
&mut wire,
&wire,
syscall::CallFlags::empty(),
&[func],
)?;
+2 -2
View File
@@ -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(),
+35 -23
View File
@@ -266,14 +266,17 @@ unsafe fn serialize_ancillary_data_to_stream(
}
let fd_count = data_len / mem::size_of::<c_int>();
// 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<usize> = 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::<usize>(),
)
};
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::<usize>(&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::<usize>(),
)
};
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(())
}