Message ID | 20210209072202.41154-1-a.miloserdov@yadro.com |
---|---|
Headers | show |
Series | Fix target not properly truncating command data length | expand |
On 09.02.21 08:22, Aleksandr Miloserdov wrote: > TCM doesn't properly handle underflow case for service actions. One way to > prevent it is to always complete command with > target_complete_cmd_with_length, however it requires access to data_sg, > which is not always available. > > This change introduces target_set_cmd_data_length function which allows to > set command data length before completing it. > > Signed-off-by: Aleksandr Miloserdov <a.miloserdov@yadro.com> > Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com> > --- > drivers/target/target_core_transport.c | 15 +++++++++++---- > include/target/target_core_backend.h | 1 + > 2 files changed, 12 insertions(+), 4 deletions(-) > > diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c > index fca4bd079d02..c98540355512 100644 > --- a/drivers/target/target_core_transport.c > +++ b/drivers/target/target_core_transport.c > @@ -879,11 +879,9 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) > } > EXPORT_SYMBOL(target_complete_cmd); > > -void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) > +void target_set_cmd_data_length(struct se_cmd *cmd, int length) > { > - if ((scsi_status == SAM_STAT_GOOD || > - cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) && > - length < cmd->data_length) { > + if (length < cmd->data_length) { > if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { > cmd->residual_count += cmd->data_length - length; > } else { > @@ -893,6 +891,15 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len > > cmd->data_length = length; > } > +} > +EXPORT_SYMBOL(target_set_cmd_data_length); > + > +void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) > +{ > + if (scsi_status == SAM_STAT_GOOD || > + cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) { > + target_set_cmd_data_length(cmd, length); > + } > > target_complete_cmd(cmd, scsi_status); > } > diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h > index 6336780d83a7..ce2fba49c95d 100644 > --- a/include/target/target_core_backend.h > +++ b/include/target/target_core_backend.h > @@ -72,6 +72,7 @@ int transport_backend_register(const struct target_backend_ops *); > void target_backend_unregister(const struct target_backend_ops *); > > void target_complete_cmd(struct se_cmd *, u8); > +void target_set_cmd_data_length(struct se_cmd *, int); > void target_complete_cmd_with_length(struct se_cmd *, u8, int); > > void transport_copy_sense_to_cmd(struct se_cmd *, unsigned char *); > Looks ok to me. Reviewed-by: Bodo Stroesser <bostroesser@gmail.com>
Aleksandr, > SPC-5 (4.2.5.6 Allocation length) requires to terminate transfers to > the Data In Buffer when the number of bytes or blocks specified by the > ALLOCATION LENGTH field have been transferred or when all available > data have been transferred, whichever is less. > > PERSISTENT RESERVE IN service actions in TCM don't follow the clause > and return ALLOCATION LENGTH of data, even if actual number of data in > reply is less (e.g. there are no reservation keys). > > That causes an underflow and a failure in libiscsi PrinReadKeys.Simple > that expects Data In Buffer size equal to ADDITIONAL LENGTH + 8. Applied to 5.12/scsi-staging, thanks! -- Martin K. Petersen Oracle Linux Engineering
On Tue, 9 Feb 2021 10:22:00 +0300, Aleksandr Miloserdov wrote: > SPC-5 (4.2.5.6 Allocation length) requires to terminate transfers to the > Data In Buffer when the number of bytes or blocks specified by the > ALLOCATION LENGTH field have been transferred or when all available data > have been transferred, whichever is less. > > PERSISTENT RESERVE IN service actions in TCM don't follow the clause and > return ALLOCATION LENGTH of data, even if actual number of data in reply > is less (e.g. there are no reservation keys). > > [...] Applied to 5.12/scsi-queue, thanks! [1/2] scsi: target: core: Add cmd length set before cmd complete https://git.kernel.org/mkp/scsi/c/1c73e0c5e54d [2/2] scsi: target: core: Prevent underflow for service actions https://git.kernel.org/mkp/scsi/c/14d24e2cc774 -- Martin K. Petersen Oracle Linux Engineering