[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20191104212144.059394803@linuxfoundation.org>
Date: Mon, 4 Nov 2019 22:45:02 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, Giuseppe Scrivano <gscrivan@...hat.com>,
Miklos Szeredi <mszeredi@...hat.com>
Subject: [PATCH 4.19 109/149] fuse: flush dirty data/metadata before non-truncate setattr
From: Miklos Szeredi <mszeredi@...hat.com>
commit b24e7598db62386a95a3c8b9c75630c5d56fe077 upstream.
If writeback cache is enabled, then writes might get reordered with
chmod/chown/utimes. The problem with this is that performing the write in
the fuse daemon might itself change some of these attributes. In such case
the following sequence of operations will result in file ending up with the
wrong mode, for example:
int fd = open ("suid", O_WRONLY|O_CREAT|O_EXCL);
write (fd, "1", 1);
fchown (fd, 0, 0);
fchmod (fd, 04755);
close (fd);
This patch fixes this by flushing pending writes before performing
chown/chmod/utimes.
Reported-by: Giuseppe Scrivano <gscrivan@...hat.com>
Tested-by: Giuseppe Scrivano <gscrivan@...hat.com>
Fixes: 4d99ff8f12eb ("fuse: Turn writeback cache on")
Cc: <stable@...r.kernel.org> # v3.15+
Signed-off-by: Miklos Szeredi <mszeredi@...hat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
fs/fuse/dir.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1665,6 +1665,19 @@ int fuse_do_setattr(struct dentry *dentr
if (attr->ia_valid & ATTR_SIZE)
is_truncate = true;
+ /* Flush dirty data/metadata before non-truncate SETATTR */
+ if (is_wb && S_ISREG(inode->i_mode) &&
+ attr->ia_valid &
+ (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
+ ATTR_TIMES_SET)) {
+ err = write_inode_now(inode, true);
+ if (err)
+ return err;
+
+ fuse_set_nowrite(inode);
+ fuse_release_nowrite(inode);
+ }
+
if (is_truncate) {
fuse_set_nowrite(inode);
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Powered by blists - more mailing lists