]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
RDMA/uverbs: Prevent integer overflow issue
authorDan Carpenter <dan.carpenter@linaro.org>
Sat, 30 Nov 2024 10:06:41 +0000 (13:06 +0300)
committerLeon Romanovsky <leon@kernel.org>
Wed, 4 Dec 2024 14:19:39 +0000 (09:19 -0500)
In the expression "cmd.wqe_size * cmd.wr_count", both variables are u32
values that come from the user so the multiplication can lead to integer
wrapping.  Then we pass the result to uverbs_request_next_ptr() which also
could potentially wrap.  The "cmd.sge_count * sizeof(struct ib_uverbs_sge)"
multiplication can also overflow on 32bit systems although it's fine on
64bit systems.

This patch does two things.  First, I've re-arranged the condition in
uverbs_request_next_ptr() so that the use controlled variable "len" is on
one side of the comparison by itself without any math.  Then I've modified
all the callers to use size_mul() for the multiplications.

Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
Cc: stable@vger.kernel.org
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://patch.msgid.link/b8765ab3-c2da-4611-aae0-ddd6ba173d23@stanley.mountain
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/uverbs_cmd.c

index 66b02fbf077ac5672b256100a4a0cadead5c6a7c..5ad14c39d48c98291026adfd451db0ef3e747122 100644 (file)
@@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter,
 {
        const void __user *res = iter->cur;
 
-       if (iter->cur + len > iter->end)
+       if (len > iter->end - iter->cur)
                return (void __force __user *)ERR_PTR(-ENOSPC);
        iter->cur += len;
        return res;
@@ -2008,11 +2008,13 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
        ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
        if (ret)
                return ret;
-       wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count);
+       wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size,
+                                                      cmd.wr_count));
        if (IS_ERR(wqes))
                return PTR_ERR(wqes);
-       sgls = uverbs_request_next_ptr(
-               &iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
+       sgls = uverbs_request_next_ptr(&iter,
+                                      size_mul(cmd.sge_count,
+                                               sizeof(struct ib_uverbs_sge)));
        if (IS_ERR(sgls))
                return PTR_ERR(sgls);
        ret = uverbs_request_finish(&iter);
@@ -2198,11 +2200,11 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count,
        if (wqe_size < sizeof(struct ib_uverbs_recv_wr))
                return ERR_PTR(-EINVAL);
 
-       wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count);
+       wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count));
        if (IS_ERR(wqes))
                return ERR_CAST(wqes);
-       sgls = uverbs_request_next_ptr(
-               iter, sge_count * sizeof(struct ib_uverbs_sge));
+       sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
+                                                     sizeof(struct ib_uverbs_sge)));
        if (IS_ERR(sgls))
                return ERR_CAST(sgls);
        ret = uverbs_request_finish(iter);