]> git.hungrycats.org Git - linux/commitdiff
NFSD: Prevent a potential integer overflow
authorChuck Lever <chuck.lever@oracle.com>
Tue, 17 Sep 2024 16:15:23 +0000 (12:15 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2024 12:54:26 +0000 (13:54 +0100)
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>
fs/nfsd/nfs4callback.c

index e6183097517ffac0e4fa8b4b672e6fa3b114fa52..245efbbf145479da6c01d1e1c552a410af3a063d 100644 (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;