diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2017-07-12 06:09:22 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2017-08-08 18:34:23 -0400 |
commit | 1899bd57570a3e610db574b57d1e7e66378aa908 (patch) | |
tree | 39c0e986685fb3ebb6f533dd8f55db16d0db9bfa | |
parent | 5669b9989eaa664cacbad6a85631550bccdad963 (diff) |
drm/exynos: forbid creating framebuffers from too small GEM buffers
Add a check if the framebuffer described by the provided drm_mode_fb_cmd2
structure fits into provided GEM buffers. Without this check it is
possible to create a framebuffer object from a small buffer and set it to
the hardware, what results in displaying system memory outside the
allocated GEM buffer.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index d48fd7c918f8..73217c281c9a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
@@ -145,13 +145,19 @@ static struct drm_framebuffer * | |||
145 | exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, | 145 | exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, |
146 | const struct drm_mode_fb_cmd2 *mode_cmd) | 146 | const struct drm_mode_fb_cmd2 *mode_cmd) |
147 | { | 147 | { |
148 | const struct drm_format_info *info = drm_get_format_info(dev, mode_cmd); | ||
148 | struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; | 149 | struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER]; |
149 | struct drm_gem_object *obj; | 150 | struct drm_gem_object *obj; |
150 | struct drm_framebuffer *fb; | 151 | struct drm_framebuffer *fb; |
151 | int i; | 152 | int i; |
152 | int ret; | 153 | int ret; |
153 | 154 | ||
154 | for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { | 155 | for (i = 0; i < info->num_planes; i++) { |
156 | unsigned int height = (i == 0) ? mode_cmd->height : | ||
157 | DIV_ROUND_UP(mode_cmd->height, info->vsub); | ||
158 | unsigned long size = height * mode_cmd->pitches[i] + | ||
159 | mode_cmd->offsets[i]; | ||
160 | |||
155 | obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); | 161 | obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); |
156 | if (!obj) { | 162 | if (!obj) { |
157 | DRM_ERROR("failed to lookup gem object\n"); | 163 | DRM_ERROR("failed to lookup gem object\n"); |
@@ -160,6 +166,12 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, | |||
160 | } | 166 | } |
161 | 167 | ||
162 | exynos_gem[i] = to_exynos_gem(obj); | 168 | exynos_gem[i] = to_exynos_gem(obj); |
169 | |||
170 | if (size > exynos_gem[i]->size) { | ||
171 | i++; | ||
172 | ret = -EINVAL; | ||
173 | goto err; | ||
174 | } | ||
163 | } | 175 | } |
164 | 176 | ||
165 | fb = exynos_drm_framebuffer_init(dev, mode_cmd, exynos_gem, i); | 177 | fb = exynos_drm_framebuffer_init(dev, mode_cmd, exynos_gem, i); |