-
Notifications
You must be signed in to change notification settings - Fork 178
Description
Describe the bug
The O_CLOEXEC (or FD_CLOEXEC) flag is correctly captured and stored in file descriptor metadata when files are opened, but the flag is not acted upon during execve syscall processing. According to Linux kernel behavior, all file descriptors with the O_CLOEXEC flag set should be automatically closed when a process calls execve, but libsinsp currently does not implement this behavior.
Current behavior:
- The
O_CLOEXECflag is correctly captured from syscalls (e.g.,open,openat,pipe2,dup3) and stored insinsp_fdinfo::m_openflagsasPPM_O_CLOEXEC(seeuserspace/libsinsp/parsers.cpp:2075). - The flag is preserved in the fd table and can be queried via
m_openflags. - When
execveis called, the parser (parse_execve_exit()) does not check for or close file descriptors with thePPM_O_CLOEXECflag set. The fd table remains unchanged, leading to an incorrect state where CLOEXEC-marked fds appear to still be open after execve.
Impact:
- Incorrect fd counts in the process state
- Potential false positive due to stale cahced information when querying FDs that should have been closed
How to reproduce it
-
Capture events from a process that:
- Opens a file descriptor with
O_CLOEXECflag (e.g.,open(path, O_RDONLY | O_CLOEXEC)) - Calls
execve()to execute a new program - The new program opens a file and reuses the same FD number
- Opens a file descriptor with
-
Query the fd table after execve for the CLOEXEC-marked FD
-
Observe that the FD still exists in the table with stale information (file path, metadata from before execve)
Minimal reproduction example:
// Program opens file with O_CLOEXEC
int fd = open("/tmp/test", O_RDONLY | O_CLOEXEC);
// Process calls execve
execve("/bin/ls", argv, envp);
// New program may reuse fd=3, but libsinsp still has stale info for the old fd=3Expected behaviour
When a process calls execve (or execveat), all file descriptors that were opened with the O_CLOEXEC flag should be automatically closed in libsinsp's internal fd table, mirroring the kernel's behavior. After execve:
- FDs with
PPM_O_CLOEXECset should be removed from the fd table - Queries for those FDs should return
nullptror indicate the FD doesn't exist - No stale information should be retrievable for CLOEXEC-marked FDs
Screenshots
N/A
Environment
- Falco version: N/A (libsinsp issue, affects all versions)
- System info: N/A
- Cloud provider or hardware configuration: N/A
- OS: Linux (any distribution)
- Kernel: Any kernel version that supports
O_CLOEXEC - Installation method: N/A (libsinsp library issue)
Additional context
Relevant Code Locations:
-
Flag Storage:
userspace/libsinsp/parsers.cpp:2075-fdi->m_openflags = flags;stores the flagdriver/ppm_events_public.h:108-PPM_O_CLOEXECdefinition
-
Missing execve Handling:
userspace/libsinsp/parsers.cpp:1728-1734-parse_execve_exit()has a commented-out section about clearing the fd table, but no CLOEXEC-specific logic- The function should iterate through the fd table and close fds with
PPM_O_CLOEXECset
-
Acknowledgment of Limitation:
userspace/libsinsp/fdtable.cpp:103-110- Comment states "which we don't currently parse" and "XXX Can't have this enabled until the FD_CLOEXEC flag is supported"userspace/libscap/scap_procs.c:107-109- Similar comment in libscap code
References:
- Linux
execve(2)man page: "By default, file descriptors remain open across anexecve(). File descriptors that are marked close-on-exec are closed" O_CLOEXECflag documentation in Linuxopen(2)man page- Kernel source: File descriptors with
FD_CLOEXECset are closed indo_execveat_common()→do_close_on_exec()