[openib-general] [PATCH v2 1/7] AMSO1100 Low Level Driver.

Bob Sharp bsharp at NetEffect.com
Wed Jun 14 18:35:50 PDT 2006


> +void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
> +{
> +	struct c2_mq *mq = c2dev->qptr_array[mq_index];
> +	union c2wr *wr;
> +	void *resource_user_context;
> +	struct iw_cm_event cm_event;
> +	struct ib_event ib_event;
> +	enum c2_resource_indicator resource_indicator;
> +	enum c2_event_id event_id;
> +	unsigned long flags;
> +	u8 *pdata = NULL;
> +	int status;
> +
> +	/*
> +	 * retreive the message
> +	 */
> +	wr = c2_mq_consume(mq);
> +	if (!wr)
> +		return;
> +
> +	memset(&ib_event, 0, sizeof(ib_event));
> +	memset(&cm_event, 0, sizeof(cm_event));
> +
> +	event_id = c2_wr_get_id(wr);
> +	resource_indicator =
be32_to_cpu(wr->ae.ae_generic.resource_type);
> +	resource_user_context
> +	    (void *) (unsigned long) wr->ae.ae_generic.user_context;
> +
> +	status = cm_event.status =
> c2_convert_cm_status(c2_wr_get_result(wr));
> +
> +	pr_debug("event received c2_dev=%p, event_id=%d, "
> +		"resource_indicator=%d, user_context=%p, status = %d\n",
> +		c2dev, event_id, resource_indicator,
resource_user_context,
> +		status);
> +
> +	switch (resource_indicator) {
> +	case C2_RES_IND_QP:{
> +
> +		struct c2_qp *qp = (struct c2_qp
*)resource_user_context;
> +		struct iw_cm_id *cm_id = qp->cm_id;
> +		struct c2wr_ae_active_connect_results *res;
> +
> +		if (!cm_id) {
> +			pr_debug("event received, but cm_id is <nul>,
qp=%p!\n",
> +				qp);
> +			goto ignore_it;
> +		}
> +		pr_debug("%s: event = %s, user_context=%llx, "
> +			"resource_type=%x, "
> +			"resource=%x, qp_state=%s\n",
> +			__FUNCTION__,
> +			to_event_str(event_id),
> +			be64_to_cpu(wr->ae.ae_generic.user_context),
> +			be32_to_cpu(wr->ae.ae_generic.resource_type),
> +			be32_to_cpu(wr->ae.ae_generic.resource),
> +			to_qp_state_str(be32_to_cpu(wr-
> >ae.ae_generic.qp_state)));
> +
> +		c2_set_qp_state(qp,
be32_to_cpu(wr->ae.ae_generic.qp_state));
> +
> +		switch (event_id) {
> +		case CCAE_ACTIVE_CONNECT_RESULTS:
> +			res = &wr->ae.ae_active_connect_results;
> +			cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
> +			cm_event.local_addr.sin_addr.s_addr =
res->laddr;
> +			cm_event.remote_addr.sin_addr.s_addr =
res->raddr;
> +			cm_event.local_addr.sin_port = res->lport;
> +			cm_event.remote_addr.sin_port =	res->rport;
> +			if (status == 0) {
> +				cm_event.private_data_len =
> +
be32_to_cpu(res->private_data_length);
> +			} else {
> +				spin_lock_irqsave(&qp->lock, flags);
> +				if (qp->cm_id) {
> +					qp->cm_id->rem_ref(qp->cm_id);
> +					qp->cm_id = NULL;
> +				}
> +				spin_unlock_irqrestore(&qp->lock,
flags);
> +				cm_event.private_data_len = 0;
> +				cm_event.private_data = NULL;
> +			}
> +			if (cm_event.private_data_len) {
> +				/* copy private data */
> +				pdata
> +				    kmalloc(cm_event.private_data_len,
> +					    GFP_ATOMIC);
> +				if (!pdata) {
> +					/* Ignore the request, maybe the
> +					 * remote peer will retry */
> +					pr_debug ("Ignored connect
request -- "
> +						 "no memory for pdata"
> +
"private_data_len=%d\n",
> +
cm_event.private_data_len);
> +					goto ignore_it;
> +				}
> +
> +				memcpy(pdata, res->private_data,
> +				       cm_event.private_data_len);
> +
> +				cm_event.private_data = pdata;
> +			}
> +			if (cm_id->event_handler)
> +				cm_id->event_handler(cm_id, &cm_event);
> +			break;
> +		case CCAE_TERMINATE_MESSAGE_RECEIVED:
> +		case CCAE_CQ_SQ_COMPLETION_OVERFLOW:
> +			ib_event.device = &c2dev->ibdev;
> +			ib_event.element.qp = &qp->ibqp;
> +			ib_event.event = IB_EVENT_QP_REQ_ERR;
> +
> +			if (qp->ibqp.event_handler)
> +				qp->ibqp.event_handler(&ib_event,
> +						       qp->ibqp.
> +						       qp_context);
> +			break;
> +		case CCAE_BAD_CLOSE:
> +		case CCAE_LLP_CLOSE_COMPLETE:
> +		case CCAE_LLP_CONNECTION_RESET:
> +		case CCAE_LLP_CONNECTION_LOST:
> +			BUG_ON(cm_id->event_handler==(void*)0x6b6b6b6b);
> +
> +			spin_lock_irqsave(&qp->lock, flags);
> +			if (qp->cm_id) {
> +				qp->cm_id->rem_ref(qp->cm_id);
> +				qp->cm_id = NULL;
> +			}
> +			spin_unlock_irqrestore(&qp->lock, flags);
> +			cm_event.event = IW_CM_EVENT_CLOSE;
> +			cm_event.status = 0;
> +			if (cm_id->event_handler)
> +				cm_id->event_handler(cm_id, &cm_event);
> +			break;
> +		default:
> +			BUG_ON(1);
> +			pr_debug("%s:%d Unexpected event_id=%d on QP=%p,
"
> +				"CM_ID=%p\n",
> +				__FUNCTION__, __LINE__,
> +				event_id, qp, cm_id);
> +			break;
> +		}
> +		break;
> +	}
> +
> +	case C2_RES_IND_EP:{
> +
> +		struct c2wr_ae_connection_request *req =
> +			&wr->ae.ae_connection_request;
> +		struct iw_cm_id *cm_id =
> +			(struct iw_cm_id *)resource_user_context;
> +
> +		pr_debug("C2_RES_IND_EP event_id=%d\n", event_id);
> +		if (event_id != CCAE_CONNECTION_REQUEST) {
> +			pr_debug("%s: Invalid event_id: %d\n",
> +				__FUNCTION__, event_id);
> +			break;
> +		}
> +		cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
> +		cm_event.provider_data = (void*)(unsigned
long)req->cr_handle;
> +		cm_event.local_addr.sin_addr.s_addr = req->laddr;
> +		cm_event.remote_addr.sin_addr.s_addr = req->raddr;
> +		cm_event.local_addr.sin_port = req->lport;
> +		cm_event.remote_addr.sin_port = req->rport;
> +		cm_event.private_data_len =
> +			be32_to_cpu(req->private_data_length);
> +
> +		if (cm_event.private_data_len) {


It looks to me as if pdata is leaking here since it is not tracked and
the upper layers do not free it.  Also, if pdata is freed after the call
to cm_id->event_handler returns, it exposes an issue in user space where
the private data is garbage.  I suspect the iwarp cm should be copying
this data before it returns.

> +			pdata
> +			    kmalloc(cm_event.private_data_len,
> +				    GFP_ATOMIC);
> +			if (!pdata) {
> +				/* Ignore the request, maybe the remote
peer
> +				 * will retry */
> +				pr_debug ("Ignored connect request -- "
> +					 "no memory for pdata"
> +					 "private_data_len=%d\n",
> +					 cm_event.private_data_len);
> +				goto ignore_it;
> +			}
> +			memcpy(pdata,
> +			       req->private_data,
> +			       cm_event.private_data_len);
> +
> +			cm_event.private_data = pdata;
> +		}
> +		if (cm_id->event_handler)
> +			cm_id->event_handler(cm_id, &cm_event);
> +		break;
> +	}
> +

Bob





More information about the general mailing list