aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBeata Michalska <b.michalska@samsung.com>2015-03-04 09:02:49 -0500
committerInki Dae <inki.dae@samsung.com>2015-04-12 22:39:40 -0400
commite44bf6b7a50e331a1a97c23d726e39726b914dc8 (patch)
treec3c47e9ad2132264349c145e2e85852d138396f4
parente752747b98ae64ff0d1484a3b1b812fd2cafed53 (diff)
drm/exynos/ipp: Validate buffer enqueue requests
As for now there is no validation of incoming buffer enqueue request as far as the gem buffers are being concerned. This might lead to some undesired cases when the driver tries to operate on invalid buffers (wiht no valid gem object handle i.e.). Add some basic checks to rule out those potential issues. Signed-off-by: Beata Michalska <b.michalska@samsung.com> [mszyprow: rebased onto v4.0-rc1 and adapted to recent ipp changes] Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index d5ad17dfc24d..b7f1cbc46cc2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -476,6 +476,45 @@ err_clear:
476 return ret; 476 return ret;
477} 477}
478 478
479static int ipp_validate_mem_node(struct drm_device *drm_dev,
480 struct drm_exynos_ipp_mem_node *m_node,
481 struct drm_exynos_ipp_cmd_node *c_node)
482{
483 struct drm_exynos_ipp_config *ipp_cfg;
484 unsigned int num_plane;
485 unsigned long min_size, size;
486 unsigned int bpp;
487 int i;
488
489 /* The property id should already be varified */
490 ipp_cfg = &c_node->property.config[m_node->prop_id];
491 num_plane = drm_format_num_planes(ipp_cfg->fmt);
492
493 /**
494 * This is a rather simplified validation of a memory node.
495 * It basically verifies provided gem object handles
496 * and the buffer sizes with respect to current configuration.
497 * This is not the best that can be done
498 * but it seems more than enough
499 */
500 for (i = 0; i < num_plane; ++i) {
501 if (!m_node->buf_info.handles[i]) {
502 DRM_ERROR("invalid handle for plane %d\n", i);
503 return -EINVAL;
504 }
505 bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
506 min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
507 size = exynos_drm_gem_get_size(drm_dev,
508 m_node->buf_info.handles[i],
509 c_node->filp);
510 if (min_size > size) {
511 DRM_ERROR("invalid size for plane %d\n", i);
512 return -EINVAL;
513 }
514 }
515 return 0;
516}
517
479static int ipp_put_mem_node(struct drm_device *drm_dev, 518static int ipp_put_mem_node(struct drm_device *drm_dev,
480 struct drm_exynos_ipp_cmd_node *c_node, 519 struct drm_exynos_ipp_cmd_node *c_node,
481 struct drm_exynos_ipp_mem_node *m_node) 520 struct drm_exynos_ipp_mem_node *m_node)
@@ -552,6 +591,11 @@ static struct drm_exynos_ipp_mem_node
552 } 591 }
553 592
554 mutex_lock(&c_node->mem_lock); 593 mutex_lock(&c_node->mem_lock);
594 if (ipp_validate_mem_node(drm_dev, m_node, c_node)) {
595 ipp_put_mem_node(drm_dev, c_node, m_node);
596 mutex_unlock(&c_node->mem_lock);
597 return ERR_PTR(-EFAULT);
598 }
555 list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); 599 list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
556 mutex_unlock(&c_node->mem_lock); 600 mutex_unlock(&c_node->mem_lock);
557 601