mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
nfsd: factor out __fh_verify to allow NULL rqstp to be passed
__fh_verify() offers an interface like fh_verify() but doesn't require a struct svc_rqst *, instead it also takes the specific parts as explicit required arguments. So it is safe to call __fh_verify() with a NULL rqstp, but the net, cred, and client args must not be NULL. __fh_verify() does not use SVC_NET(), nor does the functions it calls. Rather than using rqstp->rq_client pass the client and gssclient explicitly to __fh_verify and then to nfsd_set_fh_dentry(). Lastly, it should be noted that the previous commit prepared for 4 associated tracepoints to only be used if rqstp is not NULL (this is a stop-gap that should be properly fixed so localio also benefits from the utility these tracepoints provide when debugging fh_verify issues). Signed-off-by: NeilBrown <neilb@suse.de> Co-developed-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
This commit is contained in:
parent
71c61a0077
commit
5e66d2d92a
@ -142,7 +142,11 @@ static inline __be32 check_pseudo_root(struct dentry *dentry,
|
||||
* dentry. On success, the results are used to set fh_export and
|
||||
* fh_dentry.
|
||||
*/
|
||||
static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
|
||||
struct svc_cred *cred,
|
||||
struct auth_domain *client,
|
||||
struct auth_domain *gssclient,
|
||||
struct svc_fh *fhp)
|
||||
{
|
||||
struct knfsd_fh *fh = &fhp->fh_handle;
|
||||
struct fid *fid = NULL;
|
||||
@ -184,8 +188,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
data_left -= len;
|
||||
if (data_left < 0)
|
||||
return error;
|
||||
exp = rqst_exp_find(&rqstp->rq_chandle, SVC_NET(rqstp),
|
||||
rqstp->rq_client, rqstp->rq_gssclient,
|
||||
exp = rqst_exp_find(rqstp ? &rqstp->rq_chandle : NULL,
|
||||
net, client, gssclient,
|
||||
fh->fh_fsid_type, fh->fh_fsid);
|
||||
fid = (struct fid *)(fh->fh_fsid + len);
|
||||
|
||||
@ -220,7 +224,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
put_cred(override_creds(new));
|
||||
put_cred(new);
|
||||
} else {
|
||||
error = nfsd_setuser_and_check_port(rqstp, &rqstp->rq_cred, exp);
|
||||
error = nfsd_setuser_and_check_port(rqstp, cred, exp);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
@ -295,42 +299,33 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* fh_verify - filehandle lookup and access checking
|
||||
* @rqstp: pointer to current rpc request
|
||||
* __fh_verify - filehandle lookup and access checking
|
||||
* @rqstp: RPC transaction context, or NULL
|
||||
* @net: net namespace in which to perform the export lookup
|
||||
* @cred: RPC user credential
|
||||
* @client: RPC auth domain
|
||||
* @gssclient: RPC GSS auth domain, or NULL
|
||||
* @fhp: filehandle to be verified
|
||||
* @type: expected type of object pointed to by filehandle
|
||||
* @access: type of access needed to object
|
||||
*
|
||||
* Look up a dentry from the on-the-wire filehandle, check the client's
|
||||
* access to the export, and set the current task's credentials.
|
||||
*
|
||||
* Regardless of success or failure of fh_verify(), fh_put() should be
|
||||
* called on @fhp when the caller is finished with the filehandle.
|
||||
*
|
||||
* fh_verify() may be called multiple times on a given filehandle, for
|
||||
* example, when processing an NFSv4 compound. The first call will look
|
||||
* up a dentry using the on-the-wire filehandle. Subsequent calls will
|
||||
* skip the lookup and just perform the other checks and possibly change
|
||||
* the current task's credentials.
|
||||
*
|
||||
* @type specifies the type of object expected using one of the S_IF*
|
||||
* constants defined in include/linux/stat.h. The caller may use zero
|
||||
* to indicate that it doesn't care, or a negative integer to indicate
|
||||
* that it expects something not of the given type.
|
||||
*
|
||||
* @access is formed from the NFSD_MAY_* constants defined in
|
||||
* fs/nfsd/vfs.h.
|
||||
* See fh_verify() for further descriptions of @fhp, @type, and @access.
|
||||
*/
|
||||
__be32
|
||||
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
|
||||
static __be32
|
||||
__fh_verify(struct svc_rqst *rqstp,
|
||||
struct net *net, struct svc_cred *cred,
|
||||
struct auth_domain *client,
|
||||
struct auth_domain *gssclient,
|
||||
struct svc_fh *fhp, umode_t type, int access)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
struct svc_export *exp = NULL;
|
||||
struct dentry *dentry;
|
||||
__be32 error;
|
||||
|
||||
if (!fhp->fh_dentry) {
|
||||
error = nfsd_set_fh_dentry(rqstp, fhp);
|
||||
error = nfsd_set_fh_dentry(rqstp, net, cred, client,
|
||||
gssclient, fhp);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
@ -359,7 +354,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = nfsd_setuser_and_check_port(rqstp, &rqstp->rq_cred, exp);
|
||||
error = nfsd_setuser_and_check_port(rqstp, cred, exp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
@ -389,7 +384,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
|
||||
|
||||
skip_pseudoflavor_check:
|
||||
/* Finally, check access permissions. */
|
||||
error = nfsd_permission(&rqstp->rq_cred, 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)
|
||||
@ -397,6 +392,40 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* fh_verify - filehandle lookup and access checking
|
||||
* @rqstp: pointer to current rpc request
|
||||
* @fhp: filehandle to be verified
|
||||
* @type: expected type of object pointed to by filehandle
|
||||
* @access: type of access needed to object
|
||||
*
|
||||
* Look up a dentry from the on-the-wire filehandle, check the client's
|
||||
* access to the export, and set the current task's credentials.
|
||||
*
|
||||
* Regardless of success or failure of fh_verify(), fh_put() should be
|
||||
* called on @fhp when the caller is finished with the filehandle.
|
||||
*
|
||||
* fh_verify() may be called multiple times on a given filehandle, for
|
||||
* example, when processing an NFSv4 compound. The first call will look
|
||||
* up a dentry using the on-the-wire filehandle. Subsequent calls will
|
||||
* skip the lookup and just perform the other checks and possibly change
|
||||
* the current task's credentials.
|
||||
*
|
||||
* @type specifies the type of object expected using one of the S_IF*
|
||||
* constants defined in include/linux/stat.h. The caller may use zero
|
||||
* to indicate that it doesn't care, or a negative integer to indicate
|
||||
* that it expects something not of the given type.
|
||||
*
|
||||
* @access is formed from the NFSD_MAY_* constants defined in
|
||||
* fs/nfsd/vfs.h.
|
||||
*/
|
||||
__be32
|
||||
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
|
||||
{
|
||||
return __fh_verify(rqstp, SVC_NET(rqstp), &rqstp->rq_cred,
|
||||
rqstp->rq_client, rqstp->rq_gssclient,
|
||||
fhp, type, access);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compose a file handle for an NFS reply.
|
||||
|
Loading…
Reference in New Issue
Block a user