Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4594bb5 authored by Paolo Bonzini's avatar Paolo Bonzini Committed by James Bottomley
Browse files

[SCSI] virtio_scsi: fix TMF use-after-free



Fix a use-after-free in the TMF path, where cmd may have been already
freed by virtscsi_complete_free when wait_for_completion restarts
executing virtscsi_tmf.  Technically a race, but in practice the command
will always be freed long before the completion waiter is awoken.

The fix is to make callers specifying a completion responsible for
freeing the command in all cases.

Signed-off-by: default avatarHu Tao <hutao@cn.fujitsu.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 3c8d9a95
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ static void virtscsi_complete_free(void *buf)

	if (cmd->comp)
		complete_all(cmd->comp);
	else
		mempool_free(cmd, virtscsi_cmd_pool);
}

@@ -311,21 +312,22 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
{
	DECLARE_COMPLETION_ONSTACK(comp);
	int ret;
	int ret = FAILED;

	cmd->comp = &comp;
	ret = virtscsi_kick_cmd(vscsi, vscsi->ctrl_vq, cmd,
	if (virtscsi_kick_cmd(vscsi, vscsi->ctrl_vq, cmd,
			      sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
			       GFP_NOIO);
	if (ret < 0)
		return FAILED;
			      GFP_NOIO) < 0)
		goto out;

	wait_for_completion(&comp);
	if (cmd->resp.tmf.response != VIRTIO_SCSI_S_OK &&
	    cmd->resp.tmf.response != VIRTIO_SCSI_S_FUNCTION_SUCCEEDED)
		return FAILED;
	if (cmd->resp.tmf.response == VIRTIO_SCSI_S_OK ||
	    cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED)
		ret = SUCCESS;

	return SUCCESS;
out:
	mempool_free(cmd, virtscsi_cmd_pool);
	return ret;
}

static int virtscsi_device_reset(struct scsi_cmnd *sc)