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

[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
......@@ -175,7 +175,8 @@ static void virtscsi_complete_free(void *buf)
if (cmd->comp)
complete_all(cmd->comp);
mempool_free(cmd, virtscsi_cmd_pool);
else
mempool_free(cmd, virtscsi_cmd_pool);
}
static void virtscsi_ctrl_done(struct virtqueue *vq)
......@@ -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,
sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
GFP_NOIO);
if (ret < 0)
return FAILED;
if (virtscsi_kick_cmd(vscsi, vscsi->ctrl_vq, cmd,
sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment