aboutsummaryrefslogtreecommitdiffstats
path: root/util/fusermount.c
diff options
context:
space:
mode:
authorBernd Schubert <bschubert@ddn.com>2025-02-23 00:17:39 +0100
committerBernd Schubert <bernd@bsbernd.com>2025-03-18 17:34:19 +0100
commitb9fc5a0ff8905a27e48cdac1ae26a8964fe87727 (patch)
tree5fea9879283e5b6a97e24c037c847955637b9150 /util/fusermount.c
parent1b86fe4c4de96daa4e766425193595f1c6b88a73 (diff)
downloadlibfuse-b9fc5a0ff8905a27e48cdac1ae26a8964fe87727.tar.gz
fusermount: prevent stdio FDs from being reused
Redirect stdin/stdout/stderr to /dev/null to prevent newly opened file descriptors from reusing these low numbers (0,1,2) and potential issues with that. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'util/fusermount.c')
-rw-r--r--util/fusermount.c80
1 files changed, 53 insertions, 27 deletions
diff --git a/util/fusermount.c b/util/fusermount.c
index acbff61..dbd947c 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -7,7 +7,7 @@
*/
/* This program does the mounting and unmounting of FUSE filesystems */
-#define _GNU_SOURCE /* for clone and strchrnul */
+#define _GNU_SOURCE /* for clone,strchrnul and close_range */
#include "fuse_config.h"
#include "mount_util.h"
#include "util.h"
@@ -36,6 +36,10 @@
#include <stdbool.h>
#include <sys/vfs.h>
+#ifdef HAVE_CLOSE_RANGE
+#include <linux/close_range.h>
+#endif
+
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_DEV "/dev/fuse"
@@ -1452,44 +1456,63 @@ static void show_version(void)
exit(0);
}
+static void close_range_loop(int min_fd, int max_fd, int cfd)
+{
+ for (int fd = min_fd; fd <= max_fd; fd++)
+ if (fd != cfd)
+ close(fd);
+}
+
/*
* Close all inherited fds that are not needed
* Ideally these wouldn't come up at all, applications should better
* use FD_CLOEXEC / O_CLOEXEC
*/
-static void close_inherited_fds(int cfd)
+static int close_inherited_fds(int cfd)
{
- int max_fd = sysconf(_SC_OPEN_MAX);
- int rc;
+ int rc = -1;
+ int nullfd;
-#ifdef CLOSE_RANGE_CLOEXEC
- /* high range first to be able to log errors through stdout/err*/
- rc = close_range(cfd + 1, ~0U, 0);
- if (rc < 0) {
- fprintf(stderr, "Failed to close high range of FDs: %s",
- strerror(errno));
- goto fallback;
- }
+ /* We can't even report an error */
+ if (cfd <= STDERR_FILENO)
+ return -EINVAL;
- rc = close_range(0, cfd - 1, 0);
- if (rc < 0) {
- fprintf(stderr, "Failed to close low range of FDs: %s",
- strerror(errno));
- goto fallback;
+#ifdef HAVE_CLOSE_RANGE
+ if (cfd < STDERR_FILENO + 2) {
+ close_range_loop(STDERR_FILENO + 1, cfd - 1, cfd);
+ } else {
+ rc = close_range(STDERR_FILENO + 1, cfd - 1, 0);
+ if (rc < 0)
+ goto fallback;
}
+
+ /* Close high range */
+ rc = close_range(cfd + 1, ~0U, 0);
+#else
+ goto fallback; /* make use of fallback to avoid compiler warnings */
#endif
fallback:
- /*
- * This also needs to close stdout/stderr, as the application
- * using libfuse might have closed these FDs and might be using
- * it. Although issue is now that logging errors won't be possible
- * after that.
- */
- for (int fd = 0; fd <= max_fd; fd++) {
- if (fd != cfd)
- close(fd);
+ if (rc < 0) {
+ int max_fd = sysconf(_SC_OPEN_MAX) - 1;
+
+ close_range_loop(STDERR_FILENO + 1, max_fd, cfd);
}
+
+ nullfd = open("/dev/null", O_RDWR);
+ if (nullfd < 0) {
+ perror("fusermount: cannot open /dev/null");
+ return -errno;
+ }
+
+ /* Redirect stdin, stdout, stderr to /dev/null */
+ dup2(nullfd, STDIN_FILENO);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ if (nullfd > STDERR_FILENO)
+ close(nullfd);
+
+ return 0;
}
int main(int argc, char *argv[])
@@ -1616,6 +1639,7 @@ int main(int argc, char *argv[])
goto err_out;
}
+
{
struct stat statbuf;
fstat(cfd, &statbuf);
@@ -1653,7 +1677,9 @@ wait_for_auto_unmount:
Btw, we don't want to use daemon() function here because
it forks and messes with the file descriptors. */
- close_inherited_fds(cfd);
+ res = close_inherited_fds(cfd);
+ if (res < 0)
+ exit(EXIT_FAILURE);
setsid();
res = chdir("/");