fuse: add FUSE_WRITE_KILL_PRIV

In the FOPEN_DIRECT_IO case the write path doesn't call file_remove_privs()
and that means setuid bit is not cleared if unpriviliged user writes to a
file with setuid bit set.

pjdfstest chmod test 12.t tests this and fails.

Fix this by adding a flag to the FUSE_WRITE message that requests clearing
privileges on the given file.  This needs 

This better than just calling fuse_remove_privs(), because the attributes
may not be up to date, so in that case a write may miss clearing the
privileges.

Test case:

  $ passthrough_ll /mnt/pasthrough-mnt -o default_permissions,allow_other,cache=never
  $ mkdir /mnt/pasthrough-mnt/testdir
  $ cd /mnt/pasthrough-mnt/testdir
  $ prove -rv pjdfstests/tests/chmod/12.t

Reported-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Tested-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
Miklos Szeredi
2019-05-27 09:08:12 +02:00
parent 35d6fcbb7c
commit 4a2abf99f9
2 changed files with 15 additions and 3 deletions

View File

@@ -1377,10 +1377,17 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
if (err && !nbytes)
break;
if (write)
if (write) {
if (!capable(CAP_FSETID)) {
struct fuse_write_in *inarg;
inarg = &req->misc.write.in;
inarg->write_flags |= FUSE_WRITE_KILL_PRIV;
}
nres = fuse_send_write(req, io, pos, nbytes, owner);
else
} else {
nres = fuse_send_read(req, io, pos, nbytes, owner);
}
if (!io->async)
fuse_release_user_pages(req, io->should_dirty);