mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
nfsd: move check_nfsd_access() call into nfsd_cross_mnt()
Whenever we cross a mount point, we need to check_nfsd_access() for v4. So move the call into nfsd_cross_mnt() in the place where we actually do cross. This avoids the possibility of calling nfsd_cross_mnt() without the required check_nfsd_access(). Also remove the last arg from check_nfsd_access(), which is always false. nfsd_cross_mnt() now returns an nfserr rather than an errno. Signed-off-by: NeilBrown <neil@brown.name> Reviewed-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260717093001.1972119-3-neilb@ownmail.net Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
parent
ddfabbc784
commit
f0d6ad5a2f
|
|
@ -1890,21 +1890,19 @@ __be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp,
|
|||
* check_nfsd_access - check if access to export is allowed.
|
||||
* @exp: svc_export that is being accessed.
|
||||
* @rqstp: svc_rqst attempting to access @exp.
|
||||
* @may_bypass_gss: reduce strictness of authorization check
|
||||
*
|
||||
* Return values:
|
||||
* %nfs_ok if access is granted, or
|
||||
* %nfserr_wrongsec if access is denied
|
||||
*/
|
||||
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
|
||||
bool may_bypass_gss)
|
||||
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
|
||||
{
|
||||
__be32 status;
|
||||
|
||||
status = check_xprtsec_policy(exp, rqstp);
|
||||
if (status != nfs_ok)
|
||||
return status;
|
||||
return check_security_flavor(exp, rqstp, may_bypass_gss);
|
||||
return check_security_flavor(exp, rqstp, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -104,8 +104,7 @@ int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp);
|
|||
__be32 check_xprtsec_policy(struct svc_export *exp, struct svc_rqst *rqstp);
|
||||
__be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp,
|
||||
bool may_bypass_gss);
|
||||
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
|
||||
bool may_bypass_gss);
|
||||
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
|
|
|
|||
|
|
@ -3328,7 +3328,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
|||
|
||||
if (current_fh->fh_export &&
|
||||
need_wrongsec_check(rqstp))
|
||||
op->status = check_nfsd_access(current_fh->fh_export, rqstp, false);
|
||||
op->status = check_nfsd_access(current_fh->fh_export, rqstp);
|
||||
}
|
||||
encode_op:
|
||||
if (op->status == nfserr_replay_me) {
|
||||
|
|
|
|||
|
|
@ -4574,8 +4574,6 @@ nfsd4_encode_entry4_fattr(struct nfsd4_readdir *cd, const char *name,
|
|||
* directly from the mountpoint dentry.
|
||||
*/
|
||||
if (nfsd_mountpoint(dentry, exp)) {
|
||||
int err;
|
||||
|
||||
if (!(exp->ex_flags & NFSEXP_V4ROOT)
|
||||
&& !attributes_need_mount(cd->rd_bmval)) {
|
||||
ignore_crossmnt = 1;
|
||||
|
|
@ -4586,12 +4584,7 @@ nfsd4_encode_entry4_fattr(struct nfsd4_readdir *cd, const char *name,
|
|||
* Different "."/".." handling? Something else?
|
||||
* At least, add a comment here to explain....
|
||||
*/
|
||||
err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
|
||||
if (err) {
|
||||
nfserr = nfserrno(err);
|
||||
goto out_put;
|
||||
}
|
||||
nfserr = check_nfsd_access(exp, cd->rd_rqstp, false);
|
||||
nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
|
||||
if (nfserr)
|
||||
goto out_put;
|
||||
crossed = true;
|
||||
|
|
|
|||
|
|
@ -118,15 +118,15 @@ nfserrno (int errno)
|
|||
return nfserr_io;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
|
||||
/*
|
||||
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
|
||||
* a mount point.
|
||||
* Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
|
||||
* Returns an nfs error leaving *dpp and *expp unchanged,
|
||||
* or nfs_ok having possibly changed *dpp and *expp
|
||||
*/
|
||||
int
|
||||
nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
||||
struct svc_export **expp)
|
||||
__be32
|
||||
nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
||||
struct svc_export **expp)
|
||||
{
|
||||
struct svc_export *exp = *expp, *exp2 = NULL;
|
||||
struct dentry *dentry = *dpp;
|
||||
|
|
@ -134,6 +134,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
|||
.dentry = dget(dentry)};
|
||||
unsigned int follow_flags = 0;
|
||||
int err = 0;
|
||||
__be32 nfserr = nfs_ok;
|
||||
|
||||
if (exp->ex_flags & NFSEXP_CROSSMOUNT)
|
||||
follow_flags = LOOKUP_AUTOMOUNT;
|
||||
|
|
@ -163,23 +164,28 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
|||
err = 0;
|
||||
} else if (nfsd_v4client(rqstp) ||
|
||||
(exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
|
||||
/* successfully crossed mount point */
|
||||
/*
|
||||
* This is subtle: path.dentry is *not* on path.mnt
|
||||
* at this point. The only reason we are safe is that
|
||||
* original mnt is pinned down by exp, so we should
|
||||
* put path *before* putting exp
|
||||
*/
|
||||
*dpp = path.dentry;
|
||||
path.dentry = dentry;
|
||||
*expp = exp2;
|
||||
exp2 = exp;
|
||||
nfserr = check_nfsd_access(exp, rqstp);
|
||||
if (nfserr == nfs_ok) {
|
||||
/* successfully crossed mount point */
|
||||
/*
|
||||
* This is subtle: path.dentry is *not* on path.mnt
|
||||
* at this point. The only reason we are safe is that
|
||||
* original mnt is pinned down by exp, so we should
|
||||
* put path *before* putting exp
|
||||
*/
|
||||
*dpp = path.dentry;
|
||||
path.dentry = dentry;
|
||||
*expp = exp2;
|
||||
exp2 = exp;
|
||||
}
|
||||
}
|
||||
out:
|
||||
path_put(&path);
|
||||
if (exp2)
|
||||
exp_put(exp2);
|
||||
return err;
|
||||
if (nfserr)
|
||||
return nfserr;
|
||||
return nfserrno(err);
|
||||
}
|
||||
|
||||
static void follow_to_parent(struct path *path)
|
||||
|
|
@ -277,10 +283,12 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|||
if (IS_ERR(dentry))
|
||||
goto out_nfserr;
|
||||
if (nfsd_mountpoint(dentry, exp)) {
|
||||
host_err = nfsd_cross_mnt(rqstp, &dentry, &exp);
|
||||
if (host_err) {
|
||||
__be32 nfserr = nfsd_cross_mnt(rqstp, &dentry, &exp);
|
||||
|
||||
if (nfserr) {
|
||||
dput(dentry);
|
||||
goto out_nfserr;
|
||||
exp_put(exp);
|
||||
return nfserr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -327,9 +335,6 @@ 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, false);
|
||||
if (err)
|
||||
goto out;
|
||||
/*
|
||||
* Note: we compose the file handle now, but as the
|
||||
* dentry may be negative, it may need to be updated.
|
||||
|
|
@ -337,7 +342,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
|
|||
err = fh_compose(resfh, exp, dentry, fhp);
|
||||
if (!err && d_really_is_negative(dentry))
|
||||
err = nfserr_noent;
|
||||
out:
|
||||
|
||||
dput(dentry);
|
||||
exp_put(exp);
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ static inline bool nfsd_attrs_valid(struct nfsd_attrs *attrs)
|
|||
}
|
||||
|
||||
__be32 nfserrno (int errno);
|
||||
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
||||
struct svc_export **expp);
|
||||
__be32 nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
||||
struct svc_export **expp);
|
||||
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
|
||||
const char *, unsigned int, struct svc_fh *);
|
||||
__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user