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>, Alyssa Ross <hi@alyssa.is>
Subject: [PATCH v2 5/6] isolation: Move --fd descriptor to a number of our choosing
Date: Fri, 17 Jul 2026 15:46:33 +1000 [thread overview]
Message-ID: <20260717054634.1293553-6-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260717054634.1293553-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_fds() so we don't close() it along with
any other file descriptors leaked into us by the parent.
More importantly, 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 more robustly, 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_fds() made
safe for --fd 1 and --fd 2, we can remove the logic excluding those from
conf_fd_tap().
Cc: Alyssa Ross <hi@alyssa.is>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
conf.c | 4 +---
isolation.c | 24 +++++++++++-------------
2 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/conf.c b/conf.c
index df204d13..0fcba5cf 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 725a72bb..94cbe7f8 100644
--- a/isolation.c
+++ b/isolation.c
@@ -248,7 +248,6 @@ void isolate_initial(void)
drop_caps_ep_except(keep);
}
-
/*
* isolate_fds() - Close leaked files, but not --fd, stdin, stdout, stderr
* @argc: Argument count
@@ -256,27 +255,26 @@ void isolate_initial(void)
*
* Should:
* - close all open files except for standard streams and the one from --fd
+ * - move the --fd descriptor out of the range 0-2
*
- * Return: fd number from --fd, or -1 if not specified
+ * Return: new fd number for descriptor from --fd, or -1 if not specified
*/
int isolate_fds(int argc, char **argv)
{
- int fd, rc;
+ int fd, close_from = STDERR_FILENO + 1;
fd = conf_tap_fd(argc, argv);
- if (fd == -1) {
- rc = close_range(STDERR_FILENO + 1, ~0U, CLOSE_RANGE_UNSHARE);
- } else if (fd == 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 - 1,
- CLOSE_RANGE_UNSHARE);
- if (!rc)
- rc = close_range(fd + 1, ~0U, CLOSE_RANGE_UNSHARE);
+ if (fd >= 0) {
+ /* Move the passed fd to a more convenient location */
+ if (fd != close_from &&
+ (dup2(fd, close_from) != close_from ||
+ close(fd)))
+ die_perror("Could not move --fd descriptor");
+ fd = 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
next prev 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 ` David Gibson [this message]
2026-07-17 5:46 ` [PATCH v2 6/6] main: Ensure fds 0-2 are populated 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=20260717054634.1293553-6-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=hi@alyssa.is \
--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).