Extract `Channel` FD and self-mount
Hi, I have a use case (containers) where I need to get the session FD and do the mounting myself. I took a look at changing the API to support this, but unfortunately, it seems like mnt::Mount and Session are pretty tied together at the moment.
Before I propose any significant API changes, do you have an idea how I could achieve this?
Thanks!
I poked around a bit more. First, let me clarify roughly what I'd like to do:
- Create a
Sessionwith myFileSystem. - Call
AsFd::as_fdon theSession. Then, take that FD, and pass it into my own mount(2) call withfd=123. - Call
Session::runto proceed as normal.
Fundamentally, this seems like it would require splitting Session into two types: one which holds the /dev/fuse FD (the Channel), and one which knows the mountpoint and calls umount when it's dropped.
However, The fact that a session is also a mountpoint, as far as the API is concerned, seems to stem from libfuse. That's because fuse_session_new takes the mount args already. So while the above change would be fairly trivial with fuse_pure, it's not easy with libfuse.
I don't suppose you'd consider dropping support for libfuse? :sweat_smile:
Huh, there's also a (very wacky) libfuse3 way to do this: https://github.com/libfuse/libfuse/pull/291
Can you tell me more about the use case? I'm trying to understand if this is common enough that it should be support in fuser
Can you tell me more about the use case? I'm trying to understand if this is common enough that it should be support in fuser
FUSE plays a special role in containers, where it can be used to simulate kernel-level stuff like sysfs or character devices. This is specifically permitted for unprivileged container runtimes by the kernel. However, various security safeguards mean that it requires a very specific dance:
/dev/fusehas to be opened inside the container (inside the user namespace where the mount call happens)- The
mount(orfsconfig/move_mount) syscalls have to be done inside the container as well - If the fuse daemon wants to run outside the container (e.g. in the runtime), the FD has to be passed back out to the supervisor process (using a socket or something)
- The channel can then be polled for requests normally (
Session::run)
One less-invasive way achieve this would be to offer a way to just iterate the Requests given a /dev/fuse FD. That would mean users wouldn't have access to the Filesystem abstraction, however.
We also have a similar use-case in https://github.com/awslabs/mountpoint-s3-csi-driver. We want to run FUSE/fuser process inside an unprivileged Kubernetes Pod (so we can't do mount syscall). We already have a privileged Pod for doing the mount (i.e., opening /dev/fuse and performing mount syscall), and we want to pass obtained file descriptor to our unprivileged Pod where FUSE/fuser process lives.
I see, thanks for the links! It sounds to me like the best thing to do is to add a method like Session::from_raw_fd. You can then open /dev/fuse and call mount() anyway that you want, pass the resulting fd to the correct process, and then call Session::from_raw_fd to create a fuser Session which can run and serve the fuse operations.
Does that sound like it will work for both of your use cases?
It sounds to me like the best thing to do is to add a method like Session::from_raw_fd.
Yes, that's what #301 does :)
Edit: and also #304, if you prefer less refactoring.
Ah, great. I left some comments on #304. I'd rather not remove the libfuse support right now
Hey @cberner, is there any reason for not dropping support for libfuse? Are there any known limitations of pure-Rust mounting?
Just unknown unknowns. libfuse is enabled in the default features, and I don't know what the limitations of the pure Rust implementations are. I think it might not work with some of the mac kernel extensions, but haven't tested them. If you're interested in researching and testing all the different platforms and configs, that'd be great!
Thanks for the context @cberner! We'll be sharing if we find any limitations.