]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
rdma/cm: Fix crash from treating SIDR REQ as REQ
authorSean Hefty <sean.hefty@intel.com>
Mon, 22 Aug 2011 17:14:34 +0000 (10:14 -0700)
committerSean Hefty <sean.hefty@intel.com>
Mon, 22 Aug 2011 17:14:34 +0000 (10:14 -0700)
The rdma_cm uses the local qp_type to determine how to
process an incoming request.  This can result in an
incoming REQ being treated as a SIDR REQ and vice versa.
Fix this by checking that the incoming request matches
the qp type.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
drivers/infiniband/core/cma.c

index b6a33b3c516de9b8d1c12f0c20e958ff3608e9a5..db584785289a98113f078a78e05a46560c79e168 100644 (file)
@@ -1181,6 +1181,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
        event->param.conn.qp_num = req_data->remote_qpn;
 }
 
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+       return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+                (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+               ((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+                (id->qp_type == IB_QPT_UD)) ||
+               (!id->qp_type));
+}
+
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
        struct rdma_id_private *listen_id, *conn_id;
@@ -1188,13 +1197,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
        int offset, ret;
 
        listen_id = cm_id->context;
+       if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+               return -EINVAL;
+
        if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
                return -ECONNABORTED;
 
        memset(&event, 0, sizeof event);
        offset = cma_user_data_offset(listen_id->id.ps);
        event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-       if (listen_id->id.qp_type == IB_QPT_UD) {
+       if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
                conn_id = cma_new_udp_id(&listen_id->id, ib_event);
                event.param.ud.private_data = ib_event->private_data + offset;
                event.param.ud.private_data_len =