NFSD: Prevent a potential integer overflow
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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3dad1d8a87
commit
745f7ce5a9
@@ -283,17 +283,17 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
|
|||||||
u32 length;
|
u32 length;
|
||||||
__be32 *p;
|
__be32 *p;
|
||||||
|
|
||||||
p = xdr_inline_decode(xdr, 4 + 4);
|
p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
if (unlikely(p == NULL))
|
if (unlikely(p == NULL))
|
||||||
goto out_overflow;
|
goto out_overflow;
|
||||||
hdr->status = be32_to_cpup(p++);
|
hdr->status = be32_to_cpup(p);
|
||||||
/* Ignore the tag */
|
/* Ignore the tag */
|
||||||
length = be32_to_cpup(p++);
|
if (xdr_stream_decode_u32(xdr, &length) < 0)
|
||||||
p = xdr_inline_decode(xdr, length + 4);
|
goto out_overflow;
|
||||||
if (unlikely(p == NULL))
|
if (xdr_inline_decode(xdr, length) == NULL)
|
||||||
|
goto out_overflow;
|
||||||
|
if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0)
|
||||||
goto out_overflow;
|
goto out_overflow;
|
||||||
p += XDR_QUADLEN(length);
|
|
||||||
hdr->nops = be32_to_cpup(p);
|
|
||||||
return 0;
|
return 0;
|
||||||
out_overflow:
|
out_overflow:
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|||||||
Reference in New Issue
Block a user