Skip to content

Commit 2896c93

Browse files
ddissmartinkpetersen
authored andcommitted
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: cbf031f ("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>
1 parent e71ba94 commit 2896c93

File tree

2 files changed

+71
-49
lines changed

2 files changed

+71
-49
lines changed

Diff for: drivers/target/target_core_xcopy.c

+70-49
Original file line numberDiff line numberDiff line change
@@ -46,60 +46,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
4646
return 0;
4747
}
4848

49-
struct xcopy_dev_search_info {
50-
const unsigned char *dev_wwn;
51-
struct se_device *found_dev;
52-
};
53-
49+
/**
50+
* target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
51+
*
52+
* @se_dev: device being considered for match
53+
* @dev_wwn: XCOPY requested NAA dev_wwn
54+
* @return: 1 on match, 0 on no-match
55+
*/
5456
static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev,
55-
void *data)
57+
const unsigned char *dev_wwn)
5658
{
57-
struct xcopy_dev_search_info *info = data;
5859
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
5960
int rc;
6061

61-
if (!se_dev->dev_attrib.emulate_3pc)
62+
if (!se_dev->dev_attrib.emulate_3pc) {
63+
pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev);
6264
return 0;
65+
}
6366

6467
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
6568
target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
6669

67-
rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
68-
if (rc != 0)
69-
return 0;
70-
71-
info->found_dev = se_dev;
72-
pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
73-
74-
rc = target_depend_item(&se_dev->dev_group.cg_item);
70+
rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
7571
if (rc != 0) {
76-
pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n",
77-
rc, se_dev);
78-
return rc;
72+
pr_debug("XCOPY: skip non-matching: %*ph\n",
73+
XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
74+
return 0;
7975
}
76+
pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
8077

81-
pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n",
82-
se_dev, &se_dev->dev_group);
8378
return 1;
8479
}
8580

86-
static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
87-
struct se_device **found_dev)
81+
static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
82+
const unsigned char *dev_wwn,
83+
struct se_device **_found_dev,
84+
struct percpu_ref **_found_lun_ref)
8885
{
89-
struct xcopy_dev_search_info info;
90-
int ret;
91-
92-
memset(&info, 0, sizeof(info));
93-
info.dev_wwn = dev_wwn;
94-
95-
ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info);
96-
if (ret == 1) {
97-
*found_dev = info.found_dev;
98-
return 0;
99-
} else {
100-
pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
101-
return -EINVAL;
86+
struct se_dev_entry *deve;
87+
struct se_node_acl *nacl;
88+
struct se_lun *this_lun = NULL;
89+
struct se_device *found_dev = NULL;
90+
91+
/* cmd with NULL sess indicates no associated $FABRIC_MOD */
92+
if (!sess)
93+
goto err_out;
94+
95+
pr_debug("XCOPY 0xe4: searching for: %*ph\n",
96+
XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
97+
98+
nacl = sess->se_node_acl;
99+
rcu_read_lock();
100+
hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
101+
struct se_device *this_dev;
102+
int rc;
103+
104+
this_lun = rcu_dereference(deve->se_lun);
105+
this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
106+
107+
rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn);
108+
if (rc) {
109+
if (percpu_ref_tryget_live(&this_lun->lun_ref))
110+
found_dev = this_dev;
111+
break;
112+
}
102113
}
114+
rcu_read_unlock();
115+
if (found_dev == NULL)
116+
goto err_out;
117+
118+
pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n",
119+
found_dev, &found_dev->dev_group);
120+
*_found_dev = found_dev;
121+
*_found_lun_ref = &this_lun->lun_ref;
122+
return 0;
123+
err_out:
124+
pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
125+
return -EINVAL;
103126
}
104127

105128
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,
246269

247270
switch (xop->op_origin) {
248271
case XCOL_SOURCE_RECV_OP:
249-
rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
250-
&xop->dst_dev);
272+
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
273+
xop->dst_tid_wwn,
274+
&xop->dst_dev,
275+
&xop->remote_lun_ref);
251276
break;
252277
case XCOL_DEST_RECV_OP:
253-
rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
254-
&xop->src_dev);
278+
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
279+
xop->src_tid_wwn,
280+
&xop->src_dev,
281+
&xop->remote_lun_ref);
255282
break;
256283
default:
257284
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)
391418

392419
static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
393420
{
394-
struct se_device *remote_dev;
395-
396421
if (xop->op_origin == XCOL_SOURCE_RECV_OP)
397-
remote_dev = xop->dst_dev;
422+
pr_debug("putting dst lun_ref for %p\n", xop->dst_dev);
398423
else
399-
remote_dev = xop->src_dev;
400-
401-
pr_debug("Calling configfs_undepend_item for"
402-
" remote_dev: %p remote_dev->dev_group: %p\n",
403-
remote_dev, &remote_dev->dev_group.cg_item);
424+
pr_debug("putting src lun_ref for %p\n", xop->src_dev);
404425

405-
target_undepend_item(&remote_dev->dev_group.cg_item);
426+
percpu_ref_put(xop->remote_lun_ref);
406427
}
407428

408429
static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)

Diff for: drivers/target/target_core_xcopy.h

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct xcopy_op {
2727
struct se_device *dst_dev;
2828
unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
2929
unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
30+
struct percpu_ref *remote_lun_ref;
3031

3132
sector_t src_lba;
3233
sector_t dst_lba;

0 commit comments

Comments
 (0)