public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 4/6] isolation: Move --fd descriptor to a number of our choosing
Date: Tue, 14 Jul 2026 19:29:24 +1000	[thread overview]
Message-ID: <20260714092926.2881848-5-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260714092926.2881848-1-david@gibson.dropbear.id.au>

Some users of passt pass an fd for the tap interface in, with the --fd
parameter, rather than having passt open it itself.  This requires some
slightly fiddly logic in isolate_initial() so we don't close() it along
with any other file descriptors leaked into us by hte parent.

More importantly, however, this is broken if the passed fd is 0, 1 or 2,
since in that case we will assume it's a standard stream and close it in
__daemon().  We explicitly disallow 1 or 2 in conf_tap_fd(), but 0 has been
permitted since aa1cc8922 ("conf: allow --fd 0").  It looks like the use
case of the contributor of that patch didn't involve daemonizing passt.

To fix this, use dup2() to move to the passed fd to 3.  This removes the
possibility of mixing it up with a standard stream, and as a bonus makes
the close_range() logic much simpler.  With isolate_initial() made safe
for --fd 1 and --fd 2, we can remove the logic excluding those from
conf_fd_tap().

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 conf.c      |  4 +---
 isolation.c | 21 +++++++++------------
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/conf.c b/conf.c
index f0bce41b..67f0db6e 100644
--- a/conf.c
+++ b/conf.c
@@ -1177,9 +1177,7 @@ int conf_tap_fd(int argc, char **argv)
 		return -1;
 
 	p = fdarg;
-	if (!parse_unsigned(&p, 0, &val) || !parse_eoi(p)	||
-	    val > INT_MAX					||
-	    (val != STDIN_FILENO && val <= STDERR_FILENO))
+	if (!parse_unsigned(&p, 0, &val) || !parse_eoi(p) || val > INT_MAX)
 		die("Invalid --fd: %s", fdarg);
 
 	return val;
diff --git a/isolation.c b/isolation.c
index c4d476d6..1a7b8527 100644
--- a/isolation.c
+++ b/isolation.c
@@ -207,7 +207,7 @@ static int move_root(void)
  */
 int isolate_initial(int argc, char **argv)
 {
-	int rc, fd_tap = -1;
+	int fd_tap = -1, close_from = STDERR_FILENO + 1;
 	uint64_t keep;
 
 	/* We want to keep CAP_NET_BIND_SERVICE in the initial
@@ -249,19 +249,16 @@ int isolate_initial(int argc, char **argv)
 	drop_caps_ep_except(keep);
 
 	fd_tap = conf_tap_fd(argc, argv);
-
-	if (fd_tap == -1) {
-		rc = close_range(STDERR_FILENO + 1, ~0U, CLOSE_RANGE_UNSHARE);
-	} else if (fd_tap == STDERR_FILENO + 1) { /* Still a single range */
-		rc = close_range(STDERR_FILENO + 2, ~0U, CLOSE_RANGE_UNSHARE);
-	} else {
-		rc = close_range(STDERR_FILENO + 1, fd_tap - 1,
-				 CLOSE_RANGE_UNSHARE);
-		if (!rc)
-			rc = close_range(fd_tap + 1, ~0U, CLOSE_RANGE_UNSHARE);
+	if (fd_tap >= 0) {
+		/* Move the passed fd to a more convenient location */
+		if (fd_tap != close_from			&&
+		    (dup2(fd_tap, close_from) != close_from	||
+		     close(fd_tap)))
+			die_perror("Could not move --fd descriptor");
+		fd_tap = close_from++;
 	}
 
-	if (rc) {
+	if (close_range(close_from, ~0U, CLOSE_RANGE_UNSHARE)) {
 		if (errno == ENOSYS || errno == EINVAL) {
 			/* This probably means close_range() or the
 			 * CLOSE_RANGE_UNSHARE flag is not supported by the
-- 
2.55.0


  parent reply	other threads:[~2026-07-14  9:29 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14  9:29 [PATCH 0/6] Fix bug 215 and some related issues with fd handling David Gibson
2026-07-14  9:29 ` [PATCH 1/6] isolation, util: Fold close_open_files() into isolate_initial() David Gibson
2026-07-15  7:12   ` Stefano Brivio
2026-07-14  9:29 ` [PATCH 2/6] isolation, conf: Set c->fd_tap from eary parse of --fd David Gibson
2026-07-15  7:12   ` Stefano Brivio
2026-07-14  9:29 ` [PATCH 3/6] conf: Make conf_tap_fd() operate more like conf_mode() David Gibson
2026-07-14  9:29 ` David Gibson [this message]
2026-07-14  9:29 ` [PATCH 5/6] main: Ensure fds 0-2 are populated David Gibson
2026-07-14  9:29 ` [PATCH 6/6] passt: *Always* close pidfile_fd, not just when daemonizing David Gibson

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=20260714092926.2881848-5-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --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).