public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>, jirib79@gmail.com
Subject: [PATCH v2 6/6] main: Ensure fds 0-2 are populated
Date: Fri, 17 Jul 2026 15:46:34 +1000	[thread overview]
Message-ID: <20260717054634.1293553-7-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260717054634.1293553-1-david@gibson.dropbear.id.au>

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.

Cc: jirib79@gmail.com
Link: https://bugs.passt.top/show_bug.cgi?id=215
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 passt.c | 19 +++++++++++++------
 util.c  |  3 +--
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/passt.c b/passt.c
index e930df43..a2e7bf1f 100644
--- a/passt.c
+++ b/passt.c
@@ -330,8 +330,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;
@@ -344,6 +344,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;
@@ -411,11 +420,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");
 
@@ -431,6 +435,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;
diff --git a/util.c b/util.c
index ce5021a9..bd4c6caa 100644
--- a/util.c
+++ b/util.c
@@ -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;
-- 
2.55.0


      parent reply	other threads:[~2026-07-17  5:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17  5:46 [PATCH v2 0/6] Fix bug 215 and some related issues with fd handling David Gibson
2026-07-17  5:46 ` [PATCH v2 1/6] passt: Always close pidfile_fd, not just when daemonizing David Gibson
2026-07-17  5:46 ` [PATCH v2 2/6] isolation: Move close_open_files() to isolate_fds() David Gibson
2026-07-17  5:46 ` [PATCH v2 3/6] isolation, conf: Set c->fd_tap from early parse of --fd David Gibson
2026-07-17  5:46 ` [PATCH v2 4/6] conf: Make conf_tap_fd() operate more like conf_mode() David Gibson
2026-07-17  5:46 ` [PATCH v2 5/6] isolation: Move --fd descriptor to a number of our choosing David Gibson
2026-07-17  5:46 ` David Gibson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260717054634.1293553-7-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=jirib79@gmail.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).