This is a note to let you know that I've just added the patch titled NFSD: Update the NFSv2 GETATTR argument decoder to use struct xdr_stream to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 1e265741e8e5554e2fd1e4a42aa49e827a518da2 Author: Chuck Lever <chuck.lever@xxxxxxxxxx> Date: Wed Oct 21 12:14:23 2020 -0400 NFSD: Update the NFSv2 GETATTR argument decoder to use struct xdr_stream [ Upstream commit ebcd8e8b28535b643a4c06685bd363b3b73a96af ] Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index dbd8d3604653..5c187d3bcb57 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -626,7 +626,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { }, [NFSPROC_GETATTR] = { .pc_func = nfsd_proc_getattr, - .pc_decode = nfssvc_decode_fhandle, + .pc_decode = nfssvc_decode_fhandleargs, .pc_encode = nfssvc_encode_attrstat, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_fhandle), @@ -776,7 +776,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { }, [NFSPROC_STATFS] = { .pc_func = nfsd_proc_statfs, - .pc_decode = nfssvc_decode_fhandle, + .pc_decode = nfssvc_decode_fhandleargs, .pc_encode = nfssvc_encode_statfsres, .pc_argsize = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_statfsres), diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 13df5464a087..45d980d624f4 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -23,8 +23,9 @@ static u32 nfs_ftypes[] = { /* - * XDR functions for basic NFS types + * Basic NFSv2 data types (RFC 1094 Section 2.3) */ + static __be32 * decode_fh(__be32 *p, struct svc_fh *fhp) { @@ -37,6 +38,21 @@ decode_fh(__be32 *p, struct svc_fh *fhp) return p + (NFS_FHSIZE >> 2); } +static bool +svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp) +{ + __be32 *p; + + p = xdr_inline_decode(xdr, NFS_FHSIZE); + if (!p) + return false; + fh_init(fhp, NFS_FHSIZE); + memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); + fhp->fh_handle.fh_size = NFS_FHSIZE; + + return true; +} + /* Helper function for NFSv2 ACL code */ __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp) { @@ -194,14 +210,12 @@ __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *f */ int -nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) +nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p) { + struct xdr_stream *xdr = &rqstp->rq_arg_stream; struct nfsd_fhandle *args = rqstp->rq_argp; - p = decode_fh(p, &args->fh); - if (!p) - return 0; - return xdr_argsize_check(rqstp, p); + return svcxdr_decode_fhandle(xdr, &args->fh); } int diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h index edd87688ff86..50466ac6200c 100644 --- a/fs/nfsd/xdr.h +++ b/fs/nfsd/xdr.h @@ -144,7 +144,7 @@ union nfsd_xdrstore { #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) -int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *); +int nfssvc_decode_fhandleargs(struct svc_rqst *, __be32 *); int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *); int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *); int nfssvc_decode_readargs(struct svc_rqst *, __be32 *);