From a30d048e2f84b05eb11989b13b4c9e6b067115f3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Jan 05 2021 17:10:44 +0000 Subject: Merge branch 'users/ddiss/cve/linux-4.12/bsc1178372_EMBARGO' into SLE15-SP1 Pull target fix from David Disseldorp --- diff --git a/patches.suse/target-fix-XCOPY-NAA-identifier-lookup.patch b/patches.suse/target-fix-XCOPY-NAA-identifier-lookup.patch new file mode 100644 index 0000000..0987b7d --- /dev/null +++ b/patches.suse/target-fix-XCOPY-NAA-identifier-lookup.patch @@ -0,0 +1,209 @@ +From f24c7d48a2415ca5ec67d180b45b79fd21f4b2f5 Mon Sep 17 00:00:00 2001 +From: David Disseldorp +Date: Tue, 3 Nov 2020 02:21:58 +0100 +Subject: [PATCH] target: fix XCOPY NAA identifier lookup +Patch-mainline: Not yet, embargoed until 2021-01-12 10:00 PST +References: CVE-2020-28374, bsc#1178372 + +When attempting to match EXTENDED COPY CSCD descriptors with +corresponding se_devices, target_xcopy_locate_se_dev_e4() currently +iterates over LIO's global devices list, which includes all configured +backstores. + +This change ensures that only initiator-accessible backstores are +considered during CSCD descriptor lookup, according to the session's +se_node_acl LUN list. + +To avoid LUN removal race conditions, device pinning is changed from +being ConfigFS based to instead using the se_node_acl lun_ref. + +Reference: CVE-2020-28374 +Fixes: cbf031f425fd ("target: Add support for EXTENDED_COPY copy offload emulation") +Signed-off-by: David Disseldorp +Signed-off-by: Mike Christie +[ddiss: squash with lun_ref pinning change] +--- + drivers/target/target_core_xcopy.c | 115 +++++++++++++++++------------ + drivers/target/target_core_xcopy.h | 1 + + 2 files changed, 69 insertions(+), 47 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index 44e15d7fb2f0..cd38f3c22db6 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -46,60 +46,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) + return 0; + } + +-struct xcopy_dev_search_info { +- const unsigned char *dev_wwn; +- struct se_device *found_dev; +-}; +- ++/** ++ * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers ++ * ++ * @se_dev: device being considered for match ++ * @dev_wwn: XCOPY requested NAA dev_wwn ++ * @return: 1 on match, 0 on no-match ++ */ + static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev, +- void *data) ++ const unsigned char *dev_wwn) + { +- struct xcopy_dev_search_info *info = data; + unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + int rc; + +- if (!se_dev->dev_attrib.emulate_3pc) ++ if (!se_dev->dev_attrib.emulate_3pc) { ++ pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev); + return 0; ++ } + + memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN); + target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]); + +- rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); +- if (rc != 0) +- return 0; +- +- info->found_dev = se_dev; +- pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); +- +- rc = target_depend_item(&se_dev->dev_group.cg_item); ++ rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); + if (rc != 0) { +- pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n", +- rc, se_dev); +- return rc; ++ pr_debug("XCOPY: skip non-matching: %*ph\n", ++ XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn); ++ return 0; + } ++ pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); + +- pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n", +- se_dev, &se_dev->dev_group); + return 1; + } + +-static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, +- struct se_device **found_dev) ++static int target_xcopy_locate_se_dev_e4(struct se_session *sess, ++ const unsigned char *dev_wwn, ++ struct se_device **_found_dev, ++ struct percpu_ref **_found_lun_ref) + { +- struct xcopy_dev_search_info info; +- int ret; ++ struct se_dev_entry *deve; ++ struct se_node_acl *nacl; ++ struct se_lun *this_lun = NULL; ++ struct se_device *found_dev = NULL; ++ int rc = 0; + +- memset(&info, 0, sizeof(info)); +- info.dev_wwn = dev_wwn; ++ /* cmd with NULL sess indicates no associated $FABRIC_MOD */ ++ if (!sess) ++ goto err_out; + +- ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info); +- if (ret == 1) { +- *found_dev = info.found_dev; +- return 0; +- } else { +- pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); +- return -EINVAL; ++ pr_debug("XCOPY 0xe4: searching for: %*ph\n", ++ XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn); ++ ++ nacl = sess->se_node_acl; ++ rcu_read_lock(); ++ hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) { ++ struct se_device *this_dev; ++ ++ this_lun = rcu_dereference(deve->se_lun); ++ this_dev = rcu_dereference_raw(this_lun->lun_se_dev); ++ ++ rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn); ++ if (rc) { ++ if (percpu_ref_tryget_live(&this_lun->lun_ref)) ++ found_dev = this_dev; ++ break; ++ } + } ++ rcu_read_unlock(); ++ if (found_dev == NULL) ++ goto err_out; ++ ++ pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n", ++ found_dev, &found_dev->dev_group); ++ *_found_dev = found_dev; ++ *_found_lun_ref = &this_lun->lun_ref; ++ return 0; ++err_out: ++ pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); ++ return -EINVAL; + } + + static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, +@@ -246,12 +269,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + + switch (xop->op_origin) { + case XCOL_SOURCE_RECV_OP: +- rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, +- &xop->dst_dev); ++ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, ++ xop->dst_tid_wwn, ++ &xop->dst_dev, ++ &xop->remote_lun_ref); + break; + case XCOL_DEST_RECV_OP: +- rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, +- &xop->src_dev); ++ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, ++ xop->src_tid_wwn, ++ &xop->src_dev, ++ &xop->remote_lun_ref); + break; + default: + pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - " +@@ -391,18 +418,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd) + + static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop) + { +- struct se_device *remote_dev; +- + if (xop->op_origin == XCOL_SOURCE_RECV_OP) +- remote_dev = xop->dst_dev; ++ pr_debug("putting dst lun_ref for %p\n", xop->dst_dev); + else +- remote_dev = xop->src_dev; +- +- pr_debug("Calling configfs_undepend_item for" +- " remote_dev: %p remote_dev->dev_group: %p\n", +- remote_dev, &remote_dev->dev_group.cg_item); ++ pr_debug("putting src lun_ref for %p\n", xop->src_dev); + +- target_undepend_item(&remote_dev->dev_group.cg_item); ++ percpu_ref_put(xop->remote_lun_ref); + } + + static void xcopy_pt_release_cmd(struct se_cmd *se_cmd) +diff --git a/drivers/target/target_core_xcopy.h b/drivers/target/target_core_xcopy.h +index c56a1bde9417..e5f20005179a 100644 +--- a/drivers/target/target_core_xcopy.h ++++ b/drivers/target/target_core_xcopy.h +@@ -27,6 +27,7 @@ struct xcopy_op { + struct se_device *dst_dev; + unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; ++ struct percpu_ref *remote_lun_ref; + + sector_t src_lba; + sector_t dst_lba; +-- +2.26.2 + diff --git a/series.conf b/series.conf index af152cb..f45583b 100644 --- a/series.conf +++ b/series.conf @@ -57176,6 +57176,7 @@ patches.suse/0004-ocfs2-give-applications-more-IO-opportunities-during.patch patches.suse/cifs-set_root_ses-ipc.patch patches.suse/ibmvnic-fix-NULL-pointer-dereference.patch + patches.suse/target-fix-XCOPY-NAA-identifier-lookup.patch ######################################################## # end of sorted patches