All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vivek Goyal <vgoyal@redhat.com>
To: linux-fsdevel@vger.kernel.org, miklos@szeredi.hu
Cc: virtio-fs@redhat.com, vgoyal@redhat.com
Subject: [Virtio-fs] [PATCH v3 4/6] fuse: Don't send ATTR_MODE to kill suid/sgid for handle_killpriv_v2
Date: Fri,  9 Oct 2020 14:15:10 -0400	[thread overview]
Message-ID: <20201009181512.65496-5-vgoyal@redhat.com> (raw)
In-Reply-To: <20201009181512.65496-1-vgoyal@redhat.com>

If client does a write() on a suid/sgid file, VFS will first call
fuse_setattr() with ATTR_KILL_S[UG]ID set. This requires sending
setattr to file server with ATTR_MODE set to kill suid/sgid. But
to do that client needs to know latest mode otherwise it is racy.

To reduce the race window, current code first call fuse_do_getattr()
to get latest ->i_mode and then resets suid/sgid bits and sends rest
to server with setattr(ATTR_MODE). This does not reduce the race
completely but narrows race window significantly.

With fc->handle_killpriv_v2 enabled, it should be possible to remove
this race completely. Do not kill suid/sgid with ATTR_MODE at all. It
will be killed by server when WRITE request is sent to server soon.
This is similar to fc->handle_killpriv logic. V2 is just more refined
version of protocol. Hence this patch does not send ATTR_MODE to
kill suid/sgid if fc->handle_killpriv_v2 is enabled.

This creates an issue if fc->writeback_cache is enabled. In that
case WRITE can be cached in guest and server might not see WRITE
request and hence will not kill suid/sgid. Miklos suggested that
in such cases, we should fallback to a writethrough WRITE instead
and that will generate WRITE request and kill suid/sgid. This patch
implements that too.

But this relies on client seeing the suid/sgid set. If another client
sets suid/sgid and this client does not see it immideately, then we
will not fallback to writethrough WRITE. So this is one limitation
with both fc->handle_killpriv_v2 and fc->writeback_cache enabled.
Both the options are not fully compatible. But might be good enough
for many use cases.

Note: I am not checking whether security.capability is set or not when
      falling back to writethrough path. if suid/sgid is not set and only
      security.capability is set, that will be taken care of by
      file_remove_privs() call in ->writeback_cache path.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 fs/fuse/dir.c  | 2 +-
 fs/fuse/file.c | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index ecdb7895c156..510178594a8d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1664,7 +1664,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 		 *
 		 * This should be done on write(), truncate() and chown().
 		 */
-		if (!fc->handle_killpriv) {
+		if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
 			/*
 			 * ia_mode calculation may have used stale i_mode.
 			 * Refresh and recalculate.
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e40428f3d0f1..ee1bb9bfdcd5 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1260,17 +1260,24 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	ssize_t written_buffered = 0;
 	struct inode *inode = mapping->host;
 	ssize_t err;
+	struct fuse_conn *fc = get_fuse_conn(inode);
 	loff_t endbyte = 0;
 
-	if (get_fuse_conn(inode)->writeback_cache) {
+	if (fc->writeback_cache) {
 		/* Update size (EOF optimization) and mode (SUID clearing) */
 		err = fuse_update_attributes(mapping->host, file);
 		if (err)
 			return err;
 
+		if (fc->handle_killpriv_v2 &&
+		    should_remove_suid(file_dentry(file))) {
+			goto writethrough;
+		}
+
 		return generic_file_write_iter(iocb, from);
 	}
 
+writethrough:
 	inode_lock(inode);
 
 	/* We can write back this queue in page reclaim */
-- 
2.25.4


WARNING: multiple messages have this Message-ID (diff)
From: Vivek Goyal <vgoyal@redhat.com>
To: linux-fsdevel@vger.kernel.org, miklos@szeredi.hu
Cc: vgoyal@redhat.com, virtio-fs@redhat.com
Subject: [PATCH v3 4/6] fuse: Don't send ATTR_MODE to kill suid/sgid for handle_killpriv_v2
Date: Fri,  9 Oct 2020 14:15:10 -0400	[thread overview]
Message-ID: <20201009181512.65496-5-vgoyal@redhat.com> (raw)
In-Reply-To: <20201009181512.65496-1-vgoyal@redhat.com>

If client does a write() on a suid/sgid file, VFS will first call
fuse_setattr() with ATTR_KILL_S[UG]ID set. This requires sending
setattr to file server with ATTR_MODE set to kill suid/sgid. But
to do that client needs to know latest mode otherwise it is racy.

To reduce the race window, current code first call fuse_do_getattr()
to get latest ->i_mode and then resets suid/sgid bits and sends rest
to server with setattr(ATTR_MODE). This does not reduce the race
completely but narrows race window significantly.

With fc->handle_killpriv_v2 enabled, it should be possible to remove
this race completely. Do not kill suid/sgid with ATTR_MODE at all. It
will be killed by server when WRITE request is sent to server soon.
This is similar to fc->handle_killpriv logic. V2 is just more refined
version of protocol. Hence this patch does not send ATTR_MODE to
kill suid/sgid if fc->handle_killpriv_v2 is enabled.

This creates an issue if fc->writeback_cache is enabled. In that
case WRITE can be cached in guest and server might not see WRITE
request and hence will not kill suid/sgid. Miklos suggested that
in such cases, we should fallback to a writethrough WRITE instead
and that will generate WRITE request and kill suid/sgid. This patch
implements that too.

But this relies on client seeing the suid/sgid set. If another client
sets suid/sgid and this client does not see it immideately, then we
will not fallback to writethrough WRITE. So this is one limitation
with both fc->handle_killpriv_v2 and fc->writeback_cache enabled.
Both the options are not fully compatible. But might be good enough
for many use cases.

Note: I am not checking whether security.capability is set or not when
      falling back to writethrough path. if suid/sgid is not set and only
      security.capability is set, that will be taken care of by
      file_remove_privs() call in ->writeback_cache path.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 fs/fuse/dir.c  | 2 +-
 fs/fuse/file.c | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index ecdb7895c156..510178594a8d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1664,7 +1664,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 		 *
 		 * This should be done on write(), truncate() and chown().
 		 */
-		if (!fc->handle_killpriv) {
+		if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
 			/*
 			 * ia_mode calculation may have used stale i_mode.
 			 * Refresh and recalculate.
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e40428f3d0f1..ee1bb9bfdcd5 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1260,17 +1260,24 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	ssize_t written_buffered = 0;
 	struct inode *inode = mapping->host;
 	ssize_t err;
+	struct fuse_conn *fc = get_fuse_conn(inode);
 	loff_t endbyte = 0;
 
-	if (get_fuse_conn(inode)->writeback_cache) {
+	if (fc->writeback_cache) {
 		/* Update size (EOF optimization) and mode (SUID clearing) */
 		err = fuse_update_attributes(mapping->host, file);
 		if (err)
 			return err;
 
+		if (fc->handle_killpriv_v2 &&
+		    should_remove_suid(file_dentry(file))) {
+			goto writethrough;
+		}
+
 		return generic_file_write_iter(iocb, from);
 	}
 
+writethrough:
 	inode_lock(inode);
 
 	/* We can write back this queue in page reclaim */
-- 
2.25.4


  parent reply	other threads:[~2020-10-09 18:15 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-09 18:15 [Virtio-fs] [PATCH v3 0/6] fuse: Implement FUSE_HANDLE_KILLPRIV_V2 and enable SB_NOSEC Vivek Goyal
2020-10-09 18:15 ` Vivek Goyal
2020-10-09 18:15 ` [Virtio-fs] [PATCH v3 1/6] fuse: Introduce the notion of FUSE_HANDLE_KILLPRIV_V2 Vivek Goyal
2020-10-09 18:15   ` Vivek Goyal
2020-10-09 18:15 ` [Virtio-fs] [PATCH v3 2/6] fuse: Set FUSE_WRITE_KILL_PRIV in cached write path Vivek Goyal
2020-10-09 18:15   ` Vivek Goyal
2020-10-09 18:15 ` [Virtio-fs] [PATCH v3 3/6] fuse: setattr should set FATTR_KILL_PRIV upon size change Vivek Goyal
2020-10-09 18:15   ` Vivek Goyal
2020-11-06 14:39   ` [Virtio-fs] " Miklos Szeredi
2020-11-06 14:39     ` Miklos Szeredi
2020-11-06 17:18     ` [Virtio-fs] " Vivek Goyal
2020-11-06 17:18       ` Vivek Goyal
2020-11-11 13:54       ` [Virtio-fs] " Miklos Szeredi
2020-11-11 13:54         ` Miklos Szeredi
2020-11-11 14:27         ` [Virtio-fs] " Harry G. Coin
2020-11-11 16:24         ` Miklos Szeredi
2020-11-11 16:24           ` Miklos Szeredi
2020-11-11 22:09           ` [Virtio-fs] " Vivek Goyal
2020-11-11 22:09             ` Vivek Goyal
2020-11-11 19:16         ` [Virtio-fs] " Vivek Goyal
2020-11-11 19:16           ` Vivek Goyal
2020-10-09 18:15 ` Vivek Goyal [this message]
2020-10-09 18:15   ` [PATCH v3 4/6] fuse: Don't send ATTR_MODE to kill suid/sgid for handle_killpriv_v2 Vivek Goyal
2020-10-09 18:15 ` [Virtio-fs] [PATCH v3 5/6] fuse: Add a flag FUSE_OPEN_KILL_PRIV for open() request Vivek Goyal
2020-10-09 18:15   ` Vivek Goyal
2020-11-06 13:55   ` [Virtio-fs] " Miklos Szeredi
2020-11-06 13:55     ` Miklos Szeredi
2020-11-06 16:00     ` [Virtio-fs] " Vivek Goyal
2020-11-06 16:00       ` Vivek Goyal
2020-11-06 16:33       ` [Virtio-fs] " Miklos Szeredi
2020-11-06 16:33         ` Miklos Szeredi
2020-11-06 18:41         ` [Virtio-fs] " Vivek Goyal
2020-11-06 18:41           ` Vivek Goyal
2020-10-09 18:15 ` [Virtio-fs] [PATCH v3 6/6] fuse: Support SB_NOSEC flag to improve direct write performance Vivek Goyal
2020-10-09 18:15   ` Vivek Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201009181512.65496-5-vgoyal@redhat.com \
    --to=vgoyal@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=virtio-fs@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.