summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeata Michalska <b.michalska@samsung.com>2015-02-26 12:18:46 (GMT)
committerBeata Michalska <b.michalska@samsung.com>2015-02-26 13:20:53 (GMT)
commit00a9c3ed567d2e81316147eef8ad69e249dbedf6 (patch)
treebfab98a5d43ddb8f7c8d76e7d90fecab70e939ff
parentc71b7bf6b9f3ee27ae2b4d8955c1edf9eb1d9888 (diff)
downloadlinux-3.10-00a9c3ed567d2e81316147eef8ad69e249dbedf6.zip
linux-3.10-00a9c3ed567d2e81316147eef8ad69e249dbedf6.tar.gz
linux-3.10-00a9c3ed567d2e81316147eef8ad69e249dbedf6.tar.bz2
drm/exynos/ipp: Validate buffer enqueue requestsrefs/changes/90/35990/1
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. Change-Id: I117b5c566169d33fd46646068f835f48b333da73 Signed-off-by: Beata Michalska <b.michalska@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 5b25364..73cf965 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -523,6 +523,41 @@ err_clear:
return ret;
}
+static int ipp_validate_mem_node(struct drm_exynos_ipp_mem_node *m_node,
+ struct drm_exynos_ipp_cmd_node *c_node)
+{
+ struct drm_exynos_ipp_config *ipp_cfg;
+ unsigned int num_plane;
+ unsigned long min_size;
+ unsigned int bpp;
+ int i;
+
+ /* The property id should already be varified */
+ ipp_cfg = &c_node->property.config[m_node->prop_id];
+ num_plane = drm_format_num_planes(ipp_cfg->fmt);
+
+ /**
+ * This is a rather simplified validation of a memory node.
+ * It basically verifies provided gem object handles
+ * and the buffer sizes with respect to current configuration.
+ * This is not the best that can be done
+ * but it seems more than enough
+ */
+ for (i = 0; i < num_plane; ++i) {
+ if (!m_node->buf_info.handles[i]) {
+ DRM_ERROR("invalid handle for plane %d\n", i);
+ return -EINVAL;
+ }
+ bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
+ min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
+ if (min_size > m_node->buf_info.size[i]) {
+ DRM_ERROR("invalid size for plane %d\n", i);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
static int ipp_put_mem_node(struct drm_device *drm_dev,
struct drm_exynos_ipp_cmd_node *c_node,
struct drm_exynos_ipp_mem_node *m_node)
@@ -595,7 +630,6 @@ static struct drm_exynos_ipp_mem_node
DRM_ERROR("failed to get addr.\n");
goto err_clear;
}
-
size = exynos_drm_gem_get_size(drm_dev,
qbuf->handle[i], c_node->filp);
if (!size) {
@@ -614,6 +648,9 @@ static struct drm_exynos_ipp_mem_node
}
m_node->buf_info = buf_info;
+ if (ipp_validate_mem_node(m_node, c_node))
+ goto err_clear;
+
list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
mutex_unlock(&c_node->mem_lock);