Re: [PATCH v2] NFSv4.2: Update mode bits after ALLOCATE and DEALLOCATE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 1, 2022 at 2:47 PM Trond Myklebust <trondmy@xxxxxxxxxxxxxxx> wrote:
>
> On Thu, 2022-09-01 at 14:22 -0400, Trond Myklebust wrote:
> > On Thu, 2022-09-01 at 14:05 -0400, Anna Schumaker wrote:
> > > From: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx>
> > >
> > > The fallocate call invalidates suid and sgid bits as part of normal
> > > operation. We need to mark the mode bits as invalid when using
> > > fallocate
> > > with an suid so these will be updated the next time the user looks
> > > at
> > > them.
> > >
> > > This fixes xfstests generic/683 and generic/684.
> > >
> > > Reported-by: Yue Cui <cuiyue-fnst@xxxxxxxxxxx>
> > > Fixes: 913eca1aea87 ("NFS: Fallocate should use the
> > > nfs4_fattr_bitmap")
> > > Signed-off-by: Anna Schumaker <Anna.Schumaker@xxxxxxxxxx>
> > > ---
> > >  fs/nfs/internal.h  | 25 +++++++++++++++++++++++++
> > >  fs/nfs/nfs42proc.c | 13 ++++++++++++-
> > >  fs/nfs/write.c     | 25 -------------------------
> > >  3 files changed, 37 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> > > index 27c720d71b4e..898dd95bc7a7 100644
> > > --- a/fs/nfs/internal.h
> > > +++ b/fs/nfs/internal.h
> > > @@ -606,6 +606,31 @@ static inline gfp_t nfs_io_gfp_mask(void)
> > >         return GFP_KERNEL;
> > >  }
> > >
> > > +/*
> > > + * Special version of should_remove_suid() that ignores
> > > capabilities.
> > > + */
> > > +static inline int nfs_should_remove_suid(const struct inode
> > > *inode)
> > > +{
> > > +       umode_t mode = inode->i_mode;
> > > +       int kill = 0;
> > > +
> > > +       /* suid always must be killed */
> > > +       if (unlikely(mode & S_ISUID))
> > > +               kill = ATTR_KILL_SUID;
> > > +
> > > +       /*
> > > +        * sgid without any exec bits is just a mandatory locking
> > > mark; leave
> > > +        * it alone.  If some exec bits are set, it's a real sgid;
> > > kill it.
> > > +        */
> > > +       if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
> > > +               kill |= ATTR_KILL_SGID;
> > > +
> > > +       if (unlikely(kill && S_ISREG(mode)))
> > > +               return kill;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > >  /* unlink.c */
> > >  extern struct rpc_task *
> > >  nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
> > > diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
> > > index 068c45b3bc1a..23023ddf75d1 100644
> > > --- a/fs/nfs/nfs42proc.c
> > > +++ b/fs/nfs/nfs42proc.c
> > > @@ -56,6 +56,7 @@ static int _nfs42_proc_fallocate(struct
> > > rpc_message
> > > *msg, struct file *filep,
> > >         struct nfs42_falloc_res res = {
> > >                 .falloc_server  = server,
> > >         };
> > > +       unsigned int invalid = 0;
> > >         int status;
> > >
> > >         msg->rpc_argp = &args;
> > > @@ -78,10 +79,20 @@ static int _nfs42_proc_fallocate(struct
> > > rpc_message *msg, struct file *filep,
> > >
> > >         status = nfs4_call_sync(server->client, server, msg,
> > >                                 &args.seq_args, &res.seq_res, 0);
> > > +
> > > +       if (!res.falloc_fattr->valid)
> > > +               invalid |= NFS_INO_INVALID_ATTR;
>
> Oh wait... We shouldn't need this.^^^^^^^^^
> nfs_post_op_update_inode_force_wcc() will do the right thing for you
> here.

Sure. I can remove that and put everything under the "if (status == 0)".

Anna

>
> > > +       if (nfs_should_remove_suid(inode))
> > > +               invalid |= NFS_INO_INVALID_MODE;
> > > +       if (invalid) {
> > > +               spin_lock(&inode->i_lock);
> > > +               nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
> > > +               spin_unlock(&inode->i_lock);
> > > +       }
> >
> > This all really wants to go into the 'if (status == 0)' below.
> > > +
> > >         if (status == 0)
> > >                 status = nfs_post_op_update_inode_force_wcc(inode,
> > >
> > > res.falloc_fattr);
> > > -
> > >         if (msg->rpc_proc ==
> > > &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE])
> > >                 trace_nfs4_fallocate(inode, &args, status);
> > >         else
> > > diff --git a/fs/nfs/write.c b/fs/nfs/write.c
> > > index 1843fa235d9b..f41d24b54fd1 100644
> > > --- a/fs/nfs/write.c
> > > +++ b/fs/nfs/write.c
> > > @@ -1496,31 +1496,6 @@ void nfs_commit_prepare(struct rpc_task
> > > *task,
> > > void *calldata)
> > >         NFS_PROTO(data->inode)->commit_rpc_prepare(task, data);
> > >  }
> > >
> > > -/*
> > > - * Special version of should_remove_suid() that ignores
> > > capabilities.
> > > - */
> > > -static int nfs_should_remove_suid(const struct inode *inode)
> > > -{
> > > -       umode_t mode = inode->i_mode;
> > > -       int kill = 0;
> > > -
> > > -       /* suid always must be killed */
> > > -       if (unlikely(mode & S_ISUID))
> > > -               kill = ATTR_KILL_SUID;
> > > -
> > > -       /*
> > > -        * sgid without any exec bits is just a mandatory locking
> > > mark; leave
> > > -        * it alone.  If some exec bits are set, it's a real sgid;
> > > kill it.
> > > -        */
> > > -       if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
> > > -               kill |= ATTR_KILL_SGID;
> > > -
> > > -       if (unlikely(kill && S_ISREG(mode)))
> > > -               return kill;
> > > -
> > > -       return 0;
> > > -}
> > > -
> > >  static void nfs_writeback_check_extend(struct nfs_pgio_header
> > > *hdr,
> > >                 struct nfs_fattr *fattr)
> > >  {
> >
> > Otherwise, looks OK.
> >
>
> --
> Trond Myklebust
> Linux NFS client maintainer, Hammerspace
> trond.myklebust@xxxxxxxxxxxxxxx
>
>



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux