fuse: Don't override access(X_OK) if user is root.

Bug originally reported here by trysis:
https://stackoverflow.com/questions/64273334/test-x-in-mounted-filesystem

If the user is root then we override normally access controls in FUSE,
see https://bugzilla.redhat.com/show_bug.cgi?id=1106548.

However this causes test -x to mark all files as executable.  We
shouldn't let root execute any file, only ones which have the 'x' bit
set.  Therefore this narrows the fix in bug 1106548 so it only applies
to read and write bits.

To test this I created a disk with guestfish which had an executable
and a non-executable file:

  $ guestfish -N fs -m /dev/sda1
  ><fs> touch /file1
  ><fs> touch /file2
  ><fs> chmod 0755 /file1
  ><fs> ll /
  total 24
  drwxr-xr-x  3 root root  4096 Oct 12 14:04 .
  drwxr-xr-x 19 root root  4096 Oct 12 14:04 ..
  -rwxr-xr-x  1 root root     0 Oct 12 14:04 file1
  -rw-r--r--  1 root root     0 Oct 12 14:04 file2
  drwx------  2 root root 16384 Oct 12 14:04 lost+found

I then mounted and tested it as non-root:

  $ guestmount -a test1.img -m /dev/sda1 /tmp/mnt -v -x
  $ ls -l /tmp/mnt
  total 16
  -rwxr-xr-x. 1 root root     0 Oct 12 15:04 file1
  -rw-r--r--. 1 root root     0 Oct 12 15:04 file2
  drwx------. 2 root root 16384 Oct 12 15:04 lost+found
  $ test -x /tmp/mnt/file1; echo $?
  0
  $ test -x /tmp/mnt/file2; echo $?
  1

and as root:

  $ sudo guestmount -a test1.img -m /dev/sda1 /tmp/mnt -v -x
  $ test -x /tmp/mnt/file1; echo $?
  0
  $ test -x /tmp/mnt/file2; echo $?
  0

In the debug output for non-root we can see the difference:

  libguestfs: /file1: testing access mask X_OK: caller UID:GID = 1000:1000, file UID:GID = 0:0, file mode = 100755, result = OK
  libguestfs: /file2: testing access mask X_OK: caller UID:GID = 1000:1000, file UID:GID = 0:0, file mode = 100644, result = EACCESS

and for root:

  libguestfs: /file1: testing access mask X_OK: caller UID:GID = 0:0, file UID:GID = 0:0, file mode = 100755, result = OK
  libguestfs: /file2: testing access mask X_OK: caller UID:GID = 0:0, file UID:GID = 0:0, file mode = 100644, result = OK

After this commit the root output changes to this (ie. same decision
as non-root):

  libguestfs: /file1: testing access mask X_OK: caller UID:GID = 0:0, file UID:GID = 0:0, file mode = 100755, result = OK
  libguestfs: /file2: testing access mask X_OK: caller UID:GID = 0:0, file UID:GID = 0:0, file mode = 100644, result = EACCESS
This commit is contained in:
Richard W.M. Jones
2020-10-12 15:05:07 +01:00
parent 4663112d89
commit 3f4a529ab7

View File

@@ -330,8 +330,9 @@ mount_local_access (const char *path, int mask)
fuse = fuse_get_context ();
/* Root user should be able to access everything, so only bother
* with these fine-grained tests for non-root. (RHBZ#1106548).
/* Root user should be able to read and write everything, so only
* bother with these fine-grained tests for non-root.
* (RHBZ#1106548).
*/
if (fuse->uid != 0) {
if (mask & R_OK)
@@ -344,12 +345,16 @@ mount_local_access (const char *path, int mask)
( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IWUSR
: fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IWGRP
: statbuf.st_mode & S_IWOTH);
if (mask & X_OK)
ok = ok &&
( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IXUSR
: fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IXGRP
: statbuf.st_mode & S_IXOTH);
}
/* We still want the -x test because otherwise root is unable to
* test if a file is executable.
* https://stackoverflow.com/questions/64273334/test-x-in-mounted-filesystem
*/
if (mask & X_OK)
ok = ok &&
( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IXUSR
: fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IXGRP
: statbuf.st_mode & S_IXOTH);
debug (g, "%s: "
"testing access mask%s%s%s%s: "