Skip to content
Snippets Groups Projects
Verified Commit df8e2ded authored by Jacob Lorentzon's avatar Jacob Lorentzon
Browse files

Fix file descriptor leak in fork().

parent 777a82b5
No related branches found
No related tags found
No related merge requests found
......@@ -119,9 +119,11 @@ pub fn fork_impl() -> Result<usize> {
}
fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
let new_pid = {
let (cur_filetable_fd, new_pid_fd, new_pid);
{
let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?);
let (new_pid_fd, new_pid) = new_context()?;
(new_pid_fd, new_pid) = new_context()?;
// Do not allocate new signal stack, but copy existing address (all memory will be re-mapped
// CoW later).
......@@ -138,6 +140,18 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
copy_str(*cur_pid_fd, *new_pid_fd, "name")?;
copy_str(*cur_pid_fd, *new_pid_fd, "cwd")?;
// Copy existing files into new file table, but do not reuse the same file table (i.e. new
// parent FDs will not show up for the child).
{
cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?);
// This must be done before the address space is copied.
unsafe {
initial_rsp.write(*cur_filetable_fd);
initial_rsp.add(1).write(*new_pid_fd);
}
}
// CoW-duplicate address space.
{
let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?);
......@@ -190,22 +204,18 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
let buf = create_set_addr_space_buf(*new_addr_space_fd, fork_ret as usize, initial_rsp as usize);
let _ = syscall::write(*new_addr_space_sel_fd, &buf)?;
}
// Copy existing files into new file table, but do not reuse the same file table (i.e. new
// parent FDs will not show up for the child).
{
let cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?);
// TODO: Use cross_scheme_links or something similar to avoid copying the file table in the
// kernel.
let new_filetable_fd = FdGuard::new(syscall::dup(*cur_filetable_fd, b"copy")?);
let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?);
let _ = syscall::write(*new_filetable_sel_fd, &usize::to_ne_bytes(*new_filetable_fd));
}
copy_float_env_regs(*cur_pid_fd, *new_pid_fd)?;
new_pid
};
}
// Copy the file table. We do this last to ensure that all previously used file descriptors are
// closed. The only exception -- the filetable selection fd and the current filetable fd --
// will be closed by the child process.
{
// TODO: Use cross_scheme_links or something similar to avoid copying the file table in the
// kernel.
let new_filetable_fd = FdGuard::new(syscall::dup(*cur_filetable_fd, b"copy")?);
let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?);
let _ = syscall::write(*new_filetable_sel_fd, &usize::to_ne_bytes(*new_filetable_fd));
}
// Unblock context.
syscall::kill(new_pid, SIGCONT)?;
......@@ -216,6 +226,11 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
unsafe extern "sysv64" fn __relibc_internal_fork_impl(initial_rsp: *mut usize) -> usize {
Error::mux(fork_inner(initial_rsp))
}
#[no_mangle]
unsafe extern "sysv64" fn __relibc_internal_fork_hook(cur_filetable_fd: usize, new_pid_fd: usize) {
let _ = syscall::close(cur_filetable_fd);
let _ = syscall::close(new_pid_fd);
}
#[no_mangle]
core::arch::global_asm!("
......@@ -233,13 +248,19 @@ fork_wrapper:
push r14
push r15
sub rsp, 16
mov rdi, rsp
call __relibc_internal_fork_impl
jmp 2f
fork_ret:
mov rdi, [rsp]
mov rsi, [rsp + 8]
call __relibc_internal_fork_hook
xor rax, rax
2:
add rsp, 16
pop r15
pop r14
pop r13
......
......@@ -88,9 +88,6 @@ fn fexec_impl_inner(file: File, path: &[u8], args: &[&[u8]], envs: &[&[u8]], arg
// some misalignments, and then execute the SYS_EXEC syscall to replace the program memory
// entirely.
// TODO: Introduce RAII guards to all owned allocations so that no leaks occur in case of
// errors.
let mut header_bytes = [0_u8; core::mem::size_of::<Header>()];
read_all(fd, Some(0), &mut header_bytes)?;
let header = Header::from_bytes(&header_bytes);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment