redox-rt: refresh inherited filetable before rebuilding fd table
Backport of upstream relibc 580eab8b ('Refresh filetable data before
filetable creation'). FdTbl::from_binary_fd reconstructs an exec'd
process's fd table from the inherited filetable fd. A plain lseek(0) did
not force the backing scheme to re-materialize the current descriptor
set, so an exec'd child (e.g. a login shell) could read a STALE snapshot
and end up with a desynchronized fd -- observed as an interactive shell
whose pty-slave stdin (fd 0) returns nothing while writes to fd 1/2 work.
Issue a SYS_DUP2 'refresh' on the filetable fd before reading it.
This commit is contained in:
+19
-1
@@ -965,7 +965,25 @@ impl FdTbl {
|
||||
pub fn from_binary_fd(filetable_fd: FdGuardUpper) -> Result<Self> {
|
||||
let mut fdtbl = Self::new();
|
||||
let files_reader_fd = filetable_fd.as_raw_fd();
|
||||
let _ = filetable_fd.lseek(0, syscall::flag::SEEK_SET);
|
||||
// Refresh the inherited filetable's data before reading it, so an
|
||||
// exec'd process reconstructs its fd table from the LATEST parent state
|
||||
// rather than a stale snapshot. Without this, some inherited fds (e.g.
|
||||
// an interactive shell's pty-slave stdin) are left desynchronized and
|
||||
// reads return nothing even though writes to sibling fds work.
|
||||
// Upstream relibc 580eab8b ("Refresh filetable data before filetable
|
||||
// creation"). A plain lseek did not force the underlying scheme to
|
||||
// re-materialize the current descriptor set.
|
||||
let buf = b"refresh";
|
||||
unsafe {
|
||||
syscall::syscall4(
|
||||
syscall::SYS_DUP2,
|
||||
files_reader_fd,
|
||||
files_reader_fd,
|
||||
buf.as_ptr() as usize,
|
||||
buf.len(),
|
||||
)
|
||||
}?;
|
||||
|
||||
fdtbl.resize(Self::DEFAULT_CAPACITY);
|
||||
|
||||
let mut reader = crate::proc::FileBufReader::from_fd(files_reader_fd);
|
||||
|
||||
Reference in New Issue
Block a user