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

Commit e511d1ae authored by Sean Hefty's avatar Sean Hefty Committed by Roland Dreier
Browse files

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: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 8fb488d7
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -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_id	*id;
	void *private_data;
	int offset, ret;

	memset(&req, 0, sizeof req);
	offset = cma_user_data_offset(id_priv);
	req.private_data_len = offset + conn_param->private_data_len;
	if (req.private_data_len < conn_param->private_data_len)
		return -EINVAL;

	if (req.private_data_len) {
		req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
		if (!req.private_data)
		private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
		if (!private_data)
			return -ENOMEM;
	} else {
		req.private_data = NULL;
		private_data = NULL;
	}

	if (conn_param->private_data && conn_param->private_data_len)
		memcpy((void *) req.private_data + offset,
		       conn_param->private_data, conn_param->private_data_len);
		memcpy(private_data + offset, conn_param->private_data,
		       conn_param->private_data_len);

	if (req.private_data) {
		ret = cma_format_hdr((void *) req.private_data, id_priv);
	if (private_data) {
		ret = cma_format_hdr(private_data, id_priv);
		if (ret)
			goto out;
		req.private_data = private_data;
	}

	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;
	}
out:
	kfree(req.private_data);
	kfree(private_data);
	return ret;
}