dup2 registers the stale fd instead of the dup() result, leaking a host fd per call
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 821
- Forks
- 23
- PR merge metrics
- No merged PRs in 30d
Description
Summary
The SYS_dup2 handler (lib/tinykvm/linux/system_calls.cpp:1066) registers
the old translation instead of the fd it just created:
const int result = dup(fd);
if (result < 0) {
regs.sysret() = -errno;
} else {
cpu.machine().fds().manage_as(new_vfd, new_fd, false, false);
// ^^^^^^ should be `result`
regs.sysret() = new_vfd;
}
new_fd is the previous translation of new_vfd (or -1 if there was none).
The fd returned by dup() is never recorded, so it is leaked, and the virtual
fd is bound to an fd that is stale or invalid.
Three observed shapes
- Wrong return + fd leak.
dup2(1, 5)onto an unused virtual fd returns
-EBADFwhere Linux returns success, and leaks one host fd per call. 64
calls leave +64 host fds open after the VM is destroyed. - Binding to a closed fd. When
new_vfddid have a prior translation, the
handler closes that host fd earlier in the function and then re-registers
it:fcntl(76, F_GETFD)on the resulting vfd returns -1. - Aliasing after fd recycling. Once the kernel recycles the closed fd
number, the stale vfd and a legitimately-opened new vfd refer to the same
host fd. A byte written into a newly created pipe was read back through the
stale vfd, which perdup2semantics should be a different pipe's write
end. In a multi-VM host process the recyclingopen()can come from another
tenant; we did not demonstrate that variant, but nothing structurally
prevents it.
Fix
cpu.machine().fds().manage_as(new_vfd, result, false, false);
and close(result) on the path where manage_as throws, so the failure case
does not leak either.
Test
tests/unit/syscalls.cpp — "dup2 onto a fresh virtual fd must succeed and not
go stale". Fails on the current tree with FAILED: 2 == 0.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the SYS_dup2 handler in lib/tinykvm/linux/system_calls.cpp:1066 and run the named test in tests/unit/syscalls.cpp. Verify that the virtual fd is registered with the dup() result and that a manage_as failure does not leak it. Done means the fresh-virtual-fd test passes and the observed stale-fd and leak behavior is corrected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100