diff mbox series

[2/2] fuse: Enable SB_NOSEC if filesystem is not shared

Message ID 20200901204045.1250822-3-vgoyal@redhat.com (mailing list archive)
State New, archived
Headers show
Series fuse: Enable SB_NOSEC if filesystem is not shared | expand

Commit Message

Vivek Goyal Sept. 1, 2020, 8:40 p.m. UTC
We don't enable SB_NOSEC on fuse filesystems thinking filesystem is
shared and files attrs setuid/setgid/capabilities can change without
fuse knowing about it. This means on every WRITE, file_remove_privs(),
is called and that calls into fuse server to figure out if security.capability
xattr has been set on file. Most of the time this is a performance hog,
specially for small writes done at high frequency.

Enable SB_NOSEC if fuse filesystem sets flag FS_NONSHARED_FS. This means,
do not expect file attrs/xattrs to change without the knowledge of
fuse. In this case it should be possible to enable SB_NOSEC.

For the case of shared filesystems, we will have to come up with a different
mechanism to enable SB_NOSEC. I guess it will depend on invalidation
mechanisms implemented by filesystem and cache coherency guarantees.

I do clear inode S_NOSEC flag whenever file attrs are being refreshed. So
this still honors attr timeout protocol.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 fs/fuse/inode.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 088faa3e352c..2da13fe25417 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -187,6 +187,9 @@  void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
 		inode->i_mode &= ~S_ISVTX;
 
 	fi->orig_ino = attr->ino;
+
+	/* Clear S_NOSEC whenever cached attrs are being refreshed */
+	inode->i_flags &= ~S_NOSEC;
 }
 
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
@@ -967,6 +970,9 @@  static void process_init_reply(struct fuse_conn *fc, struct fuse_args *args,
 			}
 			if (arg->flags & FUSE_NONSHARED_FS) {
 				fc->nonshared_fs = 1;
+				down_write(&fc->sb->s_umount);
+				fc->sb->s_flags |= SB_NOSEC;
+				up_write(&fc->sb->s_umount);
 			}
 		} else {
 			ra_pages = fc->max_read / PAGE_SIZE;