summaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2019-05-27 09:08:12 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2019-05-27 11:42:36 +0200
commit4a2abf99f9c2877039006b8dfb3ec4e0d1278fe8 (patch)
tree01872fd7aac66a14a0aaaccb7f74289e1603eccf /fs/fuse
parent35d6fcbb7c3e296a52136347346a698a35af3fda (diff)
downloadlinux-4a2abf99f9c2877039006b8dfb3ec4e0d1278fe8.tar.gz
linux-4a2abf99f9c2877039006b8dfb3ec4e0d1278fe8.tar.bz2
linux-4a2abf99f9c2877039006b8dfb3ec4e0d1278fe8.zip
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>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/file.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 143c54f93f2d..c1064866c402 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -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);