test-tool, xcopy: Fix target descriptor handling

Fail the XCOPY tests if no appropriate target descriptor is available
instead of causing memory corruption or truncating the descriptor.
This commit is contained in:
Bart Van Assche
2021-09-05 18:15:04 -07:00
parent aa214feaf3
commit b781b21d50
9 changed files with 145 additions and 42 deletions

View File

@@ -2906,7 +2906,11 @@ int get_desc_len(enum ec_descr_type_code desc_type)
return desc_len;
}
void populate_ident_tgt_desc(unsigned char *buf, struct scsi_device *dev)
/*
* Populate a 24 byte SCSI designator. See also Table 529 — Designation
* descriptor in SPC-6.
*/
static int populate_ident_tgt_desc(uint8_t buf[24], struct scsi_device *dev)
{
int ret;
struct scsi_task *inq_di_task = NULL;
@@ -2914,15 +2918,19 @@ void populate_ident_tgt_desc(unsigned char *buf, struct scsi_device *dev)
struct scsi_inquiry_device_designator *desig, *tgt_desig = NULL;
enum scsi_designator_type prev_type = 0;
ret = inquiry(dev, &inq_di_task, 1, SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255, EXPECT_STATUS_GOOD);
ret = inquiry(dev, &inq_di_task, 1,
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255,
EXPECT_STATUS_GOOD);
if (ret < 0 || inq_di_task == NULL) {
logging(LOG_NORMAL, "Failed to read Device Identification page");
goto finished;
logging(LOG_NORMAL,
"Failed to read Device Identification page");
goto err;
} else {
inq_di = scsi_datain_unmarshall(inq_di_task);
if (inq_di == NULL) {
logging(LOG_NORMAL, "Failed to unmarshall inquiry datain blob");
goto finished;
logging(LOG_NORMAL,
"Failed to unmarshall inquiry datain blob");
goto err;
}
}
@@ -2932,7 +2940,8 @@ void populate_ident_tgt_desc(unsigned char *buf, struct scsi_device *dev)
case SCSI_DESIGNATOR_TYPE_T10_VENDORT_ID:
case SCSI_DESIGNATOR_TYPE_EUI_64:
case SCSI_DESIGNATOR_TYPE_NAA:
if (prev_type <= desig->designator_type) {
if (prev_type <= desig->designator_type &&
desig->designator_length <= 20) {
tgt_desig = desig;
prev_type = desig->designator_type;
}
@@ -2942,31 +2951,47 @@ void populate_ident_tgt_desc(unsigned char *buf, struct scsi_device *dev)
}
}
if (tgt_desig == NULL) {
logging(LOG_NORMAL, "No suitalble target descriptor format found");
goto finished;
logging(LOG_NORMAL,
"No suitable target descriptor found");
goto err;
}
memset(buf, 0, 24);
buf[0] = tgt_desig->code_set;
buf[1] = (tgt_desig->designator_type & 0xF) | ((tgt_desig->association & 3) << 4);
buf[1] = (tgt_desig->designator_type & 0xF) |
((tgt_desig->association & 3) << 4);
buf[3] = tgt_desig->designator_length;
memcpy(buf + 4, tgt_desig->designator, tgt_desig->designator_length);
finished:
scsi_free_scsi_task(inq_di_task);
return 0;
err:
scsi_free_scsi_task(inq_di_task);
return -1;
}
int populate_tgt_desc(unsigned char *desc, enum ec_descr_type_code desc_type, int luid_type, int nul, int peripheral_type, uint16_t rel_init_port_id, int pad, struct scsi_device *dev)
int populate_tgt_desc(uint8_t desc[32], enum ec_descr_type_code desc_type,
int luid_type, int nul, int peripheral_type,
uint16_t rel_init_port_id, int pad,
struct scsi_device *dev)
{
assert(desc_type < 256);
assert(luid_type < 4);
assert(nul < 2);
assert(peripheral_type < 32);
desc[0] = desc_type;
desc[1] = (luid_type << 6) | (nul << 5) | peripheral_type;
scsi_set_uint16(&desc[2], rel_init_port_id);
if (desc_type == IDENT_DESCR_TGT_DESCR)
populate_ident_tgt_desc(desc+4, dev);
if (desc_type == IDENT_DESCR_TGT_DESCR &&
populate_ident_tgt_desc(desc + 4, dev) < 0)
return -1;
if (peripheral_type == 0) {
// Issue readcapacity for each sd if testing with different LUs
// If single LU, use block_size from prior readcapacity involcation
// Issue read capacity for each sd if testing with different LUs
// If single LU, use block_size from prior readcapacity
// invocation.
desc[28] = pad << 2;
desc[29] = (block_size >> 16) & 0xFF;
desc[30] = (block_size >> 8) & 0xFF;

View File

@@ -915,7 +915,10 @@ int clear_swp(struct scsi_device *sdev);
int extendedcopy(struct scsi_device *sdev, struct iscsi_data *data, int status, enum scsi_sense_key key, int *ascq, int num_ascq);
int get_desc_len(enum ec_descr_type_code desc_type);
int populate_tgt_desc(unsigned char *desc, enum ec_descr_type_code desc_type, int luid_type, int nul, int peripheral_type, uint16_t rel_init_port_id, int pad, struct scsi_device *dev);
int populate_tgt_desc(uint8_t desc[32], enum ec_descr_type_code desc_type,
int luid_type, int nul, int peripheral_type,
uint16_t rel_init_port_id, int pad,
struct scsi_device *dev);
int populate_seg_desc_hdr(unsigned char *hdr, enum ec_descr_type_code desc_type, int dc, int cat, uint16_t src_index, uint16_t dst_index);
int populate_seg_desc_b2b(unsigned char *desc, int dc, int cat, int src_index, int dst_index, uint16_t num_blks, uint64_t src_lba, uint64_t dst_lba);
int populate_seg_desc_b2b_off(unsigned char *desc, int cat, int src_index,

View File

@@ -30,13 +30,17 @@
int init_xcopy_descr(unsigned char *buf, int offset, int num_tgt_desc,
int num_seg_desc, int *tgt_desc_len, int *seg_desc_len)
{
int i;
int i, len;
/* Initialize target descriptor list with num_tgt_desc
* target descriptor */
for (i = 0; i < num_tgt_desc; i++)
offset += populate_tgt_desc(buf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
for (i = 0; i < num_tgt_desc; i++) {
len = populate_tgt_desc(buf + offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0)
return -1;
offset += len;
}
*tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Initialize segment descriptor list with num_seg_desc
@@ -56,7 +60,7 @@ test_extendedcopy_descr_limits(void)
struct iscsi_data data;
unsigned char *xcopybuf;
struct scsi_copy_results_op_params *opp = NULL;
int tgt_desc_len = 0, seg_desc_len = 0, seg_desc_count;
int tgt_desc_len = 0, seg_desc_len = 0, seg_desc_count, len;
unsigned int alloc_len;
logging(LOG_VERBOSE, LOG_BLANK_LINE);
@@ -88,9 +92,14 @@ test_extendedcopy_descr_limits(void)
logging(LOG_VERBOSE,
"Test sending more than supported target descriptors");
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
len = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
(opp->max_target_desc_count+1), 1,
&tgt_desc_len, &seg_desc_len);
if (len < 0) {
CU_FAIL("Populating XCOPY descriptor failed");
return;
}
data.size = len;
populate_param_header(xcopybuf, 1, 0, 0, 0,
tgt_desc_len, seg_desc_len, 0);
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
@@ -98,9 +107,14 @@ test_extendedcopy_descr_limits(void)
logging(LOG_VERBOSE,
"Test sending more than supported segment descriptors");
memset(xcopybuf, 0, alloc_len);
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET, 1,
len = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET, 1,
(opp->max_segment_desc_count+1),
&tgt_desc_len, &seg_desc_len);
if (len < 0) {
CU_FAIL("Populating XCOPY descriptor failed");
return;
}
data.size = len;
populate_param_header(xcopybuf, 2, 0, 0, 0,
tgt_desc_len, seg_desc_len, 0);
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
@@ -113,10 +127,15 @@ test_extendedcopy_descr_limits(void)
/* Overfill remaining max_desc_list_length with segment descriptors */
seg_desc_len = alloc_len - XCOPY_DESC_OFFSET - tgt_desc_len;
seg_desc_count = seg_desc_len / get_desc_len(BLK_TO_BLK_SEG_DESCR);
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
len = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
(opp->max_target_desc_count+1),
seg_desc_count,
&tgt_desc_len, &seg_desc_len);
if (len < 0) {
CU_FAIL("Populating XCOPY descriptor failed");
return;
}
data.size = len;
populate_param_header(xcopybuf, 3, 0, 0, 0,
tgt_desc_len, seg_desc_len, 0);
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);

View File

@@ -33,6 +33,8 @@ int init_xcopybuf(unsigned char *buf, int tgt_desc_type, int seg_desc_type,
offset += populate_tgt_desc(buf+offset, tgt_desc_type, LU_ID_TYPE_LUN,
0, 0, 0, 0, sd);
if (offset < 0)
return -1;
*tgt_desc_len = offset - XCOPY_DESC_OFFSET;
if (seg_desc_type == BLK_TO_BLK_SEG_DESCR)
offset += populate_seg_desc_b2b(buf+offset, 0, 0, 0, 0, 2048, 0,
@@ -48,7 +50,7 @@ int init_xcopybuf(unsigned char *buf, int tgt_desc_type, int seg_desc_type,
void
test_extendedcopy_descr_type(void)
{
int tgt_desc_len = 0, seg_desc_len = 0, alloc_len;
int tgt_desc_len = 0, seg_desc_len = 0, alloc_len, len;
struct iscsi_data data;
unsigned char *xcopybuf;
@@ -67,8 +69,13 @@ test_extendedcopy_descr_type(void)
logging(LOG_VERBOSE,
"Send Fibre Channel N_Port_Name target descriptor");
data.size = init_xcopybuf(xcopybuf, 0xE0, BLK_TO_BLK_SEG_DESCR,
len = init_xcopybuf(xcopybuf, 0xE0, BLK_TO_BLK_SEG_DESCR,
&tgt_desc_len, &seg_desc_len);
if (len < 0) {
CU_FAIL("Populating XCOPY descriptor failed");
return;
}
data.size = len;
populate_param_header(xcopybuf, 1, 0, 0, 0,
tgt_desc_len, seg_desc_len, 0);
@@ -76,9 +83,14 @@ test_extendedcopy_descr_type(void)
logging(LOG_VERBOSE, "Send Stream-to-Stream Copy segment descriptor");
memset(xcopybuf, 0, alloc_len);
data.size = init_xcopybuf(xcopybuf, IDENT_DESCR_TGT_DESCR,
len = init_xcopybuf(xcopybuf, IDENT_DESCR_TGT_DESCR,
STRM_TO_STRM_SEG_DESCR,
&tgt_desc_len, &seg_desc_len);
if (len < 0) {
CU_FAIL("Populating XCOPY descriptor failed");
return;
}
data.size = len;
populate_param_header(xcopybuf, 1, 0, 0, 0,
tgt_desc_len, seg_desc_len, 0);

View File

@@ -29,7 +29,7 @@
void
test_extendedcopy_param(void)
{
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET, len;
struct iscsi_data data;
unsigned char *xcopybuf;
@@ -45,8 +45,14 @@ test_extendedcopy_param(void)
xcopybuf = data.data;
memset(xcopybuf, 0, data.size);
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,

View File

@@ -29,7 +29,7 @@
void
test_extendedcopy_simple(void)
{
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET, len;
struct iscsi_data data;
unsigned char *xcopybuf;
unsigned int copied_blocks;
@@ -69,8 +69,13 @@ test_extendedcopy_simple(void)
memset(xcopybuf, 0, data.size);
/* Initialize target descriptor list with one target descriptor */
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
goto free;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Initialize segment descriptor list with one segment descriptor */
@@ -94,6 +99,7 @@ test_extendedcopy_simple(void)
CU_FAIL("Blocks were not copied correctly");
}
free:
free(buf1);
free(buf2);
}
@@ -107,6 +113,7 @@ test_extendedcopy_large(void)
struct scsi_copy_results_op_params *opp = NULL;
uint32_t cp_len_bytes = 0;
int i, tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
int len;
struct iscsi_data data;
unsigned char *xcopybuf;
unsigned int write_blocks;
@@ -174,8 +181,13 @@ test_extendedcopy_large(void)
memset(xcopybuf, 0, data.size);
/* Initialize target descriptor list with one target descriptor */
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
goto free;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Initialize segment descriptor list with one segment descriptor */
@@ -199,6 +211,7 @@ test_extendedcopy_large(void)
CU_FAIL("Blocks were not copied correctly");
}
free:
free(buf1);
free(buf2);
}

View File

@@ -29,7 +29,7 @@
void
test_extendedcopy_validate_seg_descr(void)
{
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET, len;
struct iscsi_data data;
unsigned char *xcopybuf;
@@ -46,8 +46,13 @@ test_extendedcopy_validate_seg_descr(void)
memset(xcopybuf, 0, data.size);
logging(LOG_VERBOSE, "Send invalid target descriptor index");
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Inaccessible DESTINATION TARGET DESCRIPTOR INDEX */
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 1,
@@ -62,8 +67,13 @@ test_extendedcopy_validate_seg_descr(void)
"Number of copy blocks beyond destination block device capacity");
memset(xcopybuf, 0, data.size);
offset = XCOPY_DESC_OFFSET;
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Beyond EOL */
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,

View File

@@ -29,7 +29,7 @@
void
test_extendedcopy_validate_tgt_descr(void)
{
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET, len;
int ret;
struct scsi_inquiry_standard *std_inq;
struct iscsi_data data;
@@ -55,8 +55,13 @@ test_extendedcopy_validate_tgt_descr(void)
logging(LOG_VERBOSE, "Unsupported LU_ID TYPE");
/* Unsupported LU ID TYPE */
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_RSVD, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
2048, 0, num_blocks - 2048);
@@ -81,8 +86,13 @@ test_extendedcopy_validate_tgt_descr(void)
/* NUL bit */
memset(xcopybuf, 0, data.size);
offset = XCOPY_DESC_OFFSET;
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 1, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
2048, 0, num_blocks - 2048);

View File

@@ -33,7 +33,7 @@ test_receive_copy_results_copy_status(void)
struct scsi_task *cs_task = NULL;
struct scsi_copy_results_copy_status *csp;
int tgt_desc_len = 0, seg_desc_len = 0;
int offset = XCOPY_DESC_OFFSET, list_id = 1;
int offset = XCOPY_DESC_OFFSET, len, list_id = 1;
struct iscsi_data data;
unsigned char *xcopybuf;
struct scsi_inquiry_supported_pages *sup_inq;
@@ -148,8 +148,13 @@ test_receive_copy_results_copy_status(void)
memset(xcopybuf, 0, data.size);
/* Initialize target descriptor list with one target descriptor */
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
len = populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
if (len < 0) {
CU_FAIL("Populating target descriptor failed");
return;
}
offset += len;
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
/* Initialize segment descriptor list with one segment descriptor */