From: Chuck Lever <chuck.lever@xxxxxxxxxx> commit 7f33b92e5b18e904a481e6e208486da43e4dc841 upstream. If the tag length is >= U32_MAX - 3 then the "length + 4" addition can result in an integer overflow. Address this by splitting the decoding into several steps so that decode_cb_compound4res() does not have to perform arithmetic on the unsafe length value. Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/nfsd/nfs4callback.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -297,17 +297,17 @@ static int decode_cb_compound4res(struct u32 length; __be32 *p; - p = xdr_inline_decode(xdr, 4 + 4); + p = xdr_inline_decode(xdr, XDR_UNIT); if (unlikely(p == NULL)) goto out_overflow; - hdr->status = be32_to_cpup(p++); + hdr->status = be32_to_cpup(p); /* Ignore the tag */ - length = be32_to_cpup(p++); - p = xdr_inline_decode(xdr, length + 4); - if (unlikely(p == NULL)) + if (xdr_stream_decode_u32(xdr, &length) < 0) + goto out_overflow; + if (xdr_inline_decode(xdr, length) == NULL) + goto out_overflow; + if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0) goto out_overflow; - p += XDR_QUADLEN(length); - hdr->nops = be32_to_cpup(p); return 0; out_overflow: return -EIO; Patches currently in stable-queue which might be from chuck.lever@xxxxxxxxxx are queue-6.6/nfsd-release-svc_expkey-svc_export-with-rcu_work.patch queue-6.6/nfsd-fix-nfsd4_shutdown_copy.patch queue-6.6/nfsd-prevent-a-potential-integer-overflow.patch queue-6.6/nfsd-prevent-null-dereference-in-nfsd4_process_cb_up.patch queue-6.6/svcrdma-address-an-integer-overflow.patch queue-6.6/svcrdma-fix-miss-destroy-percpu_counter-in-svc_rdma_.patch queue-6.6/sunrpc-make-sure-cache-entry-active-before-cache_show.patch queue-6.6/nfsd-cap-the-number-of-bytes-copied-by-nfs4_reset_re.patch