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: 67cdb40ca4 ("[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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
213305a1cb
commit
c57721b24b
1 changed files with 9 additions and 7 deletions
|
|
@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter,
|
||||||
{
|
{
|
||||||
const void __user *res = iter->cur;
|
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);
|
return (void __force __user *)ERR_PTR(-ENOSPC);
|
||||||
iter->cur += len;
|
iter->cur += len;
|
||||||
return res;
|
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));
|
ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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))
|
if (IS_ERR(wqes))
|
||||||
return PTR_ERR(wqes);
|
return PTR_ERR(wqes);
|
||||||
sgls = uverbs_request_next_ptr(
|
sgls = uverbs_request_next_ptr(&iter,
|
||||||
&iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
|
size_mul(cmd.sge_count,
|
||||||
|
sizeof(struct ib_uverbs_sge)));
|
||||||
if (IS_ERR(sgls))
|
if (IS_ERR(sgls))
|
||||||
return PTR_ERR(sgls);
|
return PTR_ERR(sgls);
|
||||||
ret = uverbs_request_finish(&iter);
|
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))
|
if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
|
||||||
return ERR_PTR(-EINVAL);
|
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))
|
if (IS_ERR(wqes))
|
||||||
return ERR_CAST(wqes);
|
return ERR_CAST(wqes);
|
||||||
sgls = uverbs_request_next_ptr(
|
sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
|
||||||
iter, sge_count * sizeof(struct ib_uverbs_sge));
|
sizeof(struct ib_uverbs_sge)));
|
||||||
if (IS_ERR(sgls))
|
if (IS_ERR(sgls))
|
||||||
return ERR_CAST(sgls);
|
return ERR_CAST(sgls);
|
||||||
ret = uverbs_request_finish(iter);
|
ret = uverbs_request_finish(iter);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue