aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meson.build2
-rw-r--r--util/fusermount.c80
2 files changed, 54 insertions, 28 deletions
diff --git a/meson.build b/meson.build
index 0487639..cbcd70d 100644
--- a/meson.build
+++ b/meson.build
@@ -72,7 +72,7 @@ private_cfg.set_quoted('PACKAGE_VERSION', meson.project_version())
# Test for presence of some functions
test_funcs = [ 'fork', 'fstatat', 'openat', 'readlinkat', 'pipe2',
'splice', 'vmsplice', 'posix_fallocate', 'fdatasync',
- 'utimensat', 'copy_file_range', 'fallocate' ]
+ 'utimensat', 'copy_file_range', 'fallocate', 'close_range' ]
foreach func : test_funcs
private_cfg.set('HAVE_' + func.to_upper(),
cc.has_function(func, prefix: include_default, args: args_default))
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("/");