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. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZOpW2gUwxXeCmhkh7ulgGnXF3j0FAl/8z5UACgkQ7ulgGnXF 3j2GUhAAnx2ZRzskvSzxpj0/4cC1vWYA43pBMRxoSmWyLKnOPOGenYQVZDl4H3Qp kC0TIzvrqqLdFjHNyL3gqR9NMp/NoIO4zVu6tM0ofUoOKNJfSoqRDpJawklIGTQE GbPPavV74vFMHG1QN+6xCXsYMhWXz4Q1iMRpybWHl8jhPAGbY7eQ+Ge4UUafC8Ij xGzTopSdTtW+KKssYWuvqy991GJoYNtNhhXbc3yVTi+4hTWzU2rK7Em2+LH5x+WW aghHvYfBUH0QiHTEZNTHT5Z2zAtXHZzvFbzCH88GblbPGlZ/CPN7pvUQGnFhW0m9 2GNCC4UsYb9KRiwYtNKrhxkA9kLHvH2BQ04Uhx5xR1c8v1y5DqjGBAu3MG9/lnGz SlGQzWQdDhT6hmW8G4/4Kd9BQswwJNoHjru5P7MtO4Rp3do6898c0DI7Gbcl9AYQ KT3ncXcfvgWaI2XVQ9Sw5l9P6yjeHGI0PrLqiX7uM+KyJ8U1UPH18Go+IKppDX9j Siit855gxEI3eTBhdR7zVRXTGKFt5OYJAueWs83Oo5+xkiLPHoV/QXb9OVVK72cW RpNxFFM16DwqbzYWU0c6j7N8dMTVCgaMDlPjCMUbu+kr5CV1WfUTuygYx0HMxwT8 9JKr7ktEVNKshD3v65k2T0pOQU1xAljLljyVHe78j4pM1Wg2CLU= =Xma3 -----END PGP SIGNATURE----- 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
This commit is contained in:
Коммит
ea49c88f40
|
@ -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)
|
||||
rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
if (rc != 0) {
|
||||
pr_debug("XCOPY: skip non-matching: %*ph\n",
|
||||
XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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,
|
||||
|
@ -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("putting src lun_ref for %p\n", 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);
|
||||
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче