Skip to content

Commit 5e66d2d

Browse files
neilbrownAnna Schumaker
authored andcommitted
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 <[email protected]> Co-developed-by: Mike Snitzer <[email protected]> Signed-off-by: Mike Snitzer <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 71c61a0 commit 5e66d2d

File tree

1 file changed

+60
-31
lines changed

1 file changed

+60
-31
lines changed

fs/nfsd/nfsfh.c

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ static inline __be32 check_pseudo_root(struct dentry *dentry,
142142
* dentry. On success, the results are used to set fh_export and
143143
* fh_dentry.
144144
*/
145-
static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
145+
static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
146+
struct svc_cred *cred,
147+
struct auth_domain *client,
148+
struct auth_domain *gssclient,
149+
struct svc_fh *fhp)
146150
{
147151
struct knfsd_fh *fh = &fhp->fh_handle;
148152
struct fid *fid = NULL;
@@ -184,8 +188,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
184188
data_left -= len;
185189
if (data_left < 0)
186190
return error;
187-
exp = rqst_exp_find(&rqstp->rq_chandle, SVC_NET(rqstp),
188-
rqstp->rq_client, rqstp->rq_gssclient,
191+
exp = rqst_exp_find(rqstp ? &rqstp->rq_chandle : NULL,
192+
net, client, gssclient,
189193
fh->fh_fsid_type, fh->fh_fsid);
190194
fid = (struct fid *)(fh->fh_fsid + len);
191195

@@ -220,7 +224,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
220224
put_cred(override_creds(new));
221225
put_cred(new);
222226
} else {
223-
error = nfsd_setuser_and_check_port(rqstp, &rqstp->rq_cred, exp);
227+
error = nfsd_setuser_and_check_port(rqstp, cred, exp);
224228
if (error)
225229
goto out;
226230
}
@@ -295,42 +299,33 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
295299
}
296300

297301
/**
298-
* fh_verify - filehandle lookup and access checking
299-
* @rqstp: pointer to current rpc request
302+
* __fh_verify - filehandle lookup and access checking
303+
* @rqstp: RPC transaction context, or NULL
304+
* @net: net namespace in which to perform the export lookup
305+
* @cred: RPC user credential
306+
* @client: RPC auth domain
307+
* @gssclient: RPC GSS auth domain, or NULL
300308
* @fhp: filehandle to be verified
301309
* @type: expected type of object pointed to by filehandle
302310
* @access: type of access needed to object
303311
*
304-
* Look up a dentry from the on-the-wire filehandle, check the client's
305-
* access to the export, and set the current task's credentials.
306-
*
307-
* Regardless of success or failure of fh_verify(), fh_put() should be
308-
* called on @fhp when the caller is finished with the filehandle.
309-
*
310-
* fh_verify() may be called multiple times on a given filehandle, for
311-
* example, when processing an NFSv4 compound. The first call will look
312-
* up a dentry using the on-the-wire filehandle. Subsequent calls will
313-
* skip the lookup and just perform the other checks and possibly change
314-
* the current task's credentials.
315-
*
316-
* @type specifies the type of object expected using one of the S_IF*
317-
* constants defined in include/linux/stat.h. The caller may use zero
318-
* to indicate that it doesn't care, or a negative integer to indicate
319-
* that it expects something not of the given type.
320-
*
321-
* @access is formed from the NFSD_MAY_* constants defined in
322-
* fs/nfsd/vfs.h.
312+
* See fh_verify() for further descriptions of @fhp, @type, and @access.
323313
*/
324-
__be32
325-
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
314+
static __be32
315+
__fh_verify(struct svc_rqst *rqstp,
316+
struct net *net, struct svc_cred *cred,
317+
struct auth_domain *client,
318+
struct auth_domain *gssclient,
319+
struct svc_fh *fhp, umode_t type, int access)
326320
{
327-
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
321+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
328322
struct svc_export *exp = NULL;
329323
struct dentry *dentry;
330324
__be32 error;
331325

332326
if (!fhp->fh_dentry) {
333-
error = nfsd_set_fh_dentry(rqstp, fhp);
327+
error = nfsd_set_fh_dentry(rqstp, net, cred, client,
328+
gssclient, fhp);
334329
if (error)
335330
goto out;
336331
}
@@ -359,7 +354,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
359354
if (error)
360355
goto out;
361356

362-
error = nfsd_setuser_and_check_port(rqstp, &rqstp->rq_cred, exp);
357+
error = nfsd_setuser_and_check_port(rqstp, cred, exp);
363358
if (error)
364359
goto out;
365360

@@ -389,14 +384,48 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
389384

390385
skip_pseudoflavor_check:
391386
/* Finally, check access permissions. */
392-
error = nfsd_permission(&rqstp->rq_cred, exp, dentry, access);
387+
error = nfsd_permission(cred, exp, dentry, access);
393388
out:
394389
trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error);
395390
if (error == nfserr_stale)
396391
nfsd_stats_fh_stale_inc(nn, exp);
397392
return error;
398393
}
399394

395+
/**
396+
* fh_verify - filehandle lookup and access checking
397+
* @rqstp: pointer to current rpc request
398+
* @fhp: filehandle to be verified
399+
* @type: expected type of object pointed to by filehandle
400+
* @access: type of access needed to object
401+
*
402+
* Look up a dentry from the on-the-wire filehandle, check the client's
403+
* access to the export, and set the current task's credentials.
404+
*
405+
* Regardless of success or failure of fh_verify(), fh_put() should be
406+
* called on @fhp when the caller is finished with the filehandle.
407+
*
408+
* fh_verify() may be called multiple times on a given filehandle, for
409+
* example, when processing an NFSv4 compound. The first call will look
410+
* up a dentry using the on-the-wire filehandle. Subsequent calls will
411+
* skip the lookup and just perform the other checks and possibly change
412+
* the current task's credentials.
413+
*
414+
* @type specifies the type of object expected using one of the S_IF*
415+
* constants defined in include/linux/stat.h. The caller may use zero
416+
* to indicate that it doesn't care, or a negative integer to indicate
417+
* that it expects something not of the given type.
418+
*
419+
* @access is formed from the NFSD_MAY_* constants defined in
420+
* fs/nfsd/vfs.h.
421+
*/
422+
__be32
423+
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
424+
{
425+
return __fh_verify(rqstp, SVC_NET(rqstp), &rqstp->rq_cred,
426+
rqstp->rq_client, rqstp->rq_gssclient,
427+
fhp, type, access);
428+
}
400429

401430
/*
402431
* Compose a file handle for an NFS reply.

0 commit comments

Comments
 (0)