Commit ea49c88f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mkp-scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi

Pull SCSI target fix from Martin Petersen:
 "This addresses an issue in the SCSI target subsystem. A connected
  initiator could specify IDs for any configured backing store device,
  not just the ones explicitly made visible to the host.

  The remedy is to honor the access control list when doing ID
  descriptor lookups"

* tag 'mkp-scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi:
  scsi: target: Fix XCOPY NAA identifier lookup
parents a0d54b4f 2896c938
......@@ -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;
/* cmd with NULL sess indicates no associated $FABRIC_MOD */
if (!sess)
goto err_out;
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;
int rc;
memset(&info, 0, sizeof(info));
info.dev_wwn = dev_wwn;
this_lun = rcu_dereference(deve->se_lun);
this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info);
if (ret == 1) {
*found_dev = info.found_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;
} else {
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)
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment