mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-17 20:54:10 +00:00
scsi: target: Fix XCOPY NAA identifier lookup
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: cbf031f425
("target: Add support for EXTENDED_COPY copy offload emulation")
Reviewed-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
e71ba9452f
commit
2896c93811
2 changed files with 69 additions and 47 deletions
|
@ -46,60 +46,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xcopy_dev_search_info {
|
/**
|
||||||
const unsigned char *dev_wwn;
|
* target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
|
||||||
struct se_device *found_dev;
|
*
|
||||||
};
|
* @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,
|
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];
|
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
||||||
int rc;
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
|
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||||
target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
|
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);
|
rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||||
if (rc != 0)
|
if (rc != 0) {
|
||||||
|
pr_debug("XCOPY: skip non-matching: %*ph\n",
|
||||||
|
XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
info->found_dev = se_dev;
|
|
||||||
pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
|
pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
|
||||||
|
|
||||||
rc = target_depend_item(&se_dev->dev_group.cg_item);
|
|
||||||
if (rc != 0) {
|
|
||||||
pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n",
|
|
||||||
rc, se_dev);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
|
static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
|
||||||
struct se_device **found_dev)
|
const unsigned char *dev_wwn,
|
||||||
|
struct se_device **_found_dev,
|
||||||
|
struct percpu_ref **_found_lun_ref)
|
||||||
{
|
{
|
||||||
struct xcopy_dev_search_info info;
|
struct se_dev_entry *deve;
|
||||||
int ret;
|
struct se_node_acl *nacl;
|
||||||
|
struct se_lun *this_lun = NULL;
|
||||||
|
struct se_device *found_dev = NULL;
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
/* cmd with NULL sess indicates no associated $FABRIC_MOD */
|
||||||
info.dev_wwn = dev_wwn;
|
if (!sess)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info);
|
pr_debug("XCOPY 0xe4: searching for: %*ph\n",
|
||||||
if (ret == 1) {
|
XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
|
||||||
*found_dev = info.found_dev;
|
|
||||||
return 0;
|
nacl = sess->se_node_acl;
|
||||||
} else {
|
rcu_read_lock();
|
||||||
pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
|
hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
|
||||||
return -EINVAL;
|
struct se_device *this_dev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
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,
|
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) {
|
switch (xop->op_origin) {
|
||||||
case XCOL_SOURCE_RECV_OP:
|
case XCOL_SOURCE_RECV_OP:
|
||||||
rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
|
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
|
||||||
&xop->dst_dev);
|
xop->dst_tid_wwn,
|
||||||
|
&xop->dst_dev,
|
||||||
|
&xop->remote_lun_ref);
|
||||||
break;
|
break;
|
||||||
case XCOL_DEST_RECV_OP:
|
case XCOL_DEST_RECV_OP:
|
||||||
rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
|
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
|
||||||
&xop->src_dev);
|
xop->src_tid_wwn,
|
||||||
|
&xop->src_dev,
|
||||||
|
&xop->remote_lun_ref);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
|
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)
|
static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
|
||||||
{
|
{
|
||||||
struct se_device *remote_dev;
|
|
||||||
|
|
||||||
if (xop->op_origin == XCOL_SOURCE_RECV_OP)
|
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
|
else
|
||||||
remote_dev = xop->src_dev;
|
pr_debug("putting src lun_ref for %p\n", xop->src_dev);
|
||||||
|
|
||||||
pr_debug("Calling configfs_undepend_item for"
|
percpu_ref_put(xop->remote_lun_ref);
|
||||||
" remote_dev: %p remote_dev->dev_group: %p\n",
|
|
||||||
remote_dev, &remote_dev->dev_group.cg_item);
|
|
||||||
|
|
||||||
target_undepend_item(&remote_dev->dev_group.cg_item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
|
static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct xcopy_op {
|
||||||
struct se_device *dst_dev;
|
struct se_device *dst_dev;
|
||||||
unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
||||||
unsigned char local_dev_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 src_lba;
|
||||||
sector_t dst_lba;
|
sector_t dst_lba;
|
||||||
|
|
Loading…
Add table
Reference in a new issue