Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c57721b2 authored by Dan Carpenter's avatar Dan Carpenter Committed by Greg Kroah-Hartman
Browse files

RDMA/uverbs: Prevent integer overflow issue



commit d0257e089d1bbd35c69b6c97ff73e3690ab149a9 upstream.

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: 67cdb40c ("[IB] uverbs: Implement more commands")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDan Carpenter <dan.carpenter@linaro.org>
Link: https://patch.msgid.link/b8765ab3-c2da-4611-aae0-ddd6ba173d23@stanley.mountain


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 213305a1
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -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;
@@ -2024,11 +2024,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);
@@ -2213,11 +2215,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);