diff mbox series

[2/6] nfsd: add cred parameter to __fh_verify()

Message ID 20240701025802.22985-3-neilb@suse.de (mailing list archive)
State New
Headers show
Series nfsd: provide simpler interface for LOCALIO access | expand

Commit Message

NeilBrown July 1, 2024, 2:53 a.m. UTC
__fh_verify() now takes a 'cred' parameter and never dereferences
rqstp->rq_cred.

nfsd_permission(), nfsd_setuser() and nfsexp_flags() only never needed
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(-)

Comments

Jeff Layton July 1, 2024, 11:02 a.m. UTC | #1
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.
kernel test robot July 1, 2024, 5:34 p.m. UTC | #2
Hi NeilBrown,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.10-rc6 next-20240701]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/NeilBrown/nfsd-introduce-__fh_verify-which-takes-explicit-nfsd_net-arg/20240701-122856
base:   linus/master
patch link:    https://lore.kernel.org/r/20240701025802.22985-3-neilb%40suse.de
patch subject: [PATCH 2/6] nfsd: add cred parameter to __fh_verify()
config: parisc-defconfig
compiler: hppa-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build):

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202407020129.uUBFQk9E-lkp@intel.com/

All warnings (new ones prefixed by >>):

   fs/nfsd/nfsfh.c:334: warning: Function parameter or struct member 'nn' not described in '__fh_verify'
>> fs/nfsd/nfsfh.c:334: warning: Function parameter or struct member 'cred' not described in '__fh_verify'
   fs/nfsd/nfsfh.c:334: warning: expecting prototype for fh_verify(). Prototype was for __fh_verify() instead


vim +334 fs/nfsd/nfsfh.c

03550fac06c4f0 J. Bruce Fields 2008-03-14  302  
b3d47676d474ec J. Bruce Fields 2008-10-20  303  /**
b3d47676d474ec J. Bruce Fields 2008-10-20  304   * fh_verify - filehandle lookup and access checking
b3d47676d474ec J. Bruce Fields 2008-10-20  305   * @rqstp: pointer to current rpc request
b3d47676d474ec J. Bruce Fields 2008-10-20  306   * @fhp: filehandle to be verified
b3d47676d474ec J. Bruce Fields 2008-10-20  307   * @type: expected type of object pointed to by filehandle
b3d47676d474ec J. Bruce Fields 2008-10-20  308   * @access: type of access needed to object
b3d47676d474ec J. Bruce Fields 2008-10-20  309   *
b3d47676d474ec J. Bruce Fields 2008-10-20  310   * Look up a dentry from the on-the-wire filehandle, check the client's
b3d47676d474ec J. Bruce Fields 2008-10-20  311   * access to the export, and set the current task's credentials.
b3d47676d474ec J. Bruce Fields 2008-10-20  312   *
b3d47676d474ec J. Bruce Fields 2008-10-20  313   * Regardless of success or failure of fh_verify(), fh_put() should be
b3d47676d474ec J. Bruce Fields 2008-10-20  314   * called on @fhp when the caller is finished with the filehandle.
b3d47676d474ec J. Bruce Fields 2008-10-20  315   *
b3d47676d474ec J. Bruce Fields 2008-10-20  316   * fh_verify() may be called multiple times on a given filehandle, for
b3d47676d474ec J. Bruce Fields 2008-10-20  317   * example, when processing an NFSv4 compound.  The first call will look
b3d47676d474ec J. Bruce Fields 2008-10-20  318   * up a dentry using the on-the-wire filehandle.  Subsequent calls will
b3d47676d474ec J. Bruce Fields 2008-10-20  319   * skip the lookup and just perform the other checks and possibly change
b3d47676d474ec J. Bruce Fields 2008-10-20  320   * the current task's credentials.
03550fac06c4f0 J. Bruce Fields 2008-03-14  321   *
b3d47676d474ec J. Bruce Fields 2008-10-20  322   * @type specifies the type of object expected using one of the S_IF*
b3d47676d474ec J. Bruce Fields 2008-10-20  323   * constants defined in include/linux/stat.h.  The caller may use zero
b3d47676d474ec J. Bruce Fields 2008-10-20  324   * to indicate that it doesn't care, or a negative integer to indicate
b3d47676d474ec J. Bruce Fields 2008-10-20  325   * that it expects something not of the given type.
03550fac06c4f0 J. Bruce Fields 2008-03-14  326   *
b3d47676d474ec J. Bruce Fields 2008-10-20  327   * @access is formed from the NFSD_MAY_* constants defined in
93f580a9a2413d Oleg Drokin     2016-07-07  328   * fs/nfsd/vfs.h.
03550fac06c4f0 J. Bruce Fields 2008-03-14  329   */
63e675e35f79ed NeilBrown       2024-07-01  330  static __be32
72924991777f5b NeilBrown       2024-07-01  331  __fh_verify(struct svc_rqst *rqstp,
72924991777f5b NeilBrown       2024-07-01  332  	    struct nfsd_net *nn, struct svc_cred *cred,
63e675e35f79ed NeilBrown       2024-07-01  333  	    struct svc_fh *fhp, umode_t type, int access)
03550fac06c4f0 J. Bruce Fields 2008-03-14 @334  {
20ad856e47323e Amir Goldstein  2021-01-06  335  	struct svc_export *exp = NULL;
03550fac06c4f0 J. Bruce Fields 2008-03-14  336  	struct dentry	*dentry;
03550fac06c4f0 J. Bruce Fields 2008-03-14  337  	__be32		error;
03550fac06c4f0 J. Bruce Fields 2008-03-14  338  
03550fac06c4f0 J. Bruce Fields 2008-03-14  339  	if (!fhp->fh_dentry) {
72924991777f5b NeilBrown       2024-07-01  340  		error = nfsd_set_fh_dentry(rqstp, nn, cred, fhp);
03550fac06c4f0 J. Bruce Fields 2008-03-14  341  		if (error)
03550fac06c4f0 J. Bruce Fields 2008-03-14  342  			goto out;
864f0f61f829ba J. Bruce Fields 2009-11-25  343  	}
^1da177e4c3f41 Linus Torvalds  2005-04-16  344  	dentry = fhp->fh_dentry;
^1da177e4c3f41 Linus Torvalds  2005-04-16  345  	exp = fhp->fh_export;
051382885552e1 Chuck Lever     2022-06-21  346  
051382885552e1 Chuck Lever     2022-06-21  347  	trace_nfsd_fh_verify(rqstp, fhp, type, access);
051382885552e1 Chuck Lever     2022-06-21  348  
6fa02839bf9412 J. Bruce Fields 2007-11-12  349  	/*
864f0f61f829ba J. Bruce Fields 2009-11-25  350  	 * We still have to do all these permission checks, even when
864f0f61f829ba J. Bruce Fields 2009-11-25  351  	 * fh_dentry is already set:
864f0f61f829ba J. Bruce Fields 2009-11-25  352  	 * 	- fh_verify may be called multiple times with different
864f0f61f829ba J. Bruce Fields 2009-11-25  353  	 * 	  "access" arguments (e.g. nfsd_proc_create calls
864f0f61f829ba J. Bruce Fields 2009-11-25  354  	 * 	  fh_verify(...,NFSD_MAY_EXEC) first, then later (in
864f0f61f829ba J. Bruce Fields 2009-11-25  355  	 * 	  nfsd_create) calls fh_verify(...,NFSD_MAY_CREATE).
864f0f61f829ba J. Bruce Fields 2009-11-25  356  	 *	- in the NFSv4 case, the filehandle may have been filled
864f0f61f829ba J. Bruce Fields 2009-11-25  357  	 *	  in by fh_compose, and given a dentry, but further
864f0f61f829ba J. Bruce Fields 2009-11-25  358  	 *	  compound operations performed with that filehandle
864f0f61f829ba J. Bruce Fields 2009-11-25  359  	 *	  still need permissions checks.  In the worst case, a
864f0f61f829ba J. Bruce Fields 2009-11-25  360  	 *	  mountpoint crossing may have changed the export
864f0f61f829ba J. Bruce Fields 2009-11-25  361  	 *	  options, and we may now need to use a different uid
864f0f61f829ba J. Bruce Fields 2009-11-25  362  	 *	  (for example, if different id-squashing options are in
864f0f61f829ba J. Bruce Fields 2009-11-25  363  	 *	  effect on the new filesystem).
6fa02839bf9412 J. Bruce Fields 2007-11-12  364  	 */
03a816b46d7eba Steve Dickson   2009-09-09  365  	error = check_pseudo_root(rqstp, dentry, exp);
03a816b46d7eba Steve Dickson   2009-09-09  366  	if (error)
03a816b46d7eba Steve Dickson   2009-09-09  367  		goto out;
03a816b46d7eba Steve Dickson   2009-09-09  368  
72924991777f5b NeilBrown       2024-07-01  369  	error = nfsd_setuser_and_check_port(rqstp, cred, exp);
7fc90ec93a5eb7 J. Bruce Fields 2006-06-30  370  	if (error)
7fc90ec93a5eb7 J. Bruce Fields 2006-06-30  371  		goto out;
7fc90ec93a5eb7 J. Bruce Fields 2006-06-30  372  
e75b23f9e323b1 J. Bruce Fields 2016-07-19  373  	error = nfsd_mode_check(rqstp, dentry, type);
^1da177e4c3f41 Linus Torvalds  2005-04-16  374  	if (error)
^1da177e4c3f41 Linus Torvalds  2005-04-16  375  		goto out;
^1da177e4c3f41 Linus Torvalds  2005-04-16  376  
9091224f3cff47 J. Bruce Fields 2007-07-17  377  	/*
9091224f3cff47 J. Bruce Fields 2007-07-17  378  	 * pseudoflavor restrictions are not enforced on NLM,
9091224f3cff47 J. Bruce Fields 2007-07-17  379  	 * which clients virtually always use auth_sys for,
9091224f3cff47 J. Bruce Fields 2007-07-17  380  	 * even while using RPCSEC_GSS for NFS.
9091224f3cff47 J. Bruce Fields 2007-07-17  381  	 */
204f4ce75434c3 J. Bruce Fields 2011-04-08  382  	if (access & NFSD_MAY_LOCK || access & NFSD_MAY_BYPASS_GSS)
04716e6621ff4a J. Bruce Fields 2008-08-07  383  		goto skip_pseudoflavor_check;
04716e6621ff4a J. Bruce Fields 2008-08-07  384  	/*
04716e6621ff4a J. Bruce Fields 2008-08-07  385  	 * Clients may expect to be able to use auth_sys during mount,
04716e6621ff4a J. Bruce Fields 2008-08-07  386  	 * even if they use gss for everything else; see section 2.3.2
04716e6621ff4a J. Bruce Fields 2008-08-07  387  	 * of rfc 2623.
04716e6621ff4a J. Bruce Fields 2008-08-07  388  	 */
04716e6621ff4a J. Bruce Fields 2008-08-07  389  	if (access & NFSD_MAY_BYPASS_GSS_ON_ROOT
04716e6621ff4a J. Bruce Fields 2008-08-07  390  			&& exp->ex_path.dentry == dentry)
04716e6621ff4a J. Bruce Fields 2008-08-07  391  		goto skip_pseudoflavor_check;
04716e6621ff4a J. Bruce Fields 2008-08-07  392  
32c1eb0cd7ee00 Andy Adamson    2007-07-17  393  	error = check_nfsd_access(exp, rqstp);
32c1eb0cd7ee00 Andy Adamson    2007-07-17  394  	if (error)
32c1eb0cd7ee00 Andy Adamson    2007-07-17  395  		goto out;
32c1eb0cd7ee00 Andy Adamson    2007-07-17  396  
04716e6621ff4a J. Bruce Fields 2008-08-07  397  skip_pseudoflavor_check:
^1da177e4c3f41 Linus Torvalds  2005-04-16  398  	/* Finally, check access permissions. */
72924991777f5b NeilBrown       2024-07-01  399  	error = nfsd_permission(cred, exp, dentry, access);
^1da177e4c3f41 Linus Torvalds  2005-04-16  400  out:
93c128e709aec2 Jeff Layton     2022-10-12  401  	trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error);
^1da177e4c3f41 Linus Torvalds  2005-04-16  402  	if (error == nfserr_stale)
4b14885411f74b Josef Bacik     2024-01-26  403  		nfsd_stats_fh_stale_inc(nn, exp);
^1da177e4c3f41 Linus Torvalds  2005-04-16  404  	return error;
^1da177e4c3f41 Linus Torvalds  2005-04-16  405  }
^1da177e4c3f41 Linus Torvalds  2005-04-16  406
diff mbox series

Patch

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);