diff --git a/lib/mount.c b/lib/mount.c index d71e6fc..e9c2ff0 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -41,7 +41,6 @@ #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0) #endif -#define FUSERMOUNT_PROG "fusermount3" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" #ifndef HAVE_FORK @@ -117,17 +116,87 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_OPT_END }; +int fileExists(const char* path); +char* findBinaryInFusermountDir(const char* binaryName); + +int fileExists(const char* path) { + FILE* file = fopen(path, "r"); + if (file) { + fclose(file); + return 1; + } + return 0; +} + +char* findBinaryInFusermountDir(const char* binaryName) { + // For security reasons, we do not search the binary on the $PATH; + // instead, we check if the binary exists in FUSERMOUNT_DIR + // as defined in meson.build + char* binaryPath = malloc(strlen(FUSERMOUNT_DIR) + strlen(binaryName) + 2); + strcpy(binaryPath, FUSERMOUNT_DIR); + strcat(binaryPath, "/"); + strcat(binaryPath, binaryName); + if (fileExists(binaryPath)) { + return binaryPath; + } + + // Debian, Ubuntu + char* binaryPath2 = malloc(strlen(binaryName) + 6); + strcat(binaryPath2, "/bin/"); + strcat(binaryPath2, binaryName); + if (fileExists(binaryPath2)) { + return binaryPath2; + } + + // If the binary does not exist in FUSERMOUNT_DIR, return NULL + return NULL; +} + +static const char *fuse_mount_prog(void) +{ + // Check if the FUSERMOUNT_PROG environment variable is set and if so, use it + const char *prog = getenv("FUSERMOUNT_PROG"); + if (prog) { + if (access(prog, X_OK) == 0) + return prog; + } + + // Check if there is a binary "fusermount3" + prog = findBinaryInFusermountDir("fusermount3"); + if (access(prog, X_OK) == 0) + return prog; + + // Check if there is a binary called "fusermount" + // This is known to work for our purposes + prog = findBinaryInFusermountDir("fusermount"); + if (access(prog, X_OK) == 0) + return prog; + + // For i = 4...99, check if there is a binary called "fusermount" + i + // It is not yet known whether this will work for our purposes, but it is better than not even attempting + for (int i = 4; i < 100; i++) { + prog = findBinaryInFusermountDir("fusermount" + i); + if (access(prog, X_OK) == 0) + return prog; + } + + // If all else fails, return NULL + return NULL; +} + static void exec_fusermount(const char *argv[]) { - execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv); - execvp(FUSERMOUNT_PROG, (char **) argv); + const char *fusermount_prog = fuse_mount_prog(); + if (fusermount_prog) { + execv(fusermount_prog, (char **) argv); + } } void fuse_mount_version(void) { int pid = fork(); if (!pid) { - const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL }; + const char *argv[] = { fuse_mount_prog(), "--version", NULL }; exec_fusermount(argv); _exit(1); } else if (pid != -1) @@ -300,7 +369,7 @@ void fuse_kern_unmount(const char *mountpoint, int fd) return; if(pid == 0) { - const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z", + const char *argv[] = { fuse_mount_prog(), "-u", "-q", "-z", "--", mountpoint, NULL }; exec_fusermount(argv); @@ -346,7 +415,7 @@ static int setup_auto_unmount(const char *mountpoint, int quiet) } } - argv[a++] = FUSERMOUNT_PROG; + argv[a++] = fuse_mount_prog(); argv[a++] = "--auto-unmount"; argv[a++] = "--"; argv[a++] = mountpoint; @@ -407,7 +476,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, } } - argv[a++] = FUSERMOUNT_PROG; + argv[a++] = fuse_mount_prog(); if (opts) { argv[a++] = "-o"; argv[a++] = opts; @@ -421,7 +490,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, snprintf(env, sizeof(env), "%i", fds[0]); setenv(FUSE_COMMFD_ENV, env, 1); exec_fusermount(argv); - perror("fuse: failed to exec fusermount3"); + perror("fuse: failed to exec fusermount"); _exit(1); }