aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorRoland Dreier <roland@purestorage.com>2012-06-05 02:37:34 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-06-12 23:12:25 -0400
commit3578ddba1ae93263d373e7bc85fd38d1f0368b78 (patch)
treec62e16158acdd7eea4106d56883352d114ac499f /drivers/scsi
parent59e4f541baf728dbb426949bfa9f6862387ffd0e (diff)
tcm_qla2xxx: Don't insert nacls without sessions into the btree
When we create an explicit node ACL in tcm_qla2xxx_make_nodeacl(), there is a call to tcm_qla2xxx_setup_nacl_from_rport(), which puts the node ACL into the lport_fcport_map even though there is no session yet for the initiator. Since the only time we remove entries from this map is when we free a session, this means that if we later delete this node ACL without the initiator ever creating a session, we'll leave the nacl pointer in the btree pointing at freed memory. This is especially bad if that initiator later does send us a command that would cause us to create a dynamic ACL and session: we'll find the stale freed nacl pointer in the btree and end up with use-after-free. We could add more code to clear the btree entry when deleting the explicit nacl, but the original insertion is pointless: without a session attached, we'll just have to update the entry when a session appears anyway. So we can just delete tcm_qla2xxx_setup_nacl_from_rport() and the code that calls it. Signed-off-by: Roland Dreier <roland@purestorage.com> Cc: Chad Dupuis <chad.dupuis@qlogic.com> Cc: Giridhar Malavali <giridhar.malavali@qlogic.com> Cc: Arun Easi <arun.easi@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c73
1 files changed, 0 insertions, 73 deletions
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index a641c970569a..acc3b1151c4f 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -762,65 +762,6 @@ static u16 tcm_qla2xxx_set_fabric_sense_len(struct se_cmd *se_cmd,
762struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs; 762struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs;
763struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs; 763struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs;
764 764
765static int tcm_qla2xxx_setup_nacl_from_rport(
766 struct se_portal_group *se_tpg,
767 struct se_node_acl *se_nacl,
768 struct tcm_qla2xxx_lport *lport,
769 struct tcm_qla2xxx_nacl *nacl,
770 u64 rport_wwnn)
771{
772 struct scsi_qla_host *vha = lport->qla_vha;
773 struct Scsi_Host *sh = vha->host;
774 struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
775 struct fc_rport *rport;
776 unsigned long flags;
777 void *node;
778 int rc;
779
780 /*
781 * Scan the existing rports, and create a session for the
782 * explict NodeACL is an matching rport->node_name already
783 * exists.
784 */
785 spin_lock_irqsave(sh->host_lock, flags);
786 list_for_each_entry(rport, &fc_host->rports, peers) {
787 if (rport_wwnn != rport->node_name)
788 continue;
789
790 pr_debug("Located existing rport_wwpn and rport->node_name: 0x%016LX, port_id: 0x%04x\n",
791 rport->node_name, rport->port_id);
792 nacl->nport_id = rport->port_id;
793
794 spin_unlock_irqrestore(sh->host_lock, flags);
795
796 spin_lock_irqsave(&vha->hw->hardware_lock, flags);
797 node = btree_lookup32(&lport->lport_fcport_map, rport->port_id);
798 if (node) {
799 rc = btree_update32(&lport->lport_fcport_map,
800 rport->port_id, se_nacl);
801 } else {
802 rc = btree_insert32(&lport->lport_fcport_map,
803 rport->port_id, se_nacl,
804 GFP_ATOMIC);
805 }
806 spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
807
808 if (rc) {
809 pr_err("Unable to insert se_nacl into fcport_map");
810 WARN_ON(rc > 0);
811 return rc;
812 }
813
814 pr_debug("Inserted into fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%08x\n",
815 se_nacl, rport_wwnn, nacl->nport_id);
816
817 return 1;
818 }
819 spin_unlock_irqrestore(sh->host_lock, flags);
820
821 return 0;
822}
823
824static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, 765static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
825 struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); 766 struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *);
826/* 767/*
@@ -890,14 +831,10 @@ static struct se_node_acl *tcm_qla2xxx_make_nodeacl(
890 struct config_group *group, 831 struct config_group *group,
891 const char *name) 832 const char *name)
892{ 833{
893 struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
894 struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
895 struct tcm_qla2xxx_lport, lport_wwn);
896 struct se_node_acl *se_nacl, *se_nacl_new; 834 struct se_node_acl *se_nacl, *se_nacl_new;
897 struct tcm_qla2xxx_nacl *nacl; 835 struct tcm_qla2xxx_nacl *nacl;
898 u64 wwnn; 836 u64 wwnn;
899 u32 qla2xxx_nexus_depth; 837 u32 qla2xxx_nexus_depth;
900 int rc;
901 838
902 if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) 839 if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0)
903 return ERR_PTR(-EINVAL); 840 return ERR_PTR(-EINVAL);
@@ -924,16 +861,6 @@ static struct se_node_acl *tcm_qla2xxx_make_nodeacl(
924 nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); 861 nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
925 nacl->nport_wwnn = wwnn; 862 nacl->nport_wwnn = wwnn;
926 tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); 863 tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn);
927 /*
928 * Setup a se_nacl handle based on an a matching struct fc_rport setup
929 * via drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port()
930 */
931 rc = tcm_qla2xxx_setup_nacl_from_rport(se_tpg, se_nacl, lport,
932 nacl, wwnn);
933 if (rc < 0) {
934 tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new);
935 return ERR_PTR(rc);
936 }
937 864
938 return se_nacl; 865 return se_nacl;
939} 866}