diff options
| author | David Gibson <david@gibson.dropbear.id.au> | 2026-07-17 15:46:34 +1000 |
|---|---|---|
| committer | Stefano Brivio <sbrivio@redhat.com> | 2026-07-18 09:54:37 +0200 |
| commit | c80d9db312dfa98909bf3b3a5b2655785cdb3b07 (patch) | |
| tree | 67fd6711a3090d42f60600d9d3c890f1ed910e76 | |
| parent | fd5b0807f5d0706e9247662f26c31b6bc8337f19 (diff) | |
| download | passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar.gz passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar.bz2 passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar.lz passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar.xz passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.tar.zst passt-c80d9db312dfa98909bf3b3a5b2655785cdb3b07.zip | |
main: Ensure fds 0-2 are populated
Usually fds 0-2 are stdin, stdout and stderr. However, there are certain
use cases where passt can be invoked with one or more of those standard fds
closed. In those cases, anything we open might be placed in one of the
standard slots. For the handful of things we open early enough, this can
be a problem because we close fds 0-2 in __daemon(), replacing them with
dupes of /dev/null.
We could avoid closing those fds in __daemon() if they're not standard
streams. However, leaving things other than the standard streams in fds
0-2 is a footgun: a stray printf() that occurs in a circumstance it
shouldn't could send harmful garbage to a device or socket. It's also
likely to be confusing if debugging with strace or similar.
To avoid this, fill any missing standard streams with a dupe of /dev/null,
right after isolate_fds(). Since open()ing /dev/null itself could land in
one of those fd 0-2 slots, we need to be careful when we close it not to
leave a new gap.
Link: https://bugs.passt.top/show_bug.cgi?id=215
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
| -rw-r--r-- | passt.c | 19 | ||||
| -rw-r--r-- | util.c | 3 |
2 files changed, 14 insertions, 8 deletions
@@ -333,8 +333,8 @@ static void passt_worker(void *opaque, int nfds, struct epoll_event *events) int main(int argc, char **argv) { struct epoll_event events[NUM_EPOLL_EVENTS]; + int nfds, devnull_fd = -1, fd; struct ctx *c = &passt_ctx; - int nfds, devnull_fd = -1; struct rlimit limit; struct timespec now; struct sigaction sa; @@ -347,6 +347,15 @@ int main(int argc, char **argv) isolate_initial(); c->fd_tap = isolate_fds(argc, argv); + if ((devnull_fd = open("/dev/null", O_RDWR | O_CLOEXEC)) < 0) + die_perror("Failed to open /dev/null"); + /* Ensure fds 0-2 are populated */ + for (fd = 0; fd <= STDERR_FILENO; fd++) { + if (fcntl(fd, F_GETFD) < 0 && + dup2(devnull_fd, fd) < 0) + die_perror("Failed to populate fd %d", fd); + } + sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = exit_handler; @@ -414,11 +423,6 @@ int main(int argc, char **argv) fwd_neigh_table_init(c); nl_neigh_notify_init(c); - if (!c->foreground) { - if ((devnull_fd = open("/dev/null", O_RDWR | O_CLOEXEC)) < 0) - die_perror("Failed to open /dev/null"); - } - if (isolate_prefork(c)) die("Failed to sandbox process, exiting"); @@ -434,6 +438,9 @@ int main(int argc, char **argv) c->pidfile_fd = -1; } + if (devnull_fd > STDERR_FILENO) + close(devnull_fd); + if (pasta_child_pid) { kill(pasta_child_pid, SIGUSR1); log_stderr = false; @@ -522,8 +522,7 @@ int __daemon(int pidfile_fd, int devnull_fd) if (setsid() < 0 || dup2(devnull_fd, STDIN_FILENO) < 0 || dup2(devnull_fd, STDOUT_FILENO) < 0 || - dup2(devnull_fd, STDERR_FILENO) < 0 || - close(devnull_fd)) + dup2(devnull_fd, STDERR_FILENO) < 0) passt_exit(EXIT_FAILURE); return 0; |
