[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