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_CLOEXEC flag is correctly captured from syscalls (e.g., open, openat, pipe2, dup3) and stored in sinsp_fdinfo::m_openflags as PPM_O_CLOEXEC (see userspace/libsinsp/parsers.cpp:2075).
- The flag is preserved in the fd table and can be queried via
m_openflags.
- When
execve is called, the parser (parse_execve_exit()) does not check for or close file descriptors with the PPM_O_CLOEXEC flag 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_CLOEXEC flag (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
-
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=3
Expected 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_CLOEXEC set should be removed from the fd table
- Queries for those FDs should return
nullptr or 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 flag
driver/ppm_events_public.h:108 - PPM_O_CLOEXEC definition
-
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_CLOEXEC set
-
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 an execve(). File descriptors that are marked close-on-exec are closed"
O_CLOEXEC flag documentation in Linux open(2) man page
- Kernel source: File descriptors with
FD_CLOEXEC set are closed in do_execveat_common() → do_close_on_exec()
Describe the bug
The
O_CLOEXEC(orFD_CLOEXEC) flag is correctly captured and stored in file descriptor metadata when files are opened, but the flag is not acted upon duringexecvesyscall processing. According to Linux kernel behavior, all file descriptors with theO_CLOEXECflag set should be automatically closed when a process callsexecve, but libsinsp currently does not implement this behavior.Current behavior:
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).m_openflags.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:
How to reproduce it
Capture events from a process that:
O_CLOEXECflag (e.g.,open(path, O_RDONLY | O_CLOEXEC))execve()to execute a new programQuery 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:
Expected behaviour
When a process calls
execve(orexecveat), all file descriptors that were opened with theO_CLOEXECflag should be automatically closed in libsinsp's internal fd table, mirroring the kernel's behavior. After execve:PPM_O_CLOEXECset should be removed from the fd tablenullptror indicate the FD doesn't existScreenshots
N/A
Environment
O_CLOEXECAdditional 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_CLOEXECdefinitionMissing 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 logicPPM_O_CLOEXECsetAcknowledgment 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 codeReferences:
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 pageFD_CLOEXECset are closed indo_execveat_common()→do_close_on_exec()