nfsd: permit unauthenticated stat of export root
RFC 2623 section 2.3.2 permits the server to bypass gss authentication checks for certain operations that a client may perform when mounting. In the case of a client that doesn't have some form of credentials available to it on boot, this allows it to perform the mount unattended. (Presumably real file access won't be needed until a user with credentials logs in.) Being slightly more lenient allows lots of old clients to access krb5-only exports, with the only loss being a small amount of information leaked about the root directory of the export. This affects only v2 and v3; v4 still requires authentication for all access. Thanks to Peter Staubach testing against a Solaris client, which suggesting addition of v3 getattr, to the list, and to Trond for noting that doing so exposes no additional information. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Cc: Peter Staubach <staubach@redhat.com> Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
This commit is contained in:
@ -63,7 +63,8 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
|
|||||||
SVCFH_fmt(&argp->fh));
|
SVCFH_fmt(&argp->fh));
|
||||||
|
|
||||||
fh_copy(&resp->fh, &argp->fh);
|
fh_copy(&resp->fh, &argp->fh);
|
||||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
nfserr = fh_verify(rqstp, &resp->fh, 0,
|
||||||
|
NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
|
||||||
if (nfserr)
|
if (nfserr)
|
||||||
RETURN_STATUS(nfserr);
|
RETURN_STATUS(nfserr);
|
||||||
|
|
||||||
@ -530,7 +531,7 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
|
|||||||
dprintk("nfsd: FSSTAT(3) %s\n",
|
dprintk("nfsd: FSSTAT(3) %s\n",
|
||||||
SVCFH_fmt(&argp->fh));
|
SVCFH_fmt(&argp->fh));
|
||||||
|
|
||||||
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
|
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
|
||||||
fh_put(&argp->fh);
|
fh_put(&argp->fh);
|
||||||
RETURN_STATUS(nfserr);
|
RETURN_STATUS(nfserr);
|
||||||
}
|
}
|
||||||
@ -558,7 +559,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
|
|||||||
resp->f_maxfilesize = ~(u32) 0;
|
resp->f_maxfilesize = ~(u32) 0;
|
||||||
resp->f_properties = NFS3_FSF_DEFAULT;
|
resp->f_properties = NFS3_FSF_DEFAULT;
|
||||||
|
|
||||||
nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
|
nfserr = fh_verify(rqstp, &argp->fh, 0,
|
||||||
|
NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
|
||||||
|
|
||||||
/* Check special features of the file system. May request
|
/* Check special features of the file system. May request
|
||||||
* different read/write sizes for file systems known to have
|
* different read/write sizes for file systems known to have
|
||||||
|
@ -302,17 +302,27 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!(access & NFSD_MAY_LOCK)) {
|
/*
|
||||||
/*
|
* pseudoflavor restrictions are not enforced on NLM,
|
||||||
* pseudoflavor restrictions are not enforced on NLM,
|
* which clients virtually always use auth_sys for,
|
||||||
* which clients virtually always use auth_sys for,
|
* even while using RPCSEC_GSS for NFS.
|
||||||
* even while using RPCSEC_GSS for NFS.
|
*/
|
||||||
*/
|
if (access & NFSD_MAY_LOCK)
|
||||||
error = check_nfsd_access(exp, rqstp);
|
goto skip_pseudoflavor_check;
|
||||||
if (error)
|
/*
|
||||||
goto out;
|
* Clients may expect to be able to use auth_sys during mount,
|
||||||
}
|
* even if they use gss for everything else; see section 2.3.2
|
||||||
|
* of rfc 2623.
|
||||||
|
*/
|
||||||
|
if (access & NFSD_MAY_BYPASS_GSS_ON_ROOT
|
||||||
|
&& exp->ex_path.dentry == dentry)
|
||||||
|
goto skip_pseudoflavor_check;
|
||||||
|
|
||||||
|
error = check_nfsd_access(exp, rqstp);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
skip_pseudoflavor_check:
|
||||||
/* Finally, check access permissions. */
|
/* Finally, check access permissions. */
|
||||||
error = nfsd_permission(rqstp, exp, dentry, access);
|
error = nfsd_permission(rqstp, exp, dentry, access);
|
||||||
|
|
||||||
|
@ -65,7 +65,8 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
|
|||||||
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
|
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
|
||||||
|
|
||||||
fh_copy(&resp->fh, &argp->fh);
|
fh_copy(&resp->fh, &argp->fh);
|
||||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
nfserr = fh_verify(rqstp, &resp->fh, 0,
|
||||||
|
NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
|
||||||
return nfsd_return_attrs(nfserr, resp);
|
return nfsd_return_attrs(nfserr, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +522,8 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
|
|||||||
|
|
||||||
dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
|
dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
|
||||||
|
|
||||||
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
|
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
|
||||||
|
NFSD_MAY_BYPASS_GSS_ON_ROOT);
|
||||||
fh_put(&argp->fh);
|
fh_put(&argp->fh);
|
||||||
return nfserr;
|
return nfserr;
|
||||||
}
|
}
|
||||||
|
@ -1866,9 +1866,9 @@ out:
|
|||||||
* N.B. After this call fhp needs an fh_put
|
* N.B. After this call fhp needs an fh_put
|
||||||
*/
|
*/
|
||||||
__be32
|
__be32
|
||||||
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
|
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
|
||||||
{
|
{
|
||||||
__be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
|
__be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
|
||||||
if (!err && vfs_statfs(fhp->fh_dentry,stat))
|
if (!err && vfs_statfs(fhp->fh_dentry,stat))
|
||||||
err = nfserr_io;
|
err = nfserr_io;
|
||||||
return err;
|
return err;
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define NFSD_MAY_LOCK 32
|
#define NFSD_MAY_LOCK 32
|
||||||
#define NFSD_MAY_OWNER_OVERRIDE 64
|
#define NFSD_MAY_OWNER_OVERRIDE 64
|
||||||
#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
|
#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
|
||||||
|
#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
|
||||||
|
|
||||||
#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
|
#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
|
||||||
#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
|
#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
|
||||||
@ -125,7 +126,7 @@ int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
|
|||||||
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
|
||||||
loff_t *, struct readdir_cd *, filldir_t);
|
loff_t *, struct readdir_cd *, filldir_t);
|
||||||
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
|
||||||
struct kstatfs *);
|
struct kstatfs *, int access);
|
||||||
|
|
||||||
int nfsd_notify_change(struct inode *, struct iattr *);
|
int nfsd_notify_change(struct inode *, struct iattr *);
|
||||||
__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
|
__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
|
||||||
|
Reference in New Issue
Block a user