relibc: fix open() to bypass FILETABLE.insert_upper collision

The open() function used openat_into_upper which calls
FILETABLE.insert_upper() to allocate UPPER fd slots. This can collide
with the namespace fd (ns_fd) that is stored in DYNAMIC_PROC_INFO,
causing the kernel to overwrite the namespace fd entry. All subsequent
open() calls then resolve to the wrong scheme.

Fix: use raw SYS_OPENAT syscalls (which auto-assign POSIX fds) and
register them with register_external_fd, bypassing insert_upper entirely.
This commit is contained in:
Red Bear OS
2026-07-13 22:42:31 +03:00
parent eac112e919
commit a540890851
+23 -4
View File
@@ -592,13 +592,32 @@ pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
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 root_fd = FdGuard::new(openat_into_upper(
crate::current_namespace_fd()?,
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(
ns_fd,
path.as_ref(),
syscall::O_DIRECTORY | O_CLOEXEC,
0,
)?);
openat_into_posix(root_fd.as_raw_fd(), reference.as_ref(), flags, fcntl_flags)
)?;
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)
}
pub fn openat<T: AsRef<str>>(
fd: usize,