Browse Source

IB/iser: Fix possible NULL derefernce ib_conn->device in session_create

If rdma_cm error event comes after ep_poll but before conn_bind, we
should protect against dereferncing the device (which may have been
terminated) in session_create and conn_create (already protected)
callbacks.

Signed-off-by: Ariel Nahum <arieln@mellanox.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Ariel Nahum 10 years ago
parent
commit
3f562a0b8f
1 changed files with 18 additions and 4 deletions
  1. 18 4
      drivers/infiniband/ulp/iser/iscsi_iser.c

+ 18 - 4
drivers/infiniband/ulp/iser/iscsi_iser.c

@@ -588,6 +588,15 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
 	if (ep) {
 	if (ep) {
 		iser_conn = ep->dd_data;
 		iser_conn = ep->dd_data;
 		max_cmds = iser_conn->max_cmds;
 		max_cmds = iser_conn->max_cmds;
+
+		mutex_lock(&iser_conn->state_mutex);
+		if (iser_conn->state != ISER_CONN_UP) {
+			iser_err("iser conn %p already started teardown\n",
+				 iser_conn);
+			mutex_unlock(&iser_conn->state_mutex);
+			goto free_host;
+		}
+
 		ib_conn = &iser_conn->ib_conn;
 		ib_conn = &iser_conn->ib_conn;
 		if (ib_conn->pi_support) {
 		if (ib_conn->pi_support) {
 			u32 sig_caps = ib_conn->device->dev_attr.sig_prot_cap;
 			u32 sig_caps = ib_conn->device->dev_attr.sig_prot_cap;
@@ -598,14 +607,19 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
 			else
 			else
 				scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
 				scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
 		}
 		}
+
+		if (iscsi_host_add(shost,
+				   ib_conn->device->ib_device->dma_device)) {
+			mutex_unlock(&iser_conn->state_mutex);
+			goto free_host;
+		}
+		mutex_unlock(&iser_conn->state_mutex);
 	} else {
 	} else {
 		max_cmds = ISER_DEF_XMIT_CMDS_MAX;
 		max_cmds = ISER_DEF_XMIT_CMDS_MAX;
+		if (iscsi_host_add(shost, NULL))
+			goto free_host;
 	}
 	}
 
 
-	if (iscsi_host_add(shost, ep ?
-			   ib_conn->device->ib_device->dma_device : NULL))
-		goto free_host;
-
 	if (cmds_max > max_cmds) {
 	if (cmds_max > max_cmds) {
 		iser_info("cmds_max changed from %u to %u\n",
 		iser_info("cmds_max changed from %u to %u\n",
 			  cmds_max, max_cmds);
 			  cmds_max, max_cmds);