]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
svcrdma: Address an integer overflow
authorChuck Lever <chuck.lever@oracle.com>
Tue, 17 Sep 2024 16:15:29 +0000 (12:15 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 11 Nov 2024 18:41:57 +0000 (13:41 -0500)
Dan Carpenter reports:
> Commit 78147ca8b4a9 ("svcrdma: Add a "parsed chunk list" data
> structure") from Jun 22, 2020 (linux-next), leads to the following
> Smatch static checker warning:
>
> net/sunrpc/xprtrdma/svc_rdma_recvfrom.c:498 xdr_check_write_chunk()
> warn: potential user controlled sizeof overflow 'segcount * 4 * 4'
>
> net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
>     488 static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)
>     489 {
>     490         u32 segcount;
>     491         __be32 *p;
>     492
>     493         if (xdr_stream_decode_u32(&rctxt->rc_stream, &segcount))
>                                                               ^^^^^^^^
>
>     494                 return false;
>     495
>     496         /* A bogus segcount causes this buffer overflow check to fail. */
>     497         p = xdr_inline_decode(&rctxt->rc_stream,
> --> 498                               segcount * rpcrdma_segment_maxsz * sizeof(*p));
>
>
> segcount is an untrusted u32.  On 32bit systems anything >= SIZE_MAX / 16 will
> have an integer overflow and some those values will be accepted by
> xdr_inline_decode().

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Fixes: 78147ca8b4a9 ("svcrdma: Add a "parsed chunk list" data structure")
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

index ae3fb9bc8a21688a43324c7577aab880b048ee1f..292022f0976e17b2226612ae12b2e1e6d71fc757 100644 (file)
@@ -493,7 +493,13 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)
        if (xdr_stream_decode_u32(&rctxt->rc_stream, &segcount))
                return false;
 
-       /* A bogus segcount causes this buffer overflow check to fail. */
+       /* Before trusting the segcount value enough to use it in
+        * a computation, perform a simple range check. This is an
+        * arbitrary but sensible limit (ie, not architectural).
+        */
+       if (unlikely(segcount > RPCSVC_MAXPAGES))
+               return false;
+
        p = xdr_inline_decode(&rctxt->rc_stream,
                              segcount * rpcrdma_segment_maxsz * sizeof(*p));
        return p != NULL;