1
0
mirror of https://github.com/projectacrn/acrn-hypervisor.git synced 2025-05-01 21:23:59 +00:00

dm: fix uninitialized heap access risk in virtio GPU

This patch fix potential uninitialized heap use in virtio_gpu.c file.

Tracked-On: 
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
This commit is contained in:
Jiaqing Zhao 2023-07-05 02:41:59 +00:00 committed by acrnsi-robot
parent ac8690cd4d
commit b35b8ef677

View File

@ -785,8 +785,23 @@ virtio_gpu_cmd_resource_attach_backing(struct virtio_gpu_command *cmd)
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
memset(&resp, 0, sizeof(resp));
/*
* 1. Per VIRTIO GPU specification,
* 'cmd->iovcnt' = 'nr_entries' of 'struct virtio_gpu_resource_attach_backing' + 2,
* where 'nr_entries' is number of instance of 'struct virtio_gpu_mem_entry'.
* case 'cmd->iovcnt < 3' means above 'nr_entries' is zero, which is invalid
* and ignored.
* 2. Function 'virtio_gpu_ctrl_bh(void *data)' guarantees cmd->iovcnt >=1.
*/
if (cmd->iovcnt < 2) {
resp.type = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
pr_err("%s : invalid memory entry.\n", __func__);
return;
}
r2d = virtio_gpu_find_resource_2d(cmd->gpu, req.resource_id);
if (r2d) {
if (r2d && req.nr_entries > 0) {
iov = malloc(req.nr_entries * sizeof(struct iovec));
if (!iov) {
resp.type = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
@ -1198,6 +1213,19 @@ virtio_gpu_cmd_create_blob(struct virtio_gpu_command *cmd)
return;
}
/*
* 1. Per VIRTIO GPU specification,
* 'cmd->iovcnt' = 'nr_entries' of 'struct virtio_gpu_resource_create_blob' + 2,
* where 'nr_entries' is number of instance of 'struct virtio_gpu_mem_entry'.
* 2. Function 'virtio_gpu_ctrl_bh(void *data)' guarantees cmd->iovcnt >=1.
*/
if (cmd->iovcnt < 2) {
resp.type = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
pr_err("%s : invalid memory entry.\n", __func__);
return;
}
if ((req.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST) ||
(req.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE)) {
pr_dbg("%s : invalid create_blob parameter for %d.\n",
@ -1227,62 +1255,64 @@ virtio_gpu_cmd_create_blob(struct virtio_gpu_command *cmd)
r2d->resource_id = req.resource_id;
entries = malloc(req.nr_entries * sizeof(struct virtio_gpu_mem_entry));
if (!entries) {
pr_err("%s : memory allocation for entries failed.\n", __func__);
free(r2d);
resp.type = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
pbuf = (uint8_t *)entries;
for (i = 1; i < (cmd->iovcnt - 1); i++) {
memcpy(pbuf, cmd->iov[i].iov_base, cmd->iov[i].iov_len);
pbuf += cmd->iov[i].iov_len;
}
if (req.size > CURSOR_BLOB_SIZE) {
/* Try to create the dma buf */
r2d->dma_info = virtio_gpu_create_udmabuf(cmd->gpu,
entries,
req.nr_entries);
if (r2d->dma_info == NULL) {
free(entries);
resp.type = VIRTIO_GPU_RESP_ERR_UNSPEC;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
r2d->blob = true;
} else {
/* Cursor resource with 64x64 and PIXMAN_a8r8g8b8 format.
* Or when it fails to create dmabuf
*/
r2d->width = 64;
r2d->height = 64;
r2d->format = PIXMAN_a8r8g8b8;
r2d->image = pixman_image_create_bits(
r2d->format, r2d->width, r2d->height, NULL, 0);
iov = malloc(req.nr_entries * sizeof(struct iovec));
if (!iov) {
free(entries);
if (req.nr_entries > 0) {
entries = malloc(req.nr_entries * sizeof(struct virtio_gpu_mem_entry));
if (!entries) {
pr_err("%s : memory allocation for entries failed.\n", __func__);
free(r2d);
resp.type = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
r2d->iov = iov;
r2d->iovcnt = req.nr_entries;
for (i = 0; i < req.nr_entries; i++) {
r2d->iov[i].iov_base = paddr_guest2host(
cmd->gpu->base.dev->vmctx,
entries[i].addr,
entries[i].length);
r2d->iov[i].iov_len = entries[i].length;
pbuf = (uint8_t *)entries;
for (i = 1; i < (cmd->iovcnt - 1); i++) {
memcpy(pbuf, cmd->iov[i].iov_base, cmd->iov[i].iov_len);
pbuf += cmd->iov[i].iov_len;
}
}
if (req.size > CURSOR_BLOB_SIZE) {
/* Try to create the dma buf */
r2d->dma_info = virtio_gpu_create_udmabuf(cmd->gpu,
entries,
req.nr_entries);
if (r2d->dma_info == NULL) {
free(entries);
resp.type = VIRTIO_GPU_RESP_ERR_UNSPEC;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
r2d->blob = true;
} else {
/* Cursor resource with 64x64 and PIXMAN_a8r8g8b8 format.
* Or when it fails to create dmabuf
*/
r2d->width = 64;
r2d->height = 64;
r2d->format = PIXMAN_a8r8g8b8;
r2d->image = pixman_image_create_bits(
r2d->format, r2d->width, r2d->height, NULL, 0);
free(entries);
iov = malloc(req.nr_entries * sizeof(struct iovec));
if (!iov) {
free(entries);
free(r2d);
resp.type = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
r2d->iov = iov;
r2d->iovcnt = req.nr_entries;
for (i = 0; i < req.nr_entries; i++) {
r2d->iov[i].iov_base = paddr_guest2host(
cmd->gpu->base.dev->vmctx,
entries[i].addr,
entries[i].length);
r2d->iov[i].iov_len = entries[i].length;
}
}
free(entries);
}
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
LIST_INSERT_HEAD(&cmd->gpu->r2d_list, r2d, link);
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));