My expectation is that when any user (possibly unprivileged) uses guestmount he can access everything inside without any permission checks unless "-o default_permissions" is not given as an option. This works fine for read(), but not for chdir(). Reproduce as follows: unprivileged@testbox:~$ guestmount -v -x --format=raw -a test.fs -m /dev/sda mnt This will mount test.fs in mnt and give verbose information. Then: unprivileged@testbox:~$ cd mnt unprivileged@testbox:~$ mkdir test_dir unprivileged@testbox:~$ chown root:root test_dir unprivileged@testbox:~$ chmod 700 test_dir unprivileged@testbox:~$ ls test_dir Everything worked perfectly so far (as it should). Note in particular that the last command was able to read the contents of test_dir. unprivileged@testbox:~$ cd test_dir -bash: cd: test_dir/: Permission denied This does not work. Output from guestmount: libguestfs: /test_dir: testing access mask X_OK: caller UID:GID = 998:998, file UID:GID = 0:0, file mode = 40700, result = EACCESS This can only come from the function mount_local_access() in lib/fuse.c It seems to do its own permission checking. However, the fuse documentation says that the access function (here: mount_local_access) from fuse_operations is not called if the 'default_permissions' mount option is given. So I do not understand what is going here. If -o default_permissions is given, the function is not called, but if it is not given we do not want to restrict the access anyway. (It seems that this should be used if a fuse filesystem wants to implement *its own* particular access controls.) My proposed fix is to remove the function completely or always return 0. Indeed I found this old discussion where removing it completely was tried, but some test failed: https://www.redhat.com/archives/libguestfs/2014-June/msg00080.html It would be interesting to know what actually happened there. Tested on version 1.40.2, but the code seems to be the same in the development tree.
As was discussed over and over again on IRC, please discuss this with the upstream fuse community to find out what the correct course of action is.
What question or input exactly would you like to have from the fuse community here?
Some sort of technical explanation of why the .access method exists if it's not useful, I guess. Or why FUSE modules are supposed to be parsing FUSE options? I want to hear from the FUSE community what the correct thing to do is. This is hardly unreasonable.
Hi! First of all I have to say that I've not contacted the libfuse team and all I'm saying is based on my own research and thoughts. It seems that the code actually using the `default_permissions` option resides here: https://github.com/torvalds/linux/blob/b3a9e3b9622ae10064826dccb4f7a52bd88c7407/fs/fuse/dir.c#L1139 So kernel will either (when `default_permissions` is supplied) issue a FUSE `getattr` and do it's own, regular file permission check or (when that option is not supplied), will forward the request to actual FUSE module to do whatever it wants. Libfuse side: https://github.com/libfuse/libfuse/blob/4322cffbe992aa0768f5ce310ef18f5d5340485e/include/fuse.h#L588 To me it sounds like there's no additional meaning given to that method, other than "regular file systems had that option, you can have it too". Let's look at that syscall description then: https://www.man7.org/linux/man-pages/man2/access.2.html The key element from that part here is that `access` syscall is checked using the real UID/GID so programs started with setuid bit can check whether the user on behalf of whom they act does have permissions for that file too. That last bit sounds like the real use case for the `access` method in general. In particular though… I can't think of reason why it would be useful in `libguestfs`'s case. As per the example in the first message of this bug report - `libguestfs` neither checks nor enforces the user permissions during regular operations so I don't see a reason why it should report otherwise in the query type methods. Proposal to make it always return 0 seems reasonable to me. Final bit of reasoning and my particular use case: I'm trying to run `debootstrap`/`multistrap` onto a `guestmount`ed file system (as a non-root user) and I'm getting exactly the same issue as in the first message - they're able to do all sorts of things with files, including changing the permissions, owners, etc,… but they do some (unreasonable in this case but nevertheless) access checks… which they fail and refuse to continue, which seems like a very unfortunate reason to fail (as the user mounting the file system already has all the permissions in the host system to modify the mounted files system's image). P.S. Thanks for all the hard work!
I have written to fuse-devel a few months ago, and there were some answers. See: https://sourceforge.net/p/fuse/mailman/message/36785025/ See in particular the last message by Miklos Szeredi, who says: "When in doubt look at sshfs." And all sshfs' access function does is check X_OK and if there are *any* executable bits at all on a regular file: if (mask & X_OK) { err = sshfs.op->getattr(path, &stbuf, NULL); if (!err) { if (S_ISREG(stbuf.st_mode) && !(stbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) err = -EACCES; } } I now believe this is the correct thing that libguestfs should also do. Filtering out the exec bit on regular files if there is not *any* executable bit makes them appear correctly in file managers and so on. Maybe this also fixes this: https://www.redhat.com/archives/libguestfs/2014-June/msg00080.html So I propose to remove the whole "if (fuse->uid != 0)" block in lib/fuse.c and replace it by if (mask & X_OK) if (S_ISREG(statbuf.st_mode) && !(statbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) ok = 0;
This product has been discontinued or is no longer tracked in Red Hat Bugzilla.
Reopening because Virtualization Tools has not been discontinued.