Commit b3f0ae83 authored by Dan Carpenter's avatar Dan Carpenter Committed by Wen Zhiwei
Browse files

RDMA/uverbs: Prevent integer overflow issue

stable inclusion
from stable-v6.6.70
commit b92667f755749cf10d9ef1088865c555ae83ffb7
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBOHV1

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b92667f755749cf10d9ef1088865c555ae83ffb7



--------------------------------

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>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 60e14be9
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;
@@ -2009,11 +2009,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);
@@ -2199,11 +2201,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);