From: Jeff Layton <jlayton@kernel.org>
To: NeilBrown <neilb@suse.de>, Chuck Lever <chuck.lever@oracle.com>
Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia <kolga@netapp.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
Mike Snitzer <snitzer@kernel.org>
Subject: Re: [PATCH 2/6] nfsd: add cred parameter to __fh_verify()
Date: Mon, 01 Jul 2024 07:02:35 -0400 [thread overview]
Message-ID: <eba7b47914674cd50b452e65be8188e42bdac95d.camel@kernel.org> (raw)
In-Reply-To: <20240701025802.22985-3-neilb@suse.de>
On Mon, 2024-07-01 at 12:53 +1000, NeilBrown wrote:
> __fh_verify() now takes a 'cred' parameter and never dereferences
> rqstp->rq_cred.
>
> nfsd_permission(), nfsd_setuser() and nfsexp_flags() only never needed
"only ever"
> the cred out of rqstp, so we now pass in the cred explicitly and not the
> rqstp.
>
> nfsd_originating_port_ok() is NOT passed a cred despite that it uses
> one. This function is not useful when rqstp is NULL and a future patch
> will address that.
>
> Signed-off-by: NeilBrown <neilb@suse.de>
> ---
> fs/nfsd/auth.c | 14 +++++++-------
> fs/nfsd/auth.h | 2 +-
> fs/nfsd/export.h | 3 ++-
> fs/nfsd/nfs4state.c | 3 ++-
> fs/nfsd/nfsfh.c | 18 +++++++++++-------
> fs/nfsd/nfsproc.c | 9 +++++----
> fs/nfsd/vfs.c | 21 ++++++++++++---------
> fs/nfsd/vfs.h | 2 +-
> 8 files changed, 41 insertions(+), 31 deletions(-)
>
> diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
> index e6beaaf4f170..93e33d1ee891 100644
> --- a/fs/nfsd/auth.c
> +++ b/fs/nfsd/auth.c
> @@ -5,26 +5,26 @@
> #include "nfsd.h"
> #include "auth.h"
>
> -int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
> +int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp)
> {
> struct exp_flavor_info *f;
> struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
>
> for (f = exp->ex_flavors; f < end; f++) {
> - if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
> + if (f->pseudoflavor == cred->cr_flavor)
> return f->flags;
> }
> return exp->ex_flags;
>
> }
>
> -int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
> +int nfsd_setuser(struct svc_cred *cred, struct svc_export *exp)
> {
> struct group_info *rqgi;
> struct group_info *gi;
> struct cred *new;
> int i;
> - int flags = nfsexp_flags(rqstp, exp);
> + int flags = nfsexp_flags(cred, exp);
>
> /* discard any old override before preparing the new set */
> revert_creds(get_cred(current_real_cred()));
> @@ -32,10 +32,10 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
> if (!new)
> return -ENOMEM;
>
> - new->fsuid = rqstp->rq_cred.cr_uid;
> - new->fsgid = rqstp->rq_cred.cr_gid;
> + new->fsuid = cred->cr_uid;
> + new->fsgid = cred->cr_gid;
>
> - rqgi = rqstp->rq_cred.cr_group_info;
> + rqgi = cred->cr_group_info;
>
> if (flags & NFSEXP_ALLSQUASH) {
> new->fsuid = exp->ex_anon_uid;
> diff --git a/fs/nfsd/auth.h b/fs/nfsd/auth.h
> index dbd66424f600..fc75c5d90be4 100644
> --- a/fs/nfsd/auth.h
> +++ b/fs/nfsd/auth.h
> @@ -12,6 +12,6 @@
> * Set the current process's fsuid/fsgid etc to those of the NFS
> * client user
> */
> -int nfsd_setuser(struct svc_rqst *, struct svc_export *);
> +int nfsd_setuser(struct svc_cred *, struct svc_export *);
>
> #endif /* LINUX_NFSD_AUTH_H */
> diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
> index 1a54d388d58d..2dbd15704a86 100644
> --- a/fs/nfsd/export.h
> +++ b/fs/nfsd/export.h
> @@ -99,7 +99,8 @@ struct svc_expkey {
> #define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
> #define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
>
> -int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp);
> +struct svc_cred;
> +int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp);
> __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
>
> /*
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index a20c2c9d7d45..eadb7d1a7f13 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -6889,7 +6889,8 @@ nfs4_check_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfs4_stid *s,
>
> nf = nfs4_find_file(s, flags);
> if (nf) {
> - status = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
> + status = nfsd_permission(&rqstp->rq_cred,
> + fhp->fh_export, fhp->fh_dentry,
> acc | NFSD_MAY_OWNER_OVERRIDE);
> if (status) {
> nfsd_file_put(nf);
> diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
> index e27ed27054ab..760684fa4b50 100644
> --- a/fs/nfsd/nfsfh.c
> +++ b/fs/nfsd/nfsfh.c
> @@ -100,9 +100,10 @@ static bool nfsd_originating_port_ok(struct svc_rqst *rqstp, int flags)
> }
>
> static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
> + struct svc_cred *cred,
> struct svc_export *exp)
> {
> - int flags = nfsexp_flags(rqstp, exp);
> + int flags = nfsexp_flags(cred, exp);
>
> /* Check if the request originated from a secure port. */
> if (!nfsd_originating_port_ok(rqstp, flags)) {
> @@ -113,7 +114,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
> }
>
> /* Set user creds for this exportpoint */
> - return nfserrno(nfsd_setuser(rqstp, exp));
> + return nfserrno(nfsd_setuser(cred, exp));
> }
>
> static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
> @@ -152,6 +153,7 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
> * fh_dentry.
> */
> static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct nfsd_net *nn,
> + struct svc_cred *cred,
> struct svc_fh *fhp)
> {
> struct knfsd_fh *fh = &fhp->fh_handle;
> @@ -230,7 +232,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct nfsd_net *nn,
> put_cred(override_creds(new));
> put_cred(new);
> } else {
> - error = nfsd_setuser_and_check_port(rqstp, exp);
> + error = nfsd_setuser_and_check_port(rqstp, cred, exp);
> if (error)
> goto out;
> }
> @@ -326,7 +328,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct nfsd_net *nn,
> * fs/nfsd/vfs.h.
> */
> static __be32
> -__fh_verify(struct svc_rqst *rqstp, struct nfsd_net *nn,
> +__fh_verify(struct svc_rqst *rqstp,
> + struct nfsd_net *nn, struct svc_cred *cred,
> struct svc_fh *fhp, umode_t type, int access)
> {
> struct svc_export *exp = NULL;
> @@ -334,7 +337,7 @@ __fh_verify(struct svc_rqst *rqstp, struct nfsd_net *nn,
> __be32 error;
>
> if (!fhp->fh_dentry) {
> - error = nfsd_set_fh_dentry(rqstp, nn, fhp);
> + error = nfsd_set_fh_dentry(rqstp, nn, cred, fhp);
> if (error)
> goto out;
> }
> @@ -363,7 +366,7 @@ __fh_verify(struct svc_rqst *rqstp, struct nfsd_net *nn,
> if (error)
> goto out;
>
> - error = nfsd_setuser_and_check_port(rqstp, exp);
> + error = nfsd_setuser_and_check_port(rqstp, cred, exp);
> if (error)
> goto out;
>
> @@ -393,7 +396,7 @@ __fh_verify(struct svc_rqst *rqstp, struct nfsd_net *nn,
>
> skip_pseudoflavor_check:
> /* Finally, check access permissions. */
> - error = nfsd_permission(rqstp, exp, dentry, access);
> + error = nfsd_permission(cred, exp, dentry, access);
> out:
> trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error);
> if (error == nfserr_stale)
> @@ -405,6 +408,7 @@ __be32
> fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
> {
> return __fh_verify(rqstp, net_generic(SVC_NET(rqstp), nfsd_net_id),
> + &rqstp->rq_cred,
> fhp, type, access);
> }
>
> diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
> index 36370b957b63..97aab34593ef 100644
> --- a/fs/nfsd/nfsproc.c
> +++ b/fs/nfsd/nfsproc.c
> @@ -331,10 +331,11 @@ nfsd_proc_create(struct svc_rqst *rqstp)
> * echo thing > device-special-file-or-pipe
> * by doing a CREATE with type==0
> */
> - resp->status = nfsd_permission(rqstp,
> - newfhp->fh_export,
> - newfhp->fh_dentry,
> - NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
> + resp->status = nfsd_permission(
> + &rqstp->rq_cred,
> + newfhp->fh_export,
> + newfhp->fh_dentry,
> + NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
> if (resp->status && resp->status != nfserr_rofs)
> goto out_unlock;
> }
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 29b1f3613800..0862f6ae86a9 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -421,8 +421,9 @@ nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,
> if (iap->ia_size < inode->i_size) {
> __be32 err;
>
> - err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
> - NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE);
> + err = nfsd_permission(&rqstp->rq_cred,
> + fhp->fh_export, fhp->fh_dentry,
> + NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE);
> if (err)
> return err;
> }
> @@ -814,7 +815,8 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
>
> sresult |= map->access;
>
> - err2 = nfsd_permission(rqstp, export, dentry, map->how);
> + err2 = nfsd_permission(&rqstp->rq_cred, export,
> + dentry, map->how);
> switch (err2) {
> case nfs_ok:
> result |= map->access;
> @@ -1475,7 +1477,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
> dirp = d_inode(dentry);
>
> dchild = dget(resfhp->fh_dentry);
> - err = nfsd_permission(rqstp, fhp->fh_export, dentry, NFSD_MAY_CREATE);
> + err = nfsd_permission(&rqstp->rq_cred, fhp->fh_export, dentry,
> + NFSD_MAY_CREATE);
> if (err)
> goto out;
>
> @@ -2255,9 +2258,9 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, in
> return err;
> }
>
> -static int exp_rdonly(struct svc_rqst *rqstp, struct svc_export *exp)
> +static int exp_rdonly(struct svc_cred *cred, struct svc_export *exp)
> {
> - return nfsexp_flags(rqstp, exp) & NFSEXP_READONLY;
> + return nfsexp_flags(cred, exp) & NFSEXP_READONLY;
> }
>
> #ifdef CONFIG_NFSD_V4
> @@ -2501,8 +2504,8 @@ nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, char *name,
> * Check for a user's access permissions to this inode.
> */
> __be32
> -nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
> - struct dentry *dentry, int acc)
> +nfsd_permission(struct svc_cred *cred, struct svc_export *exp,
> + struct dentry *dentry, int acc)
> {
> struct inode *inode = d_inode(dentry);
> int err;
> @@ -2533,7 +2536,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
> */
> if (!(acc & NFSD_MAY_LOCAL_ACCESS))
> if (acc & (NFSD_MAY_WRITE | NFSD_MAY_SATTR | NFSD_MAY_TRUNC)) {
> - if (exp_rdonly(rqstp, exp) ||
> + if (exp_rdonly(cred, exp) ||
> __mnt_is_readonly(exp->ex_path.mnt))
> return nfserr_rofs;
> if (/* (acc & NFSD_MAY_WRITE) && */ IS_IMMUTABLE(inode))
> diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
> index 57cd70062048..1565c1dc28b6 100644
> --- a/fs/nfsd/vfs.h
> +++ b/fs/nfsd/vfs.h
> @@ -153,7 +153,7 @@ __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
> __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
> struct kstatfs *, int access);
>
> -__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
> +__be32 nfsd_permission(struct svc_cred *, struct svc_export *,
> struct dentry *, int);
>
> void nfsd_filp_close(struct file *fp);
Patch itself looks fine though.
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2024-07-01 11:02 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-01 2:53 [PATCH 0/6 RFC] nfsd: provide simpler interface for LOCALIO access NeilBrown
2024-07-01 2:53 ` [PATCH 1/6] nfsd: introduce __fh_verify which takes explicit nfsd_net arg NeilBrown
2024-07-01 14:54 ` Chuck Lever
2024-07-01 15:46 ` kernel test robot
2024-07-01 2:53 ` [PATCH 2/6] nfsd: add cred parameter to __fh_verify() NeilBrown
2024-07-01 11:02 ` Jeff Layton [this message]
2024-07-01 17:34 ` kernel test robot
2024-07-01 2:53 ` [PATCH 3/6] nfsd: pass nfs_vers explicitly " NeilBrown
2024-07-01 14:57 ` Chuck Lever
2024-07-01 19:16 ` kernel test robot
2024-07-01 2:53 ` [PATCH 4/6] nfsd: pass client " NeilBrown
2024-07-01 11:12 ` Jeff Layton
2024-07-01 2:53 ` [PATCH 5/6] nfsd: __fh_verify now treats NULL rqstp as a trusted connection NeilBrown
2024-07-01 2:53 ` [PATCH 6/6] nfsd: add nfsd_file_acquire_local() NeilBrown
2024-07-01 11:21 ` Jeff Layton
2024-07-01 23:55 ` NeilBrown
2024-07-02 0:29 ` Jeff Layton
2024-07-04 8:58 ` kernel test robot
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=eba7b47914674cd50b452e65be8188e42bdac95d.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=chuck.lever@oracle.com \
--cc=kolga@netapp.com \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=snitzer@kernel.org \
--cc=tom@talpey.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox