Commit af9f62c1 authored by David Disseldorp's avatar David Disseldorp Committed by Bart Van Assche

target: bounds check XCOPY segment descriptor list

Check the length of the XCOPY request segment descriptor list against
the value advertised via the MAXIMUM SEGMENT DESCRIPTOR COUNT field in
the RECEIVE COPY OPERATING PARAMETERS response.

spc4r37 6.4.3.5 states:
  If the number of segment descriptors exceeds the allowed number, the
  copy manager shall terminate the command with CHECK CONDITION status,
  with the sense key set to ILLEGAL REQUEST, and the additional sense
  code set to TOO MANY SEGMENT DESCRIPTORS.

This functionality is testable using the libiscsi
ExtendedCopy.DescrLimits test.
Signed-off-by: default avatarDavid Disseldorp <ddiss@suse.de>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
parent 61c35919
...@@ -308,17 +308,26 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op ...@@ -308,17 +308,26 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd, static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
struct xcopy_op *xop, unsigned char *p, struct xcopy_op *xop, unsigned char *p,
unsigned int sdll) unsigned int sdll, sense_reason_t *sense_ret)
{ {
unsigned char *desc = p; unsigned char *desc = p;
unsigned int start = 0; unsigned int start = 0;
int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0; int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
*sense_ret = TCM_INVALID_PARAMETER_LIST;
if (offset != 0) { if (offset != 0) {
pr_err("XCOPY segment descriptor list length is not" pr_err("XCOPY segment descriptor list length is not"
" multiple of %d\n", XCOPY_SEGMENT_DESC_LEN); " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
return -EINVAL; return -EINVAL;
} }
if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
" large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
/* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
*sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
return -EINVAL;
}
while (start < sdll) { while (start < sdll) {
/* /*
...@@ -916,7 +925,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -916,7 +925,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
seg_desc = &p[16]; seg_desc = &p[16];
seg_desc += (rc * XCOPY_TARGET_DESC_LEN); seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll); rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
sdll, &ret);
if (rc <= 0) { if (rc <= 0) {
xcopy_pt_undepend_remotedev(xop); xcopy_pt_undepend_remotedev(xop);
goto out; goto out;
......
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