diff mbox series

[v3,5/6] fuse: Add a flag FUSE_OPEN_KILL_PRIV for open() request

Message ID 20201009181512.65496-6-vgoyal@redhat.com (mailing list archive)
State New, archived
Headers show
Series fuse: Implement FUSE_HANDLE_KILLPRIV_V2 and enable SB_NOSEC | expand

Commit Message

Vivek Goyal Oct. 9, 2020, 6:15 p.m. UTC
With FUSE_HANDLE_KILLPRIV_V2 support, server will need to kill
suid/sgid/security.capability on open(O_TRUNC), if server supports
FUSE_ATOMIC_O_TRUNC.

But server needs to kill suid/sgid only if caller does not have
CAP_FSETID. Given server does not have this information, client
needs to send this info to server.

So add a flag FUSE_OPEN_KILL_PRIV to fuse_open_in request which tells
server to kill suid/sgid(only if group execute is set).

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 fs/fuse/file.c            |  5 +++++
 include/uapi/linux/fuse.h | 10 +++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

Comments

Miklos Szeredi Nov. 6, 2020, 1:55 p.m. UTC | #1
On Fri, Oct 9, 2020 at 8:16 PM Vivek Goyal <vgoyal@redhat.com> wrote:
>
> With FUSE_HANDLE_KILLPRIV_V2 support, server will need to kill
> suid/sgid/security.capability on open(O_TRUNC), if server supports
> FUSE_ATOMIC_O_TRUNC.
>
> But server needs to kill suid/sgid only if caller does not have
> CAP_FSETID. Given server does not have this information, client
> needs to send this info to server.
>
> So add a flag FUSE_OPEN_KILL_PRIV to fuse_open_in request which tells
> server to kill suid/sgid(only if group execute is set).

This is needed for FUSE_CREATE as well (which may act as a normal open
in case the file exists, and no O_EXCL was specified), right?

I can edit the patch, if you agree.

Thanks,
Miklos
Vivek Goyal Nov. 6, 2020, 4 p.m. UTC | #2
On Fri, Nov 06, 2020 at 02:55:11PM +0100, Miklos Szeredi wrote:
> On Fri, Oct 9, 2020 at 8:16 PM Vivek Goyal <vgoyal@redhat.com> wrote:
> >
> > With FUSE_HANDLE_KILLPRIV_V2 support, server will need to kill
> > suid/sgid/security.capability on open(O_TRUNC), if server supports
> > FUSE_ATOMIC_O_TRUNC.
> >
> > But server needs to kill suid/sgid only if caller does not have
> > CAP_FSETID. Given server does not have this information, client
> > needs to send this info to server.
> >
> > So add a flag FUSE_OPEN_KILL_PRIV to fuse_open_in request which tells
> > server to kill suid/sgid(only if group execute is set).
> 
> This is needed for FUSE_CREATE as well (which may act as a normal open
> in case the file exists, and no O_EXCL was specified), right?

Hi Miklos,

IIUC, In current code we seem to use FUSE_CREATE only if file does not exist.
If file exists, then we probably will take FUSE_OPEN path.

Are you concerned about future proofing where somebody decides to use
FUSE_CREATE for create + open on a file which exists. If yes, I agree that
patching FUSE_CREATE makes sense.

> 
> I can edit the patch, if you agree.

Please do.

Thanks
Vivek
Miklos Szeredi Nov. 6, 2020, 4:33 p.m. UTC | #3
On Fri, Nov 6, 2020 at 5:00 PM Vivek Goyal <vgoyal@redhat.com> wrote:
>
> On Fri, Nov 06, 2020 at 02:55:11PM +0100, Miklos Szeredi wrote:
> > On Fri, Oct 9, 2020 at 8:16 PM Vivek Goyal <vgoyal@redhat.com> wrote:
> > >
> > > With FUSE_HANDLE_KILLPRIV_V2 support, server will need to kill
> > > suid/sgid/security.capability on open(O_TRUNC), if server supports
> > > FUSE_ATOMIC_O_TRUNC.
> > >
> > > But server needs to kill suid/sgid only if caller does not have
> > > CAP_FSETID. Given server does not have this information, client
> > > needs to send this info to server.
> > >
> > > So add a flag FUSE_OPEN_KILL_PRIV to fuse_open_in request which tells
> > > server to kill suid/sgid(only if group execute is set).
> >
> > This is needed for FUSE_CREATE as well (which may act as a normal open
> > in case the file exists, and no O_EXCL was specified), right?
>
> Hi Miklos,
>
> IIUC, In current code we seem to use FUSE_CREATE only if file does not exist.
> If file exists, then we probably will take FUSE_OPEN path.

That's true if the cache is up to date, one important point for
FUSE_CREATE is that it works atomically even if the cache is stale.
So if cache is negative and we send a FUSE_CREATE it may still open an
*existing* file, and we want to do suid/caps clearing in that case
also, no?

Thanks,
Miklos
Vivek Goyal Nov. 6, 2020, 6:41 p.m. UTC | #4
On Fri, Nov 06, 2020 at 05:33:00PM +0100, Miklos Szeredi wrote:
> On Fri, Nov 6, 2020 at 5:00 PM Vivek Goyal <vgoyal@redhat.com> wrote:
> >
> > On Fri, Nov 06, 2020 at 02:55:11PM +0100, Miklos Szeredi wrote:
> > > On Fri, Oct 9, 2020 at 8:16 PM Vivek Goyal <vgoyal@redhat.com> wrote:
> > > >
> > > > With FUSE_HANDLE_KILLPRIV_V2 support, server will need to kill
> > > > suid/sgid/security.capability on open(O_TRUNC), if server supports
> > > > FUSE_ATOMIC_O_TRUNC.
> > > >
> > > > But server needs to kill suid/sgid only if caller does not have
> > > > CAP_FSETID. Given server does not have this information, client
> > > > needs to send this info to server.
> > > >
> > > > So add a flag FUSE_OPEN_KILL_PRIV to fuse_open_in request which tells
> > > > server to kill suid/sgid(only if group execute is set).
> > >
> > > This is needed for FUSE_CREATE as well (which may act as a normal open
> > > in case the file exists, and no O_EXCL was specified), right?
> >
> > Hi Miklos,
> >
> > IIUC, In current code we seem to use FUSE_CREATE only if file does not exist.
> > If file exists, then we probably will take FUSE_OPEN path.
> 
> That's true if the cache is up to date, one important point for
> FUSE_CREATE is that it works atomically even if the cache is stale.
> So if cache is negative and we send a FUSE_CREATE it may still open an
> *existing* file, and we want to do suid/caps clearing in that case
> also, no?

Yes, makes sense. This can happen in a race condition also where
fuse_lookup_name() gets a negative dentry and then another client
creates file (with setuid/setgid/caps) set. Now fuse_create_open()
is called without O_EXCL and in that case we should remove
setuid/setgid/caps as needed. 

So yes, please make modifications accordingly for FUSE_CREATE. If you
want me to do make those changes, please let me know.

Thanks
Vivek
diff mbox series

Patch

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ee1bb9bfdcd5..5400c6d77701 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -42,6 +42,11 @@  static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
 	if (!fc->atomic_o_trunc)
 		inarg.flags &= ~O_TRUNC;
+
+	if (fc->handle_killpriv_v2 && (inarg.flags & O_TRUNC) &&
+	    !capable(CAP_FSETID))
+		inarg.open_flags |= FUSE_OPEN_KILL_PRIV;
+
 	args.opcode = opcode;
 	args.nodeid = nodeid;
 	args.in_numargs = 1;
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 7b8da0a2de0d..e20b3ee9d292 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -173,6 +173,7 @@ 
  *  - add FUSE_SETUPMAPPING and FUSE_REMOVEMAPPING
  *  - add map_alignment to fuse_init_out, add FUSE_MAP_ALIGNMENT flag
  *  - add FUSE_HANDLE_KILLPRIV_V2
+ *  - add FUSE_OPEN_KILL_PRIV
  */
 
 #ifndef _LINUX_FUSE_H
@@ -427,6 +428,13 @@  struct fuse_file_lock {
  */
 #define FUSE_FSYNC_FDATASYNC	(1 << 0)
 
+/**
+ * Open flags
+ * FUSE_OPEN_KILL_PRIV: Kill suid/sgid/security.capability. sgid is cleared
+ * 			only if file has group execute permission.
+ */
+#define FUSE_OPEN_KILL_PRIV	(1 << 0)
+
 enum fuse_opcode {
 	FUSE_LOOKUP		= 1,
 	FUSE_FORGET		= 2,  /* no reply */
@@ -588,7 +596,7 @@  struct fuse_setattr_in {
 
 struct fuse_open_in {
 	uint32_t	flags;
-	uint32_t	unused;
+	uint32_t	open_flags;
 };
 
 struct fuse_create_in {