Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/nfs4xdr.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 6bb6ffa676b7..69ff666a5695 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -262,17 +262,22 @@ static __be32 nfsd4_decode_component4(struct nfsd4_compoundargs *argp, } static __be32 -nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec64 *tv) +nfsd4_decode_nfstime4(struct nfsd4_compoundargs *argp, struct timespec64 *tv) { - DECODE_HEAD; + __be32 *p; - READ_BUF(12); + p = xdr_inline_decode(argp->xdr, sizeof(__be64) + sizeof(__be32)); + if (!p) + goto xdr_error; p = xdr_decode_hyper(p, &tv->tv_sec); tv->tv_nsec = be32_to_cpup(p++); if (tv->tv_nsec >= (u32)1000000000) - return nfserr_inval; - - DECODE_TAIL; + goto inval_arg; + return nfs_ok; +xdr_error: + return nfserr_bad_xdr; +inval_arg: + return nfserr_inval; } static __be32 @@ -413,7 +418,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, switch (dummy32) { case NFS4_SET_TO_CLIENT_TIME: len += 12; - status = nfsd4_decode_time(argp, &iattr->ia_atime); + status = nfsd4_decode_nfstime4(argp, &iattr->ia_atime); if (status) return status; iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); @@ -432,7 +437,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, switch (dummy32) { case NFS4_SET_TO_CLIENT_TIME: len += 12; - status = nfsd4_decode_time(argp, &iattr->ia_mtime); + status = nfsd4_decode_nfstime4(argp, &iattr->ia_mtime); if (status) return status; iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); @@ -1417,7 +1422,7 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, goto xdr_error; /* nii_date */ - status = nfsd4_decode_time(argp, &exid->nii_time); + status = nfsd4_decode_nfstime4(argp, &exid->nii_time); if (status) goto xdr_error; } @@ -1649,7 +1654,7 @@ nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp, READ_BUF(4); timechange = be32_to_cpup(p++); if (timechange) { - status = nfsd4_decode_time(argp, &lcp->lc_mtime); + status = nfsd4_decode_nfstime4(argp, &lcp->lc_mtime); if (status) return status; } else {