Skip to content

Commit

Permalink
Workaround for fusermountN (#48)
Browse files Browse the repository at this point in the history
Switch to patched fuse3 that searches for fusermount, fusermount3... fusermountN
  • Loading branch information
probonopd authored Apr 14, 2024
1 parent 9bf80ec commit f0f6e67
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 9 deletions.
32 changes: 24 additions & 8 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,27 @@ if ! command -v apk; then
exit 1
fi

# Minimize binary size
export CFLAGS="-ffunction-sections -fdata-sections -Os"

apk update
apk add alpine-sdk util-linux strace file autoconf automake libtool
apk add alpine-sdk util-linux strace file autoconf automake libtool xz

# Build static libfuse3 with patch for https://github.com/AppImage/type2-runtime/issues/10
apk add eudev-dev gettext-dev linux-headers meson # From https://git.alpinelinux.org/aports/tree/main/fuse3/APKBUILD
wget -c -q "https://github.com/libfuse/libfuse/releases/download/fuse-3.15.0/fuse-3.15.0.tar.xz"
tar xf fuse-3.*.tar.xz
cd fuse-3.*/
patch -p1 < ../patches/libfuse/mount.c.diff
mkdir build
cd build
meson setup --prefix=/usr ..
meson configure --default-library static
ninja install
cd ../../

# Build static squashfuse
apk add fuse-dev fuse-static zstd-dev zstd-static zlib-dev zlib-static # fuse3-static fuse3-dev
apk add zstd-dev zstd-static zlib-dev zlib-static # fuse-dev fuse-static fuse3-static fuse3-dev
wget -c -q "https://github.com/vasi/squashfuse/archive/e51978c.tar.gz"
tar xf e51978c.tar.gz
cd squashfuse-*/
Expand All @@ -26,11 +42,11 @@ cd -
# Build static AppImage runtime
export GIT_COMMIT=$(cat src/runtime/version)
cd src/runtime
make runtime-fuse2 -j$(nproc)
file runtime-fuse2
strip runtime-fuse2
ls -lh runtime-fuse2
echo -ne 'AI\x02' | dd of=runtime-fuse2 bs=1 count=3 seek=8 conv=notrunc # magic bytes, always do AFTER strip
make runtime-fuse3 -j$(nproc)
file runtime-fuse3
strip runtime-fuse3
ls -lh runtime-fuse3
echo -ne 'AI\x02' | dd of=runtime-fuse3 bs=1 count=3 seek=8 conv=notrunc # magic bytes, always do AFTER strip
cd -

# Build static patchelf
Expand Down Expand Up @@ -125,7 +141,7 @@ strip bsdtar
cd -

mkdir -p out
cp src/runtime/runtime-fuse2 out/runtime-fuse2-$ARCHITECTURE
cp src/runtime/runtime-fuse3 out/runtime-fuse3-$ARCHITECTURE
cp patchelf-*/patchelf out/patchelf-$ARCHITECTURE
cp zsync-*/zsyncmake out/zsyncmake-$ARCHITECTURE
cp squashfs-tools-*/squashfs-tools/mksquashfs out/mksquashfs-$ARCHITECTURE
Expand Down
3 changes: 2 additions & 1 deletion chroot_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ cd -
#############################################

sudo cp -r ./src miniroot/src
sudo cp -r ./patches miniroot/patches

sudo mount -o bind /dev miniroot/dev
sudo mount -t proc none miniroot/proc
Expand Down Expand Up @@ -58,7 +59,7 @@ sudo umount miniroot/proc miniroot/sys miniroot/dev
if [ "$ARCHITECTURE" = "x86" ] ; then ARCHITECTURE=i686 ; fi

mkdir out/
sudo find miniroot/ -type f -executable -name 'runtime-fuse2' -exec cp {} out/runtime-fuse2-$ARCHITECTURE \;
sudo find miniroot/ -type f -executable -name 'runtime-fuse3' -exec cp {} out/runtime-fuse3-$ARCHITECTURE \;
sudo find miniroot/ -type f -executable -name 'patchelf' -exec cp {} out/patchelf-$ARCHITECTURE \;
sudo find miniroot/ -type f -executable -name 'zsyncmake' -exec cp {} out/zsyncmake-$ARCHITECTURE \;
sudo find miniroot/ -type f -executable -name 'mksquashfs' -exec cp {} out/mksquashfs-$ARCHITECTURE \;
Expand Down
130 changes: 130 additions & 0 deletions patches/libfuse/mount.c.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
diff --git a/lib/mount.c b/lib/mount.c
index d71e6fc55..acc1711ff 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,79 @@ 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;
+ }
+
+ // 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 +361,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 +407,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 +468,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 +482,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);
}

0 comments on commit f0f6e67

Please sign in to comment.