From 6602b604c5779c94f51adb962df8d3c97bceb9fc Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Mon, 15 Dec 2025 06:44:44 -0500 Subject: [PATCH] Fix race condition in dup2 when duplicating to same fd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per POSIX, dup2(fd, fd) should return fd immediately without modifying anything. The previous implementation would close_read()/close_write() and then add_reader()/add_writer() in separate operations, temporarily setting the pipe reference count to zero. A concurrent write during this window would see readers == 0 and incorrectly return EPIPE. Added early return when old_fd == new_fd to avoid this race. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- kernel/src/ipc/fd.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/src/ipc/fd.rs b/kernel/src/ipc/fd.rs index ce44393..bc366d4 100644 --- a/kernel/src/ipc/fd.rs +++ b/kernel/src/ipc/fd.rs @@ -188,6 +188,17 @@ impl FdTable { return Err(9); // EBADF } + // Per POSIX: if old_fd == new_fd, just verify old_fd is valid and return it + // This avoids a race condition where close_read/close_write followed by + // add_reader/add_writer would temporarily set the count to zero + if old_fd == new_fd { + // Verify old_fd is valid + if self.fds[old_fd as usize].is_none() { + return Err(9); // EBADF + } + return Ok(new_fd); + } + let fd_entry = self.fds[old_fd as usize].clone().ok_or(9)?; // If new_fd is open, close it and decrement pipe ref counts