init: fix FILETABLE desync causing EEXIST on all daemon spawns
create_pipe() used raw syscall::openat() (SYS_OPENAT) and syscall::dup() which bypass relibc's FILETABLE-managed fd allocation (SYS_OPENAT_INTO). This created phantom fds known to the kernel but not to relibc's userspace FILETABLE. When Command::spawn() later called relibc's pipe2() for fork+exec error reporting, the FILETABLE allocated a position it thought was free, but the kernel rejected it with EEXIST (errno 17). This killed EVERY daemon spawn during boot: logd, randd, zerod, rtcd, nulld, acpid, pcid, inputd, lived, redoxfs, pcid-spawner, fbcond, vesad, fbbootlogd, hwd, ps2d — all failed with 'File exists (os error 17)'. Fix: use libc::pipe2() which goes through relibc's FILETABLE-managed path (FdGuard::open → SYS_OPENAT_INTO), keeping tables in sync.
This commit is contained in:
+14
-19
@@ -37,25 +37,20 @@ pub enum ServiceType {
|
||||
}
|
||||
|
||||
fn create_pipe() -> io::Result<(File, OwnedFd)> {
|
||||
let ns_fd = libredox::call::getns()
|
||||
.map_err(|e| io::Error::from_raw_os_error(e.errno()))?;
|
||||
|
||||
let rd_fd = syscall::openat(
|
||||
ns_fd,
|
||||
"/scheme/pipe",
|
||||
syscall::flag::O_RDONLY | syscall::flag::O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
.map_err(|e| io::Error::from_raw_os_error(e.errno))?;
|
||||
|
||||
let wr_raw = syscall::dup(rd_fd, b"write")
|
||||
.map_err(|e| {
|
||||
let _ = syscall::close(rd_fd);
|
||||
io::Error::from_raw_os_error(e.errno)
|
||||
})?;
|
||||
|
||||
let wr = unsafe { OwnedFd::from_raw_fd(wr_raw as i32) };
|
||||
let rd = unsafe { File::from_raw_fd(rd_fd as i32) };
|
||||
let mut fds = [0; 2];
|
||||
// Use libc::pipe2() which goes through relibc's FILETABLE-managed path
|
||||
// (FdGuard::open → SYS_OPENAT_INTO), keeping the userspace file table in
|
||||
// sync with the kernel's file table. Using raw syscall::openat()
|
||||
// (SYS_OPENAT) here would bypass the FILETABLE and create phantom fds
|
||||
// that later cause EEXIST collisions when relibc's own pipe2() (called
|
||||
// during Command::spawn fork+exec) tries to insert at a position the
|
||||
// FILETABLE incorrectly thinks is free.
|
||||
let ret = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) };
|
||||
if ret != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
let rd = unsafe { File::from_raw_fd(fds[0]) };
|
||||
let wr = unsafe { OwnedFd::from_raw_fd(fds[1]) };
|
||||
Ok((rd, wr))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user