From 381dd8ef20218796b2f93b99aaa7032c56f9e4d5 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Mon, 13 Jul 2026 22:57:31 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20open()=20uses=20single=20SYS=5FOPENAT=20?= =?UTF-8?q?call=20=E2=80=94=20eliminates=20OtherScheme=20EOPNOTSUPP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two-step pattern (open full path as scheme root, then open reference relative to root_fd) failed for namespace-internal paths like /scheme/namespace/scheme-creation-cap. The namespace scheme resolves the full path and returns OtherScheme pointing to SchemeList (a kernel scheme that does not implement kopenat). The second call then hits SchemeList.kopenat() → EOPNOTSUPP. The namespace scheme already handles reference resolution internally via open_scheme_resource(), so a single SYS_OPENAT call with the full path resolves everything. This also bypasses FILETABLE.insert_upper (which previously collided with the untracked ns_fd at UPPER index 0). --- redox-rt/src/sys.rs | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index f54fba8f86..249f45bcf5 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -589,32 +589,20 @@ pub fn getns() -> Result { pub fn open>(path: T, flags: usize) -> Result { let _siglock = tmp_disable_signals(); - let fcntl_flags = flags & syscall::O_FCNTL_MASK; - let redox_path = RedoxPath::from_absolute(path.as_ref()).ok_or(Error::new(EINVAL))?; - let (_, reference) = redox_path.as_parts().ok_or(Error::new(EINVAL))?; let ns_fd = crate::current_namespace_fd()?; - // Open the scheme root using raw SYS_OPENAT (auto-assigned POSIX fd). - // This bypasses FILETABLE.insert_upper, which could collide with the - // namespace fd (ns_fd) that is not always tracked in the UPPER table. - let root_fd = syscall::openat( + // Single SYS_OPENAT call: the kernel resolves the full path through the + // namespace scheme, which handles OtherScheme redirection internally. + // The previous two-step approach (open scheme root, then open reference) + // failed when the namespace returned OtherScheme, because the target + // scheme did not implement kopenat for the reference path. + let posix_fd = syscall::openat( ns_fd, path.as_ref(), - syscall::O_DIRECTORY | O_CLOEXEC, + flags, 0, )?; - register_external_fd(root_fd)?; - - let posix_fd = syscall::openat( - root_fd, - reference.as_ref(), - flags, - fcntl_flags, - )?; - - // Close root_fd and remove from FILETABLE, then register posix_fd. - close(root_fd)?; register_external_fd(posix_fd)?; Ok(posix_fd)