NFSD: Prevent a potential integer overflow

BugLink: https://bugs.launchpad.net/bugs/2101915

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@linaro.org>
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CVE-2024-53146
Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
Chuck Lever
2025-03-11 08:51:19 +09:00
committed by Stefan Bader
parent 39100faae8
commit 49ed664ab2
+7 -7
View File
@@ -287,17 +287,17 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
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;