On Mon, Sep 16, 2024 at 06:14:15PM +0300, Dan Carpenter wrote: > If "length" is >= U32_MAX - 3 then the "length + 4" addition can result > in an integer overflow. The impact of this bug is not totally clear to > me, but it's safer to not allow the integer overflow. > > There is also some math in xdr_inline_decode() which could overflow, so > really it's ">= U32_MAX - 7" which is problematic. Let's just check > against INT_MAX and make it easy. > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Signed-off-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> > --- > fs/nfsd/nfs4callback.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c > index 43b8320c8255..12b44c9246d1 100644 > --- a/fs/nfsd/nfs4callback.c > +++ b/fs/nfsd/nfs4callback.c > @@ -317,6 +317,8 @@ static int decode_cb_compound4res(struct xdr_stream *xdr, > hdr->status = be32_to_cpup(p++); > /* Ignore the tag */ > length = be32_to_cpup(p++); > + if (unlikely(length > INT_MAX)) > + goto out_overflow; I think we assume (wrongly) that xdr_inline_decode() will kick back any length request that is larger than the xdr_stream's xdr_buf. Here, the test could be the same: any @length value that is larger than xdr->buf->len is bogus. Another way to avoid the overflow would be to split the decode of the tag and the following op count field. Untested: length = be32_to_cpup(p); p = xdr_inline_decode(xdr, length); if (unlikely(p == NULL)) goto out_overflow; if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0) goto out_overflow; I have generally been using this approach in other NFSD XDR decoding functions. I wonder how many other xdr_inline_decode() call sites have a similar issue. > p = xdr_inline_decode(xdr, length + 4); > if (unlikely(p == NULL)) > goto out_overflow; > -- > 2.45.2 > -- Chuck Lever