The final places where __fh_verify unconditionally dereferences rqstp involve checked is the connection is suitably secure. They look at rqstp->rq_xprt which is not meaningful in the target use case of "localio" NFS in which the client talk directly to the local server. So check these to always succeed when rqstp is NULL. With this it is safe tocall __fh_verify with a NULL rqstp providing nn, cred, and client are not NULL. Signed-off-by: NeilBrown <neilb@xxxxxxx> --- fs/nfsd/export.c | 12 +++++++++--- fs/nfsd/nfsfh.c | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index ccfe8c528bcb..9e3e2380f8ae 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1077,7 +1077,13 @@ static struct svc_export *exp_find(struct cache_detail *cd, __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) { struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; - struct svc_xprt *xprt = rqstp->rq_xprt; + struct svc_xprt *xprt; + + if (!rqstp) + /* Always allow LOCALIO */ + return 0; + + xprt = rqstp->rq_xprt; if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) { if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags)) @@ -1185,7 +1191,7 @@ rqst_exp_find(struct svc_rqst *rqstp, struct nfsd_net *nn, /* First try the auth_unix client: */ exp = exp_find(cd, client, fsid_type, - fsidv, &rqstp->rq_chandle); + fsidv, rqstp ? &rqstp->rq_chandle : NULL); if (PTR_ERR(exp) == -ENOENT) goto gss; if (IS_ERR(exp)) @@ -1198,7 +1204,7 @@ rqst_exp_find(struct svc_rqst *rqstp, struct nfsd_net *nn, if (!try_gss || rqstp->rq_gssclient == NULL) return exp; gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv, - &rqstp->rq_chandle); + rqstp ? &rqstp->rq_chandle : NULL); if (PTR_ERR(gssexp) == -ENOENT) return exp; if (!IS_ERR(exp)) diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index ea3d98c43a9d..fb5a23060a4c 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -106,10 +106,10 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, int flags = nfsexp_flags(cred, exp); /* Check if the request originated from a secure port. */ - if (!nfsd_originating_port_ok(rqstp, flags)) { + if (rqstp && !nfsd_originating_port_ok(rqstp, flags)) { RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); dprintk("nfsd: request from insecure port %s!\n", - svc_print_addr(rqstp, buf, sizeof(buf))); + svc_print_addr(rqstp, buf, sizeof(buf))); return nfserr_perm; } -- 2.44.0