Skip to content

Commit b24e759

Browse files
author
Miklos Szeredi
committed
fuse: flush dirty data/metadata before non-truncate setattr
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 <[email protected]> Tested-by: Giuseppe Scrivano <[email protected]> Fixes: 4d99ff8 ("fuse: Turn writeback cache on") Cc: <[email protected]> # v3.15+ Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 80da5a8 commit b24e759

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

fs/fuse/dir.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
15221522
is_truncate = true;
15231523
}
15241524

1525+
/* Flush dirty data/metadata before non-truncate SETATTR */
1526+
if (is_wb && S_ISREG(inode->i_mode) &&
1527+
attr->ia_valid &
1528+
(ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1529+
ATTR_TIMES_SET)) {
1530+
err = write_inode_now(inode, true);
1531+
if (err)
1532+
return err;
1533+
1534+
fuse_set_nowrite(inode);
1535+
fuse_release_nowrite(inode);
1536+
}
1537+
15251538
if (is_truncate) {
15261539
fuse_set_nowrite(inode);
15271540
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);

0 commit comments

Comments
 (0)