summaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorDavid Disseldorp <ddiss@suse.de>2016-12-23 11:37:55 +0100
committerBart Van Assche <bart.vanassche@sandisk.com>2017-01-10 08:40:58 -0800
commitaf9f62c1686268c0517b289274d38f3a03bebd2a (patch)
treebaa0055b782dc4914f95bd38464168f446512553 /drivers/target
parent61c359194c46cbffec9a1f2c59c1c4011222ad84 (diff)
downloadlinux-af9f62c1686268c0517b289274d38f3a03bebd2a.tar.gz
linux-af9f62c1686268c0517b289274d38f3a03bebd2a.tar.xz
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: David Disseldorp <ddiss@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_xcopy.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index db265ad10fa4..da0f2da732e7 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -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,
struct xcopy_op *xop, unsigned char *p,
- unsigned int sdll)
+ unsigned int sdll, sense_reason_t *sense_ret)
{
unsigned char *desc = p;
unsigned int start = 0;
int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
+ *sense_ret = TCM_INVALID_PARAMETER_LIST;
+
if (offset != 0) {
pr_err("XCOPY segment descriptor list length is not"
" multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
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) {
/*
@@ -916,7 +925,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
seg_desc = &p[16];
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) {
xcopy_pt_undepend_remotedev(xop);
goto out;