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
Support unmounting FUSE mounts #705
Conversation
651b362
to
b86f643
Compare
@karelzak This would be awesome to implement. |
Accessing FUSE mounts require suid/sgid (saved uid) to be equal to the owner of the mount. If mount is running as a setuid process, swapping creds by only setting the euid/egid isn't enough to change the suid/sgid as well. We must do a full setuid()/setgid(), but that removes our ability to re-assume the identity of the original euid. The solution is swap creds in a child process, preserving the creds of the parent.
FUSE mounts don't need an fstab entry to be unmounted. This checks if a mount is a FUSE mount before checking for the fstab entry, and if so returns success.
It's too late for release v2.33, but I don't see a problem to merge it to the next release. Well, it will require some changes, for example use read_all() and write_all() in canonicalize_path_restricted() and probably use libmount stuff to get user= and user_id= in is_fuse_mount(), but I'll do these cosmetic changes before the merge. Thanks. |
All those changes sound good Karel, thanks for looking into the patch. I can make the changes you're suggesting if that will speed things up for you, let me know.Question about /etc/mtab, is it always a symlink to /proc/mounts on Linux? If so, then no need for the logic to parse the user= option, fuse only sets that when /etc/mtab is a separate file.
|
Hey @karelzak just curious what the status on this was and if there is anything I can do to make this easier for you |
The libmount is able to maintain user= option in /run/mount/utab, so it works although you have mtab as a symlink to the /proc/mounts. The problem I see is the second patch -- it's not secure enough. We have to evaluate mount options again reliable (safe) source (for user= we use /etc/fstab) or we have to be sure that /sbin/umount.type will be really executed, otherwise the library uses umount(2) with uid=0. It's necessary to call mnt_context_prepare_helper() and make sure cxt->helper is set. I'll try to fix the patch. |
Accessing FUSE mounts require suid/sgid (saved uid) to be equal to the owner of the mount. If mount is running as a setuid process, swapping creds by only setting the euid/egid isn't enough to change the suid/sgid as well. We must do a full setuid()/setgid(), but that removes our ability to re-assume the identity of the original euid. The solution is swap creds in a child process, preserving the creds of the parent. [kzak@redhat.com: - use switch() rather than if() for fork - use all-io.h - close unused pipe[] ends - be more strict about used types] Addresses: #705 Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
@rianhunter it seems on Fedora is not /sbin/umount.fuse. How is it expected that umount(8) will umount the FS? The ideal for umount(8) would be ideal to drop permissions and execute /sbin/umount.fuse. I'd like to implement into libmount something like permanent uhelper=fuse for fuse if user= or user_id= is specified in mount table (mountinfo/mtab or so), but it requires installed /sbin/umount.fuse. |
@karelzak there is no EDIT: This patch originally worked by allowing umount(8) to call umount(2) on the mounted directory as setuid root, but only doing so if the suid had the right permissions. |
Well, my idea was to redirect to umount.fuse to avoid any security sensitive decisions for fuse in umount(8) and keep all in fuse code :-) It's probably paranoid overkill, it seems that user= or user_id= verification is good enough as the options are stored in kernel mount table or in mtab (both is unwritable for non-root users). I'll follow your original patch. Thanks. |
@rianhunter please, try and test topic/fuse-umount branch in util-linux repository. The branch contains your patches after my clean up. Note you can use
to avoid libtools scripts or make install ;-) |
Hmm this was working for me before on my branch but it doesn't work for me now with your new edits. Strange thing is that it is printing "permission denied" on umount(2) to stderr, but I don't see it ever calling umount(2) in strace: EDIT: removed strace since it doesn't correctly reflect setuid state EDIT: Turns out |
Ah, mnt_fs_get_user_options(cxt->fs) works only for user=, but no for user_id=. There should be mnt_fs_get_options() or mnt_fs_get_fs_options(). I'll fix it. The question is if we really need to support user= in this fuse use-case. The user= is already supported by standard libmount functionality and I guess user= is in the game only because we use it in /etc/fstab. There is no any relation to fuse. (Well, now it does not work, because canonicalize_path_restricted(), should be already fixed by the first your patch...) Would be enough to support user_id= which is independent on fstab and it is fuse specific and maintained in /proc/self/moutinfo by kernel/libfuse? I have removed support for user= and updated support for user_id=. Please, try it. |
The option user= is already handled by evaluate_permissions() and by classic mount and umount usermount support. It seems we do not need to duplicate support for user= in is_fuse_usermount(). The option user_id= is fuse specific and it's maintained by libfuse/kernel in /proc/self/mountinfo. This is feature we need to support in umount(8). Addresses: #705 Signed-off-by: Karel Zak <kzak@redhat.com>
@karelzak Yes I think it's enough to only support Edit: Tried your new commit and it works 👍 Nice job |
Accessing FUSE mounts require suid/sgid (saved uid) to be equal to the owner of the mount. If mount is running as a setuid process, swapping creds by only setting the euid/egid isn't enough to change the suid/sgid as well. We must do a full setuid()/setgid(), but that removes our ability to re-assume the identity of the original euid. The solution is swap creds in a child process, preserving the creds of the parent. [kzak@redhat.com: - use switch() rather than if() for fork - use all-io.h - close unused pipe[] ends - be more strict about used types] Addresses: #705 Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
The option user= is already handled by evaluate_permissions() and by classic mount and umount usermount support. It seems we do not need to duplicate support for user= in is_fuse_usermount(). The option user_id= is fuse specific and it's maintained by libfuse/kernel in /proc/self/mountinfo. This is feature we need to support in umount(8). Addresses: #705 Signed-off-by: Karel Zak <kzak@redhat.com>
Merged to the master branch. Thanks for review and tests! |
FUSE mounts don't need an fstab entry to be unmounted. This checks if a mount is a FUSE mount before checking for the fstab entry, and if so returns success.
Also, make a change to how restricted path canonicalization is done to support FUSE mount points.