Skip to content

Commit efb2ea7

Browse files
author
Nicholas Bellinger
committed
iscsi-target: Fix TMR reference leak during session shutdown
This patch fixes a iscsi-target specific TMR reference leak during session shutdown, that could occur when a TMR was quiesced before the hand-off back to iscsi-target code via transport_cmd_check_stop_to_fabric(). The reference leak happens because iscsit_free_cmd() was incorrectly skipping the final target_put_sess_cmd() for TMRs when transport_generic_free_cmd() returned zero because the se_cmd->cmd_kref did not reach zero, due to the missing se_cmd assignment in original code. The result was iscsi_cmd and it's associated se_cmd memory would be freed once se_sess->sess_cmd_map where released, but the associated se_tmr_req was leaked and remained part of se_device->dev_tmr_list. This bug would manfiest itself as kernel paging request OOPsen in core_tmr_lun_reset(), when a left-over se_tmr_req attempted to dereference it's se_cmd pointer that had already been released during normal session shutdown. To address this bug, go ahead and treat ISCSI_OP_SCSI_CMD and ISCSI_OP_SCSI_TMFUNC the same when there is an extra se_cmd->cmd_kref to drop in iscsit_free_cmd(), and use op_scsi to signal __iscsit_free_cmd() when the former needs to clear any further iscsi related I/O state. Reported-by: Rob Millner <rlm@daterainc.com> Cc: Rob Millner <rlm@daterainc.com> Reported-by: Chu Yuan Lin <cyl@datera.io> Cc: Chu Yuan Lin <cyl@datera.io> Tested-by: Chu Yuan Lin <cyl@datera.io> Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent afea03f commit efb2ea7

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -737,21 +737,23 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
737737
{
738738
struct se_cmd *se_cmd = NULL;
739739
int rc;
740+
bool op_scsi = false;
740741
/*
741742
* Determine if a struct se_cmd is associated with
742743
* this struct iscsi_cmd.
743744
*/
744745
switch (cmd->iscsi_opcode) {
745746
case ISCSI_OP_SCSI_CMD:
746-
se_cmd = &cmd->se_cmd;
747-
__iscsit_free_cmd(cmd, true, shutdown);
747+
op_scsi = true;
748748
/*
749749
* Fallthrough
750750
*/
751751
case ISCSI_OP_SCSI_TMFUNC:
752-
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
753-
if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
754-
__iscsit_free_cmd(cmd, true, shutdown);
752+
se_cmd = &cmd->se_cmd;
753+
__iscsit_free_cmd(cmd, op_scsi, shutdown);
754+
rc = transport_generic_free_cmd(se_cmd, shutdown);
755+
if (!rc && shutdown && se_cmd->se_sess) {
756+
__iscsit_free_cmd(cmd, op_scsi, shutdown);
755757
target_put_sess_cmd(se_cmd);
756758
}
757759
break;

0 commit comments

Comments
 (0)