Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Also use libfuse3, fusermount3 in addition to libfuse2, fusermount #168

Closed
probonopd opened this issue Mar 26, 2022 · 11 comments
Closed

Also use libfuse3, fusermount3 in addition to libfuse2, fusermount #168

probonopd opened this issue Mar 26, 2022 · 11 comments

Comments

@probonopd
Copy link
Member

probonopd commented Mar 26, 2022

https://github.com/AppImage/libappimage/blob/1c2510ad2f385787e8fa5fdf88c0098f69095366/src/patches/squashfuse_dlopen.h#L24

Ubuntu 22.04 x64 (arriving next month -- note 22.04, not 20.04) does not ship libfuse.so.2 anymore but only libfuse.so.3 (upstream launchpad ticket; distribution policies may prevent them from shipping both by default indefinitely because fuse2 appears no longer actively maintaned by upstream). I think Fedora is doing the same. As a result, AppImages cannot run on Ubuntu 22.04 out of the box:

$ Downloads/Mu_Editor-x86_64.AppImage 
dlopen(): error loading libfuse.so.2

Hence, we should also try to dlopen() that one.

Like we are already doing for another library in the AppImageKit runtime:

https://github.com/AppImage/AppImageKit/blob/8bbf694455d00f48d835f56afaa1dabcd9178ba6/src/notify.c#L28-L45

Actually it may be a bit more involved than this, since the symbols inside libfuse may have changed in an incompatible way?

References:

@TheAssassin, @azubieta since I was never quite involved in the libappimage codebase, maybe one of you could have a look into this? I'd appreciate this very much, since having AppImages run out of the box on all supported mainstream distributions is quite important.

image

@probonopd
Copy link
Member Author

@JamesHenstridge points out:

If they're using FUSE, then it is likely that they depend on the host system /usr/bin/fusermount setuid executable, even if they're statically linked.

The binary was renamed to fusermount3 in libfuse 3.x

@probonopd probonopd changed the title Try to dlopen libfuse3, not just libfuse2 Also use libfuse3, fusermount3 in addition to libfuse2, fusermount Mar 27, 2022
@probonopd
Copy link
Member Author

probonopd commented Mar 27, 2022

As an alternative, there is also the option of statically linking (and possibly implementing the required parts of fusermount or using Golang for the runtime like in this POC).

Yes, it would add some (~3 MB?) overhead to each AppImage. But the result would be much more robust and future-proof. For AppImages that bundle all dependency libraries (currently the exception rather than the rule; another ~10 MB overhead), the result would be almost immune to userland breaking changes, almost only relying on the kernel, which is fortunately very stable when it comes to the userland interface.

Maybe that is the way to go. Wdyt?

@jhenstridge
Copy link

As I said on Twitter, the fusermount binary is setuid. If you want to ship your own copy, you'll need root access to set the file permissions.

@probonopd
Copy link
Member Author

Ouch. That's a bummer!
Need to check whether https://github.com/orivej/static-appimage/ is also using fusermount.

@probonopd
Copy link
Member Author

probonopd commented Apr 8, 2022

Need to check whether https://github.com/orivej/static-appimage/ is also using fusermount.

It is:

FreeBSD% ~/Desktop/Spotify.AppImage               
main.main (main.go:50): exec: "/bin/fusermount": stat /bin/fusermount: no such file or directory

https://github.com/hanwen/go-fuse/blob/74a933d6e856048cbff1a437bf3dbf79162e77de/fuse/api.go#L92-L97

// 1) go-fuse opens `/dev/fuse` and executes the `fusermount`
// setuid-root helper to call `mount(2)` for us. This is the default.
// Does not need root permissions but needs `fusermount` installed.
//
// 2) If `MountOptions.DirectMount` is set, go-fuse calls `mount(2)` itself.
// Needs root permissions, but works without `fusermount`.

So if we want AppImages to run without the need for the end user to have root rights (which we want), then it seems like whatever we do we will not get around using fusermount/fusermount3.

So it seems like statically linking libfuse2 or libfuse3 is not sufficient to ensure that things work on systems that come with a random libfuse version.

@probonopd
Copy link
Member Author

Highly relevant discussion:
libfuse/libfuse#460

@probonopd
Copy link
Member Author

probonopd commented Apr 30, 2022

Seems like go-fuse can work with both fusermount and fusermount3, which is a huge plus:

// fusermountBinary returns the path to the `fusermount3` binary, or, if not
// found, the `fusermount` binary.
func fusermountBinary() (string, error) {
	if path, err := lookPathFallback("fusermount3", "/bin"); err == nil {
		return path, nil
	}
	return lookPathFallback("fusermount", "/bin")
}

Now, there should be a guarantee that it will continue to work with fusermountN with N = 4...infinity.

Next step: Rebuild https://github.com/orivej/static-appimage/ with a recent https://github.com/hanwen/go-fuse/ version that includes the above, then test on systems with (only) libfuse2 and on systems with (only) libfuse3.

If it works, we could use this approach.

@probonopd
Copy link
Member Author

probonopd commented Apr 30, 2022

Another question:

If we statically link the current runtime, maybe using musl libc, will it require fusermount? If yes, can it be changed so that it won't require fusermount anymore?

What does fusermount do, after all? Allow users without root permissions to unmount FUSE mounts? Well, we don't need that, because AppImages unmount themselves after the payload application exits.

@TheAssassin, @azubieta: What do you think about statically linking the AppImage runtime using musl libc?

@azubieta
Copy link
Contributor

azubieta commented May 2, 2022

Random thought, can we make a composite elf that ships two runtimes one for fuse2 and other for fuse3 ?

The current AppRun has 25 Kb so this solution should be about 50 Kb.

@probonopd
Copy link
Member Author

probonopd commented May 2, 2022

I've experimented a bit with static runtimes built in Alpine Linux with musl libc. Still need to sort some things out. But a promising start.

@probonopd
Copy link
Member Author

Closing in favor of

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants