diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_ipp.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_ipp.c | 39 |
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 5b253640cb1..73cf965d908 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); |