Merge branch 'bind-connect-redoxfs' into 'master'

feat: Integrate UDS bind and connect operation with RedoxFS and switch get_proc_credentials to a capability-based approach.

See merge request redox-os/relibc!665
This commit is contained in:
Jeremy Soller
2025-07-18 08:57:49 -06:00
7 changed files with 124 additions and 14 deletions
Generated
+2 -2
View File
@@ -432,9 +432,9 @@ dependencies = [
[[package]]
name = "redox-path"
version = "0.2.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
[[package]]
name = "redox-rt"
+1 -1
View File
@@ -63,7 +63,7 @@ sc = "0.2.3"
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = "0.5.13"
redox-rt = { path = "redox-rt" }
redox-path = "0.2"
redox-path = "0.3"
redox_event = { git = "https://gitlab.redox-os.org/redox-os/event.git", default-features = false, features = [
"redox_syscall",
] }
+21
View File
@@ -52,6 +52,7 @@ pub enum ThreadCall {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
#[non_exhaustive]
pub enum SocketCall {
Bind = 0,
Connect = 1,
@@ -59,6 +60,15 @@ pub enum SocketCall {
GetSockOpt = 3,
SendMsg = 4,
RecvMsg = 5,
Unbind = 6,
GetToken = 7,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
#[non_exhaustive]
pub enum FsCall {
Connect = 0,
}
impl ProcCall {
@@ -103,6 +113,17 @@ impl SocketCall {
3 => Self::GetSockOpt,
4 => Self::SendMsg,
5 => Self::RecvMsg,
6 => Self::Unbind,
7 => Self::GetToken,
_ => return None,
})
}
}
impl FsCall {
pub fn try_from_raw(raw: usize) -> Option<Self> {
Some(match raw {
0 => Self::Connect,
_ => return None,
})
}
+3 -2
View File
@@ -296,11 +296,12 @@ pub fn posix_getresugid() -> Resugid<u32> {
sgid,
}
}
pub fn get_proc_credentials(target_pid: usize, buf: &mut [u8]) -> Result<usize> {
pub fn get_proc_credentials(cap_fd: usize, target_pid: usize, buf: &mut [u8]) -> Result<usize> {
if buf.len() < size_of::<crate::protocol::ProcMeta>() {
return Err(Error::new(EINVAL));
}
this_proc_call(
proc_call(
cap_fd,
buf,
CallFlags::empty(),
&[ProcCall::GetProcCredentials as u64, target_pid as u64],
+3 -2
View File
@@ -242,11 +242,12 @@ pub unsafe extern "C" fn redox_get_rgid_v1() -> RawResult {
redox_rt::sys::posix_getresugid().rgid as _
}
#[no_mangle]
pub unsafe extern "C" fn redox_get_proc_credentials_v0(
pub unsafe extern "C" fn redox_get_proc_credentials_v1(
cap_fd: usize,
target_pid: usize,
buf: &mut [u8],
) -> RawResult {
Error::mux(redox_rt::sys::get_proc_credentials(target_pid, buf))
Error::mux(redox_rt::sys::get_proc_credentials(cap_fd, target_pid, buf))
}
#[no_mangle]
+44 -2
View File
@@ -1,11 +1,16 @@
use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
use alloc::{
borrow::ToOwned,
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use redox_rt::signal::tmp_disable_signals;
use syscall::{data::Stat, error::*, flag::*};
use super::{libcscheme, FdGuard};
use crate::sync::Mutex;
pub use redox_path::canonicalize_using_cwd;
pub use redox_path::{canonicalize_using_cwd, RedoxPath};
// TODO: Define in syscall
const PATH_MAX: usize = 4096;
@@ -169,3 +174,40 @@ pub fn open(path: &str, flags: usize) -> Result<usize> {
}
Err(Error::new(ELOOP))
}
pub fn dir_path_and_fd_path(socket_path: &str) -> Result<(String, String)> {
let _siglock = tmp_disable_signals();
let cwd_guard = CWD.lock();
let full_path = canonicalize_with_cwd_internal(cwd_guard.as_deref(), socket_path)?;
let redox_path = RedoxPath::from_absolute(&full_path).ok_or(Error::new(EINVAL))?;
let (_, mut ref_path) = redox_path.as_parts().ok_or(Error::new(EINVAL))?;
if ref_path.as_ref().is_empty() {
return Err(Error::new(EINVAL));
}
if redox_path.is_default_scheme() {
let dir_to_open = String::from(get_parent_path(&full_path).ok_or(Error::new(EINVAL))?);
Ok((dir_to_open, ref_path.as_ref().to_string()))
} else {
let full_path = canonicalize_with_cwd_internal(cwd_guard.as_deref(), ref_path.as_ref())?;
let redox_path = RedoxPath::from_absolute(&full_path).ok_or(Error::new(EINVAL))?;
let (_, path) = redox_path.as_parts().ok_or(Error::new(EINVAL))?;
let dir_to_open = String::from(get_parent_path(&full_path).ok_or(Error::new(EINVAL))?);
Ok((dir_to_open, path.as_ref().to_string()))
}
}
fn get_parent_path(path: &str) -> Option<&str> {
path.rfind('/').and_then(|index| {
if index == 0 {
// Path is something like "/file.txt" or the root "/".
// The parent is the root directory "/".
Some("/")
} else {
// Path is something like "/a/b/c.txt".
// Take the slice from the beginning up to the last '/'.
Some(&path[..index])
}
})
}
+50 -5
View File
@@ -1,10 +1,14 @@
use alloc::vec::Vec;
use alloc::{string::String, vec::Vec};
use core::{cmp, mem, ptr, slice, str};
use redox_rt::{proc::FdGuard, protocol::SocketCall};
use redox_rt::{
proc::FdGuard,
protocol::{FsCall, SocketCall},
};
use syscall::{self, flag::*};
use super::{
super::{types::*, Pal, PalSocket, ERRNO},
path::dir_path_and_fd_path,
Sys,
};
use crate::{
@@ -522,15 +526,40 @@ impl PalSocket for Sys {
);
let addr = slice::from_raw_parts(&data.sun_path as *const _ as *const u8, len);
let mut path = format!("{}", str::from_utf8(addr).unwrap());
let path = format!("{}", str::from_utf8(addr).unwrap());
trace!("path: {:?}", path);
let (dir_path, mut fd_path) = dir_path_and_fd_path(&path)?;
redox_rt::sys::sys_call(
socket as usize,
path.as_bytes_mut(),
fd_path.as_bytes_mut(),
CallFlags::empty(),
&[SocketCall::Bind as u64],
)?;
let fs_bind_result = (|| -> Result<()> {
let dirfd = FdGuard::new(syscall::open(
&dir_path,
syscall::O_RDONLY | syscall::O_DIRECTORY | syscall::O_CLOEXEC,
)?);
let fd_to_send = FdGuard::new(syscall::dup(socket as usize, &[])?);
let _ = syscall::sendfd(*dirfd, *fd_to_send, 0, 0)?;
Ok(())
})();
if let Err(original_error) = fs_bind_result {
if let Err(unbind_error) = redox_rt::sys::sys_call(
socket as usize,
&mut [],
CallFlags::empty(),
&[SocketCall::Unbind as u64],
) {
eprintln!("bind: CRITICAL: failed to unbind socket after a failed transaction: {:?}", unbind_error);
}
return Err(original_error);
}
}
_ => {
return Err(Errno(EAFNOSUPPORT));
@@ -570,9 +599,25 @@ impl PalSocket for Sys {
let mut path = format!("{}", str::from_utf8(addr).unwrap());
trace!("path: {:?}", path);
let (_, fd_path) = dir_path_and_fd_path(&path)?;
let target_path = format!("/{fd_path}");
let socket_file_fd = FdGuard::new(syscall::open(&target_path, syscall::O_RDWR)?);
const TOKEN_BUF_SIZE: usize = 16;
let mut token_buf = [0u8; TOKEN_BUF_SIZE];
redox_rt::sys::sys_call(
*socket_file_fd,
&mut token_buf,
CallFlags::empty(),
&[FsCall::Connect as u64],
)?;
redox_rt::sys::sys_call(
socket as usize,
path.as_bytes_mut(),
&mut token_buf,
CallFlags::empty(),
&[SocketCall::Connect as u64],
)?;