Message ID | 20210209072202.41154-3-a.miloserdov@yadro.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 14d24e2cc77411301e906a8cf41884739de192de |
Headers | show |
Series | Fix target not properly truncating command data length | expand |
On 09.02.21 08:22, Aleksandr Miloserdov wrote: > TCM buffer length doesn't necessarily equal 8 + ADDITIONAL LENGTH which > might be considered an underflow in case of Data-In size being greater than > 8 + ADDITIONAL LENGTH. So truncate buffer length to prevent underflow. > > Signed-off-by: Aleksandr Miloserdov <a.miloserdov@yadro.com> > Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com> > --- > drivers/target/target_core_pr.c | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c > index 14db5e568f22..a13140e95b47 100644 > --- a/drivers/target/target_core_pr.c > +++ b/drivers/target/target_core_pr.c > @@ -3739,6 +3739,7 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd) > spin_unlock(&dev->t10_pr.registration_lock); > > put_unaligned_be32(add_len, &buf[4]); > + target_set_cmd_data_length(cmd, 8 + add_len); > > transport_kunmap_data_sg(cmd); > > @@ -3757,7 +3758,7 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) > struct t10_pr_registration *pr_reg; > unsigned char *buf; > u64 pr_res_key; > - u32 add_len = 16; /* Hardcoded to 16 when a reservation is held. */ > + u32 add_len = 0; > > if (cmd->data_length < 8) { > pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" > @@ -3775,8 +3776,9 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) > pr_reg = dev->dev_pr_res_holder; > if (pr_reg) { > /* > - * Set the hardcoded Additional Length > + * Set the Additional Length to 16 when a reservation is held > */ > + add_len = 16; > put_unaligned_be32(add_len, &buf[4]); > > if (cmd->data_length < 22) > @@ -3812,6 +3814,8 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) > (pr_reg->pr_res_type & 0x0f); > } > > + target_set_cmd_data_length(cmd, 8 + add_len); > + > err: > spin_unlock(&dev->dev_reservation_lock); > transport_kunmap_data_sg(cmd); > @@ -3830,7 +3834,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) > struct se_device *dev = cmd->se_dev; > struct t10_reservation *pr_tmpl = &dev->t10_pr; > unsigned char *buf; > - u16 add_len = 8; /* Hardcoded to 8. */ > + u16 len = 8; /* Hardcoded to 8. */ > > if (cmd->data_length < 6) { > pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" > @@ -3842,7 +3846,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) > if (!buf) > return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; > > - put_unaligned_be16(add_len, &buf[0]); > + put_unaligned_be16(len, &buf[0]); > buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */ > buf[2] |= 0x08; /* SIP_C: Specify Initiator Ports Capable bit */ > buf[2] |= 0x04; /* ATP_C: All Target Ports Capable bit */ > @@ -3871,6 +3875,8 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) > buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ > buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ > > + target_set_cmd_data_length(cmd, len); > + > transport_kunmap_data_sg(cmd); > > return 0; > @@ -4031,6 +4037,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) > * Set ADDITIONAL_LENGTH > */ > put_unaligned_be32(add_len, &buf[4]); > + target_set_cmd_data_length(cmd, 8 + add_len); > > transport_kunmap_data_sg(cmd); > > Looks ok to me. Reviewed-by: Bodo Stroesser <bostroesser@gmail.com>
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 14db5e568f22..a13140e95b47 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3739,6 +3739,7 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd) spin_unlock(&dev->t10_pr.registration_lock); put_unaligned_be32(add_len, &buf[4]); + target_set_cmd_data_length(cmd, 8 + add_len); transport_kunmap_data_sg(cmd); @@ -3757,7 +3758,7 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) struct t10_pr_registration *pr_reg; unsigned char *buf; u64 pr_res_key; - u32 add_len = 16; /* Hardcoded to 16 when a reservation is held. */ + u32 add_len = 0; if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" @@ -3775,8 +3776,9 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) pr_reg = dev->dev_pr_res_holder; if (pr_reg) { /* - * Set the hardcoded Additional Length + * Set the Additional Length to 16 when a reservation is held */ + add_len = 16; put_unaligned_be32(add_len, &buf[4]); if (cmd->data_length < 22) @@ -3812,6 +3814,8 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) (pr_reg->pr_res_type & 0x0f); } + target_set_cmd_data_length(cmd, 8 + add_len); + err: spin_unlock(&dev->dev_reservation_lock); transport_kunmap_data_sg(cmd); @@ -3830,7 +3834,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; - u16 add_len = 8; /* Hardcoded to 8. */ + u16 len = 8; /* Hardcoded to 8. */ if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" @@ -3842,7 +3846,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - put_unaligned_be16(add_len, &buf[0]); + put_unaligned_be16(len, &buf[0]); buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */ buf[2] |= 0x08; /* SIP_C: Specify Initiator Ports Capable bit */ buf[2] |= 0x04; /* ATP_C: All Target Ports Capable bit */ @@ -3871,6 +3875,8 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ + target_set_cmd_data_length(cmd, len); + transport_kunmap_data_sg(cmd); return 0; @@ -4031,6 +4037,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) * Set ADDITIONAL_LENGTH */ put_unaligned_be32(add_len, &buf[4]); + target_set_cmd_data_length(cmd, 8 + add_len); transport_kunmap_data_sg(cmd);