drm/virtio: Handle context ID allocation errors
It is possible to run out of memory while allocating IDs. The current code would create a context with an invalid ID; change it to return -ENOMEM to userspace. Signed-off-by: Matthew Wilcox <willy@infradead.org> Link: http://patchwork.freedesktop.org/patch/msgid/20180926160031.15721-3-willy@infradead.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
1938d1ae32
commit
6a37c49a94
|
@ -52,31 +52,22 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
|
||||||
events_clear, &events_clear);
|
events_clear, &events_clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_ctx_id_get(struct virtio_gpu_device *vgdev,
|
static int virtio_gpu_context_create(struct virtio_gpu_device *vgdev,
|
||||||
uint32_t *resid)
|
uint32_t nlen, const char *name)
|
||||||
{
|
{
|
||||||
int handle = ida_alloc_min(&vgdev->ctx_id_ida, 1, GFP_KERNEL);
|
int handle = ida_alloc_min(&vgdev->ctx_id_ida, 1, GFP_KERNEL);
|
||||||
*resid = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_gpu_ctx_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
|
if (handle < 0)
|
||||||
{
|
return handle;
|
||||||
ida_free(&vgdev->ctx_id_ida, id);
|
virtio_gpu_cmd_context_create(vgdev, handle, nlen, name);
|
||||||
}
|
return handle;
|
||||||
|
|
||||||
static void virtio_gpu_context_create(struct virtio_gpu_device *vgdev,
|
|
||||||
uint32_t nlen, const char *name,
|
|
||||||
uint32_t *ctx_id)
|
|
||||||
{
|
|
||||||
virtio_gpu_ctx_id_get(vgdev, ctx_id);
|
|
||||||
virtio_gpu_cmd_context_create(vgdev, *ctx_id, nlen, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
|
static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
|
||||||
uint32_t ctx_id)
|
uint32_t ctx_id)
|
||||||
{
|
{
|
||||||
virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
|
virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
|
||||||
virtio_gpu_ctx_id_put(vgdev, ctx_id);
|
ida_free(&vgdev->ctx_id_ida, ctx_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
|
static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
|
||||||
|
@ -261,7 +252,7 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||||
struct virtio_gpu_fpriv *vfpriv;
|
struct virtio_gpu_fpriv *vfpriv;
|
||||||
uint32_t id;
|
int id;
|
||||||
char dbgname[TASK_COMM_LEN];
|
char dbgname[TASK_COMM_LEN];
|
||||||
|
|
||||||
/* can't create contexts without 3d renderer */
|
/* can't create contexts without 3d renderer */
|
||||||
|
@ -274,7 +265,9 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
get_task_comm(dbgname, current);
|
get_task_comm(dbgname, current);
|
||||||
virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
|
id = virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname);
|
||||||
|
if (id < 0)
|
||||||
|
return id;
|
||||||
|
|
||||||
vfpriv->ctx_id = id;
|
vfpriv->ctx_id = id;
|
||||||
file->driver_priv = vfpriv;
|
file->driver_priv = vfpriv;
|
||||||
|
|
Loading…
Reference in New Issue