-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Description
Several file descriptors are leaked on error paths or lack the CLOEXEC flag. In library mode, ddprof_start_profiling() fork+execs the daemon — every FD without CLOEXEC in the parent service leaks into the ddprof child process. For long-running services, FD leaks on error paths also accumulate across profiler restarts.
1. FD leak in create_elf_from_self (src/create_elf.cc:18-35)
const int exe_fd = ::open("/proc/self/exe", O_RDONLY); // also missing O_CLOEXEC
// ...
if (!elf) { return {}; } // exe_fd leaked
if (elf_kind(...) != ELF_K_ELF) { return {}; } // exe_fd leaked
::close(exe_fd); // only on success pathShould use UniqueFd (already available in the codebase) for RAII cleanup, and add O_CLOEXEC.
2. FD leaks in ring_buffer_create (src/ringbuffer_utils.cc:54-73)
pevent->mapfd = memfd_create("allocation_ring_buffer", 1U /*MFD_CLOEXEC*/);
// ...
if (ftruncate(pevent->mapfd, buffer_size) == -1) {
DDRES_RETURN_ERROR_LOG(...); // mapfd leaked
}
pevent->fd = eventfd(0, 0); // missing EFD_CLOEXEC
if (pevent->fd == -1) {
DDRES_RETURN_ERROR_LOG(...); // mapfd leaked
}memfd_createcorrectly usesMFD_CLOEXEC, but thememfdis leaked ifftruncateoreventfdfails.eventfdis missingEFD_CLOEXEC.
3. accept() without SOCK_CLOEXEC (src/ipc.cc:429)
int const new_socket = ::accept(poll_fds[0].fd, nullptr, nullptr);The parent sockets correctly use SOCK_CLOEXEC (line 298, 334), but accepted connections don't inherit it. Should use accept4(..., SOCK_CLOEXEC).
4. signalfd without SFD_CLOEXEC (src/ipc.cc:385)
int const sfd = ::signalfd(-1, &mask, 0); // missing SFD_CLOEXEC5. pipe2 without O_CLOEXEC (src/daemonize.cc:28)
if (pipe2(pipefd, 0) == -1) { // missing O_CLOEXEC6. open without O_CLOEXEC (src/ddprof_module_lib.cc:240,300)
These already use UniqueFd for RAII, but are missing O_CLOEXEC:
UniqueFd fd_holder{::open(filepath.c_str(), O_RDONLY)}; // line 240
const UniqueFd fd_holder{::open(filepath, O_RDONLY)}; // line 300Impact
In library mode (used by services that dlopen libdd_profiling.so), these FDs leak into the fork+exec'd daemon child. The FD leaks on error paths (findings 1, 2) accumulate across profiler restarts in long-running services.