[PATCH 11/16] nfsd4: return nfserr_wrongsec

Trond Myklebust trond.myklebust at fys.uio.no
Fri May 18 18:23:05 EDT 2007


On Fri, 2007-05-18 at 17:28 -0400, J. Bruce Fields wrote:
> From: andros at citi.umich.edu <andros at citi.umich.edu>
> 
> Make the first actual use of the secinfo information by using it to
> return nfserr_wrongsec when an export is found that doesn't allow the
> flavor used on this request.
> 
> Signed-off-by: J. Bruce Fields <bfields at citi.umich.edu>
> Signed-off-by: Andy Adamson <andros at citi.umich.edu>
> ---
>  fs/nfsd/export.c            |   26 ++++++++++++++++++++++++++
>  fs/nfsd/nfsfh.c             |    6 ++++++
>  fs/nfsd/nfssvc.c            |   10 ++++++++++
>  fs/nfsd/vfs.c               |    4 ++++
>  include/linux/nfsd/export.h |    1 +
>  include/linux/nfsd/nfsd.h   |    1 +
>  6 files changed, 48 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
> index a52c4b4..25e7919 100644
> --- a/fs/nfsd/export.c
> +++ b/fs/nfsd/export.c
> @@ -1244,6 +1244,28 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
>  	return exp;
>  }
>  
> +__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
> +{
> +	struct exp_flavor_info *f;
> +	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
> +
> +	/* legacy gss-only clients are always OK: */
> +	if (exp->ex_client == rqstp->rq_gssclient)
> +		return 0;
> +	/* ip-address based client; check sec= export option: */
> +	for (f = exp->ex_flavors; f < end; f++) {
> +		if (f->pseudoflavor == rqstp->rq_flavor)
> +			return 0;
> +	}
> +	/* defaults in absence of sec= options: */
> +	if (exp->ex_nflavors == 0) {
> +		if (rqstp->rq_flavor == RPC_AUTH_NULL ||
> +		    rqstp->rq_flavor == RPC_AUTH_UNIX)
> +			return 0;
> +	}
> +	return nfserr_wrongsec;
> +}

Hmm... What about NFSv2/v3 clients? They won't grok nfserr_wrongsec...

> +
>  /*
>   * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
>   * auth_unix client) if it's available and has secinfo information;
> @@ -1356,6 +1378,10 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
>  	if (exp == NULL)
>  		return nfserr_perm;
>  	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
> +	if (rv)
> +		goto out;
> +	rv = check_nfsd_access(exp, rqstp);
> +out:
>  	exp_put(exp);
>  	return rv;
>  }
> diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
> index 6a40bc8..d8ca1e5 100644
> --- a/fs/nfsd/nfsfh.c
> +++ b/fs/nfsd/nfsfh.c
> @@ -19,6 +19,7 @@
>  
>  #include <linux/sunrpc/clnt.h>
>  #include <linux/sunrpc/svc.h>
> +#include <linux/sunrpc/svcauth_gss.h>
>  #include <linux/nfsd/nfsd.h>
>  
>  #define NFSDDBG_FACILITY		NFSDDBG_FH
> @@ -253,6 +254,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
>  	if (error)
>  		goto out;
>  
> +	/* Check security flavor */
> +	error = check_nfsd_access(exp, rqstp);
> +	if (error)
> +		goto out;
> +
>  	/* Finally, check access permissions. */
>  	error = nfsd_permission(exp, dentry, access);
>  
> diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
> index d7759ce..2f91514 100644
> --- a/fs/nfsd/nfssvc.c
> +++ b/fs/nfsd/nfssvc.c
> @@ -492,6 +492,15 @@ out:
>  	module_put_and_exit(0);
>  }
>  
> +static __be32 map_new_errors(u32 vers, __be32 nfserr)
> +{
> +	if (nfserr == nfserr_jukebox && vers == 2)
> +		return nfserr_dropit;
> +	if (nfserr == nfserr_wrongsec && vers < 4)
> +		return nfserr_perm;
> +	return nfserr;
> +}
> +
>  int
>  nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
>  {
> @@ -534,6 +543,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
>  
>  	/* Now call the procedure handler, and encode NFS status. */
>  	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
> +	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
>  	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
>  		nfserr = nfserr_dropit;
>  	if (nfserr == nfserr_dropit) {
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 7d5122b..1e7e920 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -241,6 +241,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
>  	err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
>  	if (err)
>  		return err;
> +	err = check_nfsd_access(exp, rqstp);
> +	if (err)
> +		goto out;
>  	/*
>  	 * Note: we compose the file handle now, but as the
>  	 * dentry may be negative, it may need to be updated.
> @@ -248,6 +251,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
>  	err = fh_compose(resfh, exp, dentry, fhp);
>  	if (!err && !dentry->d_inode)
>  		err = nfserr_noent;
> +out:
>  	dput(dentry);
>  	exp_put(exp);
>  	return err;
> diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
> index 09dd66b..2a5454f 100644
> --- a/include/linux/nfsd/export.h
> +++ b/include/linux/nfsd/export.h
> @@ -114,6 +114,7 @@ struct svc_expkey {
>  #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
>  #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
>  
> +__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
>  
>  /*
>   * Function declarations
> diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
> index 72feac5..9ed5870 100644
> --- a/include/linux/nfsd/nfsd.h
> +++ b/include/linux/nfsd/nfsd.h
> @@ -236,6 +236,7 @@ void		nfsd_lockd_shutdown(void);
>  #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
>  #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
>  #define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
> +#define	nfserr_wrongsec		__constant_htonl(NFSERR_WRONGSEC)
>  #define	nfserr_replay_me	__constant_htonl(NFSERR_REPLAY_ME)
>  
>  /* error codes for internal use */



More information about the NFSv4 mailing list