From b9fc5a0ff8905a27e48cdac1ae26a8964fe87727 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Sun, 23 Feb 2025 00:17:39 +0100 Subject: 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 --- util/fusermount.c | 80 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 27 deletions(-) (limited to 'util') 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 #include +#ifdef HAVE_CLOSE_RANGE +#include +#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("/"); -- cgit v1.2.3