RDMA/cma: Fix accessing invalid private data for UD
If a application is using AF_IB with a UD QP, but does not provide any private data, we will end up accessing invalid memory. Check for this case and handle it appropriately. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
8fb488d740
commit
e511d1ae16
1 changed files with 11 additions and 8 deletions
|
@ -2676,29 +2676,32 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
|
||||||
{
|
{
|
||||||
struct ib_cm_sidr_req_param req;
|
struct ib_cm_sidr_req_param req;
|
||||||
struct ib_cm_id *id;
|
struct ib_cm_id *id;
|
||||||
|
void *private_data;
|
||||||
int offset, ret;
|
int offset, ret;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof req);
|
||||||
offset = cma_user_data_offset(id_priv);
|
offset = cma_user_data_offset(id_priv);
|
||||||
req.private_data_len = offset + conn_param->private_data_len;
|
req.private_data_len = offset + conn_param->private_data_len;
|
||||||
if (req.private_data_len < conn_param->private_data_len)
|
if (req.private_data_len < conn_param->private_data_len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (req.private_data_len) {
|
if (req.private_data_len) {
|
||||||
req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
|
private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
|
||||||
if (!req.private_data)
|
if (!private_data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
req.private_data = NULL;
|
private_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn_param->private_data && conn_param->private_data_len)
|
if (conn_param->private_data && conn_param->private_data_len)
|
||||||
memcpy((void *) req.private_data + offset,
|
memcpy(private_data + offset, conn_param->private_data,
|
||||||
conn_param->private_data, conn_param->private_data_len);
|
conn_param->private_data_len);
|
||||||
|
|
||||||
if (req.private_data) {
|
if (private_data) {
|
||||||
ret = cma_format_hdr((void *) req.private_data, id_priv);
|
ret = cma_format_hdr(private_data, id_priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
req.private_data = private_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
|
id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
|
||||||
|
@ -2720,7 +2723,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
|
||||||
id_priv->cm_id.ib = NULL;
|
id_priv->cm_id.ib = NULL;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
kfree(req.private_data);
|
kfree(private_data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue