fd pollution on exec when using memfd transport
Summary
When libpulseaudio
uses memfd
transport, a stray /memfd:pulseaudio (deleted)
file descriptor remains after exec(2)
, which can pollute the fd tables of child processes.
Environment
libpulseaudio
15.0
PulseAudio 15.0.0 (on PipeWire 0.3.56); but this most likely also applies to real PulseAudio
Steps to reproduce
Compile a test program that lists its open file descriptors:
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
int main(){
DIR *d = opendir("/proc/self/fd");
if(!d) return 1;
struct dirent *dir;
char fdpath[sizeof("/proc/self/fd/4294967295")];
char link[PATH_MAX];
while(((dir = readdir(d)) != NULL)){
snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%.10s", dir->d_name);
ssize_t len = readlink(fdpath, link, sizeof(link));
link[len] = '\0';
printf("%s: %s\n", dir->d_name, link);
}
closedir(d);
return 0;
}
Then run this program by way of fork
+exec
from a program with an active memfd
-based PulseAudio connection.
One way is to up a terminal emulator that can use PulseAudio for events like terminal bells.
I found and could reproduce this on KDE's Konsole as well as its KonsolePart integration into Dolphin and Kate.
XFCE4 Terminal seems unaffected as it implements bells through X11 bells. GNOME Terminal appears to be in the same boat.
What is the current bug behavior?
File descriptor table of child processes is polluted by a stray memfd
:
0: /dev/pts/1
1: /dev/pts/1
2: /dev/pts/1
3: /proc/9612/fd
41: /memfd:pulseaudio (deleted)
What is the expected correct behavior?
No fd pollution should be observed. Specifically, the memfd
should have the CLOEXEC
flag.
memfd_create
is only called with MFD_ALLOW_SEALING
where it should probably be called with MFD_CLOEXEC
too, although I am unsure of the implications of this.